Cambiare velocità i2c e tempo di low

Salve a tutti,

per fare dei test ho la necessità di cambiare la frequenza con cui il mio arduino Due trasmette in i2c.
Volendo controllare direttamente la frequenza e sapendo che è determinata dalla seguente formula:

SCL frequency = (CPU Clock frequency)/(16 + 2 x (TWBR) PrescalerValue))

Ho abbozzato questo codice:

#include <Wire.h>
byte x=0;
void setup(){
Wire.begin();

TWBR=18;

}

void loop()
{


Wire.beginTransmission(0x04); //indirizzo casuale

Wire.write(x); //scrivo un valore casuale
Wire.endTransmission();




}

L’indirizzo del dispositivo Slave è casuale (così come il byte che trasmetto), di fatto non ho neanche attaccato un dispositivo Slave fisico, mi sto limitando a guardare le forme d’onda con l’oscilloscopio sui PIN 21 (SCL) e 20 (SDA).
Il problema è che il programma non viene compilato, TWBR non viene riconosciuto come indirzzo del registro, devo includere qualche altra libreria oltre alla wire.h?

Inoltre lo step successivo una volta modificata la frequenza era quello di cambiare il duty cycle, vorrei aumentare il tempo di LOW del segnale di CLOCK: da datasheet ho già visto si può fare modificando il registro TWI_CWGR, ma come sopra non viene riconosciuto come registro…

Help

Da dove hai ricavato i mnemonici dei registri ? Dal datasheet del processore ? Perché ... TWBR è roba relativa all'architettura AVR ... non mi sembra relativo all'architettura del SAM usato sulla DUE.

Guglielmo

gpb01: Da dove hai ricavato i mnemonici dei registri ? Dal datasheet del processore ?

Guglielmo

Ciao Guglielmo,

dal datasheet del processore montato su arduino Due: Atmel SAM 3x8E

Sul Sam non esiste il registro TWBR, quello è sul Atmega 328.

@Astro: come sempre, metre tu scrivevi io modificavo il mio post :D :D :D ... la solita telepatia ;)

@Povelz: guardati il datasheet che ti ho linkato da pag. 708 in poi ...

Guglielmo

astrobeed: Sul Sam non esiste il registro TWBR, quello è sul Atmega 328.

Grazie mille,

effettivamente TWBR l'avevo visto dalla sezione sulla libreria Wire qui sul sito di arduino (che era riferita al Atmega), il secondo registro invece l'ho preso corretto dal datasheet!

Riprovo,

grazie

Non ho risolto :confused:

Ecco il codice:

#include <Wire.h>
byte x=0;
void setup(){
Wire.setClock(400000); 
Wire.begin();

TWI_CWGR=2;



}

void loop()
{


Wire.beginTransmission(0x04); //indirizzo casuale

Wire.write(x); //scrivo un valore casuale
Wire.endTransmission();




}

L’errore è sempre: “‘TWI_CWGR’ was not declared in this scope”

A questo punto (il nome del registro che devo modificare dovrebbe essere corretto ora) il problema è:

Come modifico il valore di un registro? Devo passare all’assembly?

Grazie mille

Povelz: L'errore è sempre: "'TWI_CWGR' was not declared in this scope"

Devi andare a "sbirciare" dentro il core della DUE per vedere come viene assegnato quel registro, quasi sicuramente il nome è lo stesso, però potrebbe essere parte di una struttura, altamente probabile, pertanto devi vedere come è composta la struttura.

astrobeed: Devi andare a "sbirciare" dentro il core della DUE per vedere come viene assegnato quel registro, quasi sicuramente il nome è lo stesso, però potrebbe essere parte di una struttura, altamente probabile, pertanto devi vedere come è composta la struttura.

Mi aiuteresti con un link?

Sono un pò in confusione, pensavo fosse quello sul datasheet il nome del registro...

Nel “core” viene modificato usandolo in questo modo:

twi->TWI_CWGR = (ulCkDiv << 16) | (ulClDiv << 8) | ulClDiv ;

Devi aprire il “core” della DUE e guardare i files relativi a Wire

Guglielmo

… prova a guardare dentro questi che ho estratto dal core e che ti allego :wink:

Guglielmo

Wire.cpp (11.5 KB)

Wire.h (3.21 KB)

twi.h (3.79 KB)

Una considerazione personale, lo standard I2C prevede due velocità, 100 kHz e 400 kHz, esiste anche una modalità high speed a 3.4 Mbps però serve un hardware specifico per usarla e se serve più velocità, di quella offerta dai 400 kHz (circa 180-200 kbps reali) meglio andare su bus più efficienti. In pratica non ha alcun senso impostare velocità I2C diverse da 100 kbps o 400 kbps, il modo high speed non è supportato dal Sam, per cambiare la velocità della I2C si usa Wire.setClock(100000) oppure Wire.setClock(400000), dovrebbe funzionare anche sulla DUE, non posso confermartelo perché non uso questa scheda e non ho installato il suo core nel IDE.

gpb01: ... prova a guardare dentro questi che ho estratto dal core e che ti allego ;)

Guglielmo

Grazie mille, l'ho trovato!

astrobeed: Una considerazione personale, lo standard I2C prevede due velocità, 100 kHz e 400 kHz, esiste anche una modalità high speed a 3.4 Mbps però serve un hardware specifico per usarla e se serve più velocità, di quella offerta dai 400 kHz (circa 180-200 kbps reali) meglio andare su bus più efficienti. In pratica non ha alcun senso impostare velocità I2C diverse da 100 kbps o 400 kbps, il modo high speed non è supportato dal Sam, per cambiare la velocità della I2C si usa Wire.setClock(100000) oppure Wire.setClock(400000), dovrebbe funzionare anche sulla DUE, non posso confermartelo perché non uso questa scheda e non ho installato il suo core nel IDE.

Il problema per la mia applicazione non è tanto andare ancora più veloce, quanto cercare di separare di più i fronti di discesa/salita tra SCL e SDA, per evitare che durante la trasmissione dei bit DATA per parassitismi etc si crei una codifica di START o STOP che mi "taglia" il messaggio. Per quello cercavo di "giocare" con le forme d'onda!

Povelz: Il problema per la mia applicazione non è tanto andare ancora più veloce, quanto cercare di separare di più i fronti di discesa/salita tra SCL e SDA,

Se hai di questi problemi vuol dire che la linea I2C lavora male a livello hardware, ovvero troppa capacità parassita e/o resistenza di pullup troppo alta. Non esiste che ti metti a giocare con la durata dei periodi I2C visto che la tempistica è fondamentale per i device slave, se la alteri poi non capiscono quello che gli mandi a meno che non lo alteri allo stesso modo anche su loro. Devi risolvere la questione a livello hardware, non software.