Software C per la TWI di Atmel

Sono ormai mesi che provo varie implementazioni per l'uso del bus TWI di Atmel. Si lo so c'è la twi di arduino ad oggetti, ma io uso solo il C. Anche guardando il codice di Arduino si vede come le cose possono non andare nel verso giusto. In generale quando si usa un ciclo while (condizione); si deve avere la certezza assoluta che questa condizione si verifichi prima o poi, o meglio se la condizione non si verifica entro un certo tempo bisogna uscire dal while e prendere delle decisioni del tipo, bus twi guasto o altro. Tutto il codice che ho sperimentato si porta appresso questo problema, sto cercando di ovviare, ma mi sembra impossibile poter realizzare un software twi a prova di loop infinito.

Per chi non ha conoscenza del bus, faccio un breve riepilogo.

Per semplicità espositiva lo slave è il sensore di temperatura se95 di NTX, il master è
Arduino board 2009, l'IDE non è arduino e uso solo avrlibc.

Prima di poter usare il bus, bisgna scegliere la modalità operativa in base alle operazioni che vogliamo compiere, le più importanti modalità operative sono MT e MR, rispettivamente Master Trasmit e Master Receiver. Indifferentemente dalla modalità per iniziare si deve porre il bus nello stato di START, e solo dopo avere avuto conferma che il bus è nello stato START possiamo fare il prossimo passo. Per porre il bus in stato di START possiamo usare il seguente codice:

    // send START condition
    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

    // wait until transmission completed
    while(!(TWCR & (1<<TWINT));

Lo start vede il bit TWINT a 1, quando il bus entra nello stato di START l'hardware pulisce il bit TWINT, quindi il while attende che si verifichi questa condizione. Se questa condizione non dovesse
verificarsi il programma rimane bloccato nel while, e se ci sono altre parti del programma che girano grazie agli interrupt queste continueranno a funzionare e questo non sempre è un bene.

Il codice per avviare lo start può essere leggermente diverso nel caso si scelga di usare l'interrupt
twi che fa capo al bit TWIE e al vettore di interrupt TWI_vect.

Segue un esempio di START con interrupt abilitato:

    // send START condition, enable interrupt (TWIE) and enable ACK (TWEA)
    TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA);

    // wait until transmission completed
    while(!(TWCR & (1<<TWINT))

Come da commento, oltra ad avvirare lo start si abilita l'interrupt e l'ACK, ma rimane sempre
il problema del while. Inoltre se ci sono gli interrupt abilitati, dopo uno start il codice esegue continuamente la ISR, cioè entra ed esce e poi rientra nella ISR all'infinito.

In parte ho risolto il problema del while, ma ho dovuto aggiungere molto codice ridondante e non sono per niente contento. Comunque ora se stacco l'se95 dal bus il codice continua a girare senza loop infiniti, ma se lo ricollego non riprende a funzionare.

Tra le altre cose è difficilissimo fare debug del bus TWI, specie con la ISR abilitata.

Se avete consiglio, link, critiche ecc fatevi sentire perchè non vedo l'ora di leggervi.

Ciao.

Ma il TWI (Two-wire Interface) non é un altro nome per il I2C?
Ciao Uwe

uwefed:
Ma il TWI (Two-wire Interface) non é un altro nome per il I2C?
Ciao Uwe

Proprio quello è, l'i2c di philips.

I problemi che ho non ho capito da cosa dipendono.
Quando invio l'indirizzo per entrare in master trasmit mi devo aspettare che l'se95 invii il bit ACK al
9° bit e quindi lo stato del bus deve essere MT_SLA_ACK cioè 0x18 ed invece alle volte l'se95 non risponde al 9° bit e lo stato è MT_SLA_NACK 0x20.

Uso le resistenze di pullup interne che per caso sono queste che rompono, ma con la gestione in poling della twi invece funziona tutto, con questa via interrupt c'è questo comportamento bizzarro.

Ciao.

Praticamente vuoi emulare la I2C senza l' uso della libreria ne il HW dedicato?
Sttenzione che l' uscita deve essere un open collector e metti pure delle resistenze pullup piú piccole, qualcosa tra 4,7 e 2 kOhm.
Ciao Uwe