Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

MikroC e libreria I2C

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[11] Re: MikroC e libreria I2C

Messaggioda Foto Utentegiovannispina » 4 mar 2014, 1:34

TardoFreak ha scritto:Quindi confermi che è una cag ... ehm ... un compilatore , diciamo, migliorabile. :roll:
Alla faccia della compatibilità con ANSI C.
Con il C18 lo fai senza problemi. -:-


Rifletti.
Se è così un motivo c'è. Se tutte le variabili locali fossero statiche riserveresti dello spazio inutile in RAM.
Se poi tu vuoi che le variabili siano statiche, per casi particolare come il tuo, allora in quel caso tu puoi specificarlo.

edit: l'unico modo sarebbe quello di fare uno stack a parte per i parametri così da verificarne l'integrità, ma troppe seghe per delle mcu così scarse.
Avatar utente
Foto Utentegiovannispina
126 1 3
 
Messaggi: 43
Iscritto il: 27 lug 2013, 12:31

0
voti

[12] Re: MikroC e libreria I2C

Messaggioda Foto UtenteTardoFreak » 4 mar 2014, 1:39

Qui si parla di puntatori, non di variabili statiche.

Rileggiti il sorgente please.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[13] Re: MikroC e libreria I2C

Messaggioda Foto Utentegiovannispina » 4 mar 2014, 1:48

TardoFreak ha scritto:Qui si parla di puntatori, non di variabili statiche.

Rileggiti il sorgente please.


Buona notte. Le variabili locali, cioè anche i parametri (in questo caso il puntatore), le devi fare statiche affinché non siano perse. Se facessi un programma in assembly avresti solo due soluzioni:

1) usare i registri temporanei RX.
2) allocare uno spazio di memoria statico in RAM.

Questo è quello che succede. Solo che nel C del C18 non te ne rendi conti finché non guardi il listing in asm. Sul mC tu teoricamete dovresti specificarlo. Lo so che è una "limitazione", ma queste cose non sono fatte a caso.
Avatar utente
Foto Utentegiovannispina
126 1 3
 
Messaggi: 43
Iscritto il: 27 lug 2013, 12:31

0
voti

[14] Re: MikroC e libreria I2C

Messaggioda Foto UtenteTardoFreak » 4 mar 2014, 1:55

Ok, ti va di coglionarmi.

Io parlo di puntatori e tu di melanzane. :roll:

Addio. O_/
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

1
voti

[15] Re: MikroC e libreria I2C

Messaggioda Foto Utentec1b8 » 4 mar 2014, 10:18

Buongiorno, ieri sera era un tantino cotto e stavo lavorando, ho letto i vari passaggi in modo veloce ma qualche cosa mi ha lasciato perplesso. Questa mattina li ho riletti e vorrei chiedere a Foto Utentegiovannispina alcune delucidazioni su un paio di aspetti che mi lasciano perplesso.

Cominciamo da questa:
giovannispina ha scritto:I2C_Rd aspetta finché non viene letto il messaggio ...

Ammetto di aver studiato I2C da autodidatta ma io ho compreso che:
- a generare il segnale di clock nel bus è sempre il master (il mio PIC nell'esempio)
- quando il master vuole comunicare con uno slave invia l'indirizzo dello slave (7 impulsi di clock), un bit di lettura/scrittura (un impulso di clock) e legge (al nono impulso di clock) se lo slave risponde con ACK o con NACK
- quando il master vuole scrivere sullo slave, genera 9 implusi di clock: i primi 8 per inviare i dati allo slave, il 9° per leggere se lo slave risponde con ACK o con NACK
- quando il master vuole leggere dallo slave, genera 9 impulsi di clock: con i primi 8 legge il segnale dati del bus, con il 9° impulso di clock il master genera un segnale di ACK o NACK

Da questo ho interpretato (mia interpretazione personale) che sia sempre il master a governare il bus e per nessun motivo esso possa bloccarsi, al più potrebbe leggere un segnale ACK o NACK dallo slave in alcune condizioni e dovrebbe agire di conseguenza. Ma mai bloccarsi.
In particolare nella read, come potrebbe il master sapere se lo slave è o non è connesso? Quando uno slave non è presente il master leggerà tutti '1' (resistenze di pull-up presenti nel bus), stessa condizione che potrebbe incontrare se lo slave fosse presente e rispondesse al master con tutti '1'.
Come fa quindi la I2C_Rd() a capire quando ha ricevuto un messaggio?
Chi e come comunica al master che il messaggio ricevuto (gli 8 bit letti) è corretto (è lui a generare ACK o NACK)?

Il secondo aspetto che non mi è chiaro è il seguente:
giovannispina ha scritto:Sì, in mC, in assenza di uno stack riservato, lo spazio delle variabili locali (parametri compresi) viene riutilizzato da funzione a funzione,

Provo a fare un esempio per vedere se ho compreso:
Codice: Seleziona tutto
void func_a(void) {
    int pippo;
    // qui il codice fa qualche cosa utilizzando anche pippo
}
void func_b(void) {
    int topo;
    // qui il codice fa qualche cosa utilizzando anche topo
}

Tu dici che il compilatore potrebbe riutilizzare lo stesso spazio di memoria per salvare le variabili locali pippo e topo, a meno di non dichiarare le variabili locali come statiche.
Quindi se pippo viene salvata all'indirizzo (esempio) 0x123, anche la topo potrebbe essere salvata in 0x123 sovrascrivendo il contenuto di pippo.
Ero convinto che qualsiasi compilatore si comportasse il questo modo, mi stupirei del contrario. E sono sicuro, anche se non ho mai controllato, che anche il C18 si comporta così.
Ma il caso portato come esempio da Foto UtenteTardoFreak è una situazione totalmente diversa dall'esempio che ho appena scritto. Il suo caso è simile (attenzione solo simile) a questo:
Codice: Seleziona tutto
void func_a(void) {
    int pippo;
    // qui il codice fa qualche cosa utilizzando anche pippo
}
void func_b(void) {
    int topo;
    topo=0;
    while (topo<10) {
        // qui il codice fa qualche cosa;
        func_a();
        topo++;
    }
}

In questo semplice esempio se topo e pippo venissero posizionate dal compilatore allo stesso indirizzo di memoria la func_b non funzionerebbe a dovere perché:
- quando termina la func_a topo potrebbe essere già maggiore di 10 e quindi il while termina subito, anche dopo un solo ciclo: Errore!
- quando termina la func_a topo ha sempre un valore inferiore a 9 con conseguente loop della func_b: Errore!
In questo caso un compilatore serio dovrebbe garantire la separazione degli indirizzi di memoria tra le variabili locali della func_b e le variabili locali della func_a.
Nell'esempio di Foto UtenteTardoFreak a mio avviso la situazione è ancora più complessa perché il parametro passato è un puntatore a variabile (magari definita come globale) e questo puntatore non può, non deve mai cambiare, qualsiasi sia il numero di chiamate nidificate che vengono eseguite.
Concludendo: ho interpretato male quanto volevi affermare con?
giovannispina ha scritto:Sì, in mC, in assenza di uno stack riservato, lo spazio delle variabili locali (parametri compresi) viene riutilizzato da funzione a funzione,

Mi spieghi cosa intendevi?
Grazie.
Fabio
Avatar utente
Foto Utentec1b8
3.595 3 8 13
G.Master EY
G.Master EY
 
Messaggi: 1770
Iscritto il: 15 gen 2009, 15:23

1
voti

[16] Re: MikroC e libreria I2C

Messaggioda Foto Utenteobiuan » 4 mar 2014, 11:51

Foto UtenteTardoFreak, quando scrivi:

"// Cucu', pippo non punta piu'"

intendi che pippo è null o che punta a una zona di memoria con contenuto cambiato rispetto a quello che dovrebbe?

perché se pippo è null mi sembra evidente che è il compilatore a sbagliare, se invece è il contenuto che è cambiato, allora direi che è possibile.

EDIT: anche se pippo è null o ha un valore diverso, in realtà potrebbe essere che semplicemente hai sforato la profondità di stack e quindi stai sovrascrivendo le variabili locali con altro.
_______________________________________________________
Gli oscillatori non oscillano mai, gli amplificatori invece sempre

Io HO i poteri della supermucca, e ne vado fiero!
Avatar utente
Foto Utenteobiuan
5.894 3 10 13
Master
Master
 
Messaggi: 980
Iscritto il: 23 set 2013, 23:45

0
voti

[17] Re: MikroC e libreria I2C

Messaggioda Foto UtenteTardoFreak » 4 mar 2014, 12:36

Intendo dire che non puntava più dove doveva puntare. Probabilmente da un' altra parte of forse sarebbe potuto anche essere null.
Resta comunque il fatto che un compilatore non si può permettere un bug del genere, almeno per me che ci lavoro, questi sono bug imperdonabili ed il compilatore non può essere utilizzato. [-X
E' ovvio che nei PIC18 lo stack deve essere sintetizzato perché non esiste un vero stack (c'è solo uno stack interno a 32 livelli per le subroutines) ma i compilatori seri lo fanno, e pure bene. E, detto fra noi, non serve essere dei Wozniak per farlo.

P.S.: Alle cazzate che scrive Foto Utentegiovannispina non rispondo più perché si vede lontano un chilometro che di compilatori non capisce una mazza. :mrgreen:
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[18] Re: MikroC e libreria I2C

Messaggioda Foto Utentegiovannispina » 4 mar 2014, 12:37

c1b8 ha scritto:Buongiorno, ieri sera era un tantino cotto e stavo lavorando, ho letto i vari passaggi in modo veloce ma qualche cosa mi ha lasciato perplesso. Questa mattina li ho riletti e vorrei chiedere a Foto Utentegiovannispina alcune delucidazioni su un paio di aspetti che mi lasciano perplesso.

Cominciamo da questa:
giovannispina ha scritto:I2C_Rd aspetta finché non viene letto il messaggio ...

Ammetto di aver studiato I2C da autodidatta ma io ho compreso che:
- a generare il segnale di clock nel bus è sempre il master (il mio PIC nell'esempio)
- quando il master vuole comunicare con uno slave invia l'indirizzo dello slave (7 impulsi di clock), un bit di lettura/scrittura (un impulso di clock) e legge (al nono impulso di clock) se lo slave risponde con ACK o con NACK
- quando il master vuole scrivere sullo slave, genera 9 implusi di clock: i primi 8 per inviare i dati allo slave, il 9° per leggere se lo slave risponde con ACK o con NACK
- quando il master vuole leggere dallo slave, genera 9 impulsi di clock: con i primi 8 legge il segnale dati del bus, con il 9° impulso di clock il master genera un segnale di ACK o NACK

Da questo ho interpretato (mia interpretazione personale) che sia sempre il master a governare il bus e per nessun motivo esso possa bloccarsi, al più potrebbe leggere un segnale ACK o NACK dallo slave in alcune condizioni e dovrebbe agire di conseguenza. Ma mai bloccarsi.
In particolare nella read, come potrebbe il master sapere se lo slave è o non è connesso? Quando uno slave non è presente il master leggerà tutti '1' (resistenze di pull-up presenti nel bus), stessa condizione che potrebbe incontrare se lo slave fosse presente e rispondesse al master con tutti '1'.
Come fa quindi la I2C_Rd() a capire quando ha ricevuto un messaggio?
Chi e come comunica al master che il messaggio ricevuto (gli 8 bit letti) è corretto (è lui a generare ACK o NACK)?


Buon giorno :)
A dire il vero non conosco molto bene le interfacce I2C, io ho semplicemente guardato il sorgente di read:

Codice: Seleziona tutto
unsigned short I2C1_Rd(unsigned short ack) {
unsigned short tmp;                                 
  PIR1.SSPIF = 0;                 
  SSPCON2.RCEN = 1;           
  while (!PIR1.SSPIF) ;

  tmp = SSPBUF;
  if (ack == 0)
    SSPCON2.ACKDT = 1;
  else
    SSPCON2.ACKDT = 0;
   
  PIR1.SSPIF = 0;                 
  SSPCON2.ACKEN = 1;         
  while (!PIR1.SSPIF) ;
 
  return tmp;
}


Sembra che lui controlli ogni volta il bit SSPIF probabilmente per verificare se il dato è stato mandato/ricevuto. Togliere il while o mettere un timeout dovrebbe risolvere il problema.
Cercando sul forum di mE ho trovato questo:
Basically there is an issue with the device (hardware) setting its interrupt flag bit and the mikroE library uses this interrupt flag as the most efficient method to arriving at a decision. Any PIC device which does not have the hardware bug as detailed in the errata for your PIC of choice, will work without any problem and work in the most efficient way.

1. "our function" simply meant any solution which any other person may write.

2. This is NOT a compiler bug NOR is it a bug with the mikroE source library function. There is no bug-fix to the software, mikroE may well be kind enough to provide their source code in circumstances like this (as has been done) to enable the user of a specific device with a specific hardware bug to individually solve a local problem and forge ahead on their project.

3. It is a documented failure with the microchip PIC of your choice! Microchip have included (as pointed to by zristic) this item in their errata document which is where any reader/user will find the delta between device intend specification (as per design VHDL / Simulation / drawing board etc) and the real world manufactured end product.

It has (for reason of scrap cost reduction) become acceptable for manufacturers to sell devices which DO NOT perform as the main data sheet say's so. So long as they provide the information on any short-fall and make that information available prior (not always the case if a designer is using the very first IC release, we end up being the bug reports to the chip manufacturers) to purchase.

they have been doing this for years and years within the electronics industry between manufacturers and end product designers, for the obvious reason of cost reduction that would otherwise result from throwing what are actually defective devices in the bin. So long as the main core works correctly and there is a way to work around the KNOWN defect its a case of buyer beware!

in the micro-controller world it is so often the third party company which finds itself being blamed for a device not performing as originally documented or expected. If mikroE do a global change to this particular function i.e. remove the dependency on interrupt flag bit, then yes it solves the issue for this particular PIC, however it then makes the function less robust and less efficient for ALL PIC devices and deviates from the target product core design specification. In this instance it really is not fair to place the blame and resulting requirement for a solution at the door of mikroE, that said mikroE have provided a path to A solution which is admirable and in keeping with the customer support anyone can expect from them.

hope that helps you or anyone else understand who is actually to blame!

And i hope you marketing people out there are reading this too... stop selling us broken IC's on the off chance that people wont use the defective hardware blocks!!!


Se cercavi bene, sullo stesso post del 2008, ti diceva perché non funzionava e ti davano pure il sorgente di Read per farne una tua implementazione senza while per device con questo particolare bug hardware (peraltro segnalato dalla stessa Microchip sull'errata document). Non c'è bug-fix a questo problema, in generale quel flag andrebbe SEMPRE settato prima di fare qualsiasi tipo di azione o scrivere su SSPBUF.

Prova e vedi se va, magari al posto del while puoi mettere un delay giusto per sicurezza, in modo tale da dare abbastanza tempo al device di sincronizzarsi. :)
Avatar utente
Foto Utentegiovannispina
126 1 3
 
Messaggi: 43
Iscritto il: 27 lug 2013, 12:31

Precedente

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 22 ospiti