Gut, wer viel misst misst Mist. Kenne ich. Trotzdem hatte ich nach Einführung der Bereitschaftsprüfung beim I²C-lesen (danke Klebwax für den Ausdruck "ACK-Polling") mal die benötigten Zeiten wissen wollen. Hier sind diese Werte, bei denen vier (4) Bytes aus dem I²C-Puffer des Slaves gelesen wurden, natürlich mit den Zeiten für den zugehörigen Overhead :
Code:
I²C Δt1 Δt2
kHz tupsi tupsi ( 1 tupsi sind 50 µs)
100 22..26 14..17
400 13..15 4..6
800 11..13 2..4
Δt1 ist Messung EINSCHLIEßLICH UART-Ausgabe, Δt2 ist das wirklich interessierende Ding – NUR I²C-Übertragung, siehe Code im Kasten unten. Die Zeitangabe ist in tupsi, meiner Board-Zeiteinheit von 50 µs. Die angegebene I²C-Rate ist der Wert aus "#define SCL_CLOCK" in meiner twima_hze.c, real sind also z.B. 800 kHz; wegen der Rundung beim Berechnen von TWBR = ((F_CPU/SCL_CLOCK)-16)/2; sind das schon 833 kHz. Hier ist dann TWBR 4 -- und damit deutlich unter der verbreiteten Grenzangabe in den Libraries von 10. Trotzdem läuft die Chose bei mir klaglos.
Woher dieser Grenzwert stammt weiß ich noch nicht. Ebenso ist (mir, noch) unklar das Timing der I²C-Lese-Hardware der 8bittigen ATMEL Megas. Aber - abwarten.
Code:
// ============================================================================= =
// Lesen Daten von der Motorplatine, Slaveadresse 0x82/130dez;
// Ausgabe auf UART0
// - - - - - - - - - - - - - - - -
void I2CMrid ( void ) // I2C, Motordaten auslesen über I²C
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{ //
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
u8 ipwm12 = 99; // Read-back-Byte vom Slave
u8 soll12 = 98;
u8 ipwm34 = 97;
u8 soll34 = 96;
u8 laddr = 0x33; // Leseaddresse = 51dez
u8 i2cttt = 0; // Lokal gemessene Zeit
i2ctim = 0; // Sendedauer - siehe ~com~.h
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Lesen (read back) vom Slave ... mit der Routine aus fleury´s lib
i2c_start_wait(SLAVE_MoCo+I2C_WRITE); // set device address and write mode
i2c_write( laddr ); // write address = laddr, das angepeilte Byte
i2c_stop(); //
while ((i2c_start(SLAVE_MoCo+I2C_READ))) {} // Slave bereit zum Lesen?
//while ((i2c_rep_start(SLAVE_MoCo+I2C_READ))) {}// Slave bereit zum Lesen?
//i2c_rep_start(SLAVE_MoCo+I2C_READ); // set device address and read mode
ipwm12 = i2c_readAck(); // Bytes lesen... ab laddr = 0x33/51
soll12 = i2c_readAck(); //
ipwm34 = i2c_readAck(); //
soll34 = i2c_readNak(); // letztes Byte lesen, NAK
i2c_stop(); //
i2cttt = i2ctim; // Timerwert übernehmen
if ( ipwm12 <= 1 ) i2cRct++; // Wenn Lesebyte fehlerhaft scheint
// I2C-ERRorcounter hochzählen
// - - - - - - - - - - - - - - - - - - - -
// Ausgabe der Daten über UART - Fortsetzung der Startsequenz
uputs0 ("\r\tI²Crd # "); // Kennung dieser Routine
uputs0i(SLAVE_MoCo+I2C_READ); uputs0("/"); uputs0i ( laddr );
uputs0("\tP12 "); uputs0u(ipwm12);
uputs0("\tsp1 "); uputs0u(soll12);
uputs0("\tP34 "); uputs0u(ipwm34);
uputs0("\tsp4 "); uputs0u(soll34);
//uputs0("\ttmr "); uputs0u(i2ctim); // Timerwert ausgeben MIT UART
uputs0("\tttt "); uputs0u(i2cttt); // Gestoppte Zeit NUR I2C
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// uputs0("\tEnde I2CMrid");
return; //
}
// === Ende void I2CMrid ( void )
// ============================================================================= =
Overhead rausmessen, sprich: NUR die reine Datenübertragung zu messen, wäre möglich. Aber wozu? Immerhin geben diese Werte einen Anhalt über den tatsächlichen Zeitaufwand bei mittelschnellem I²C.
Lesezeichen