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 :
Δ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.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
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.
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.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 ) // ============================================================================= =







Zitieren

Lesezeichen