Hallo, ich versuche gerade, meinen Quadcopter (Multiwii, ATMega328p) per I2C mit GPS-Daten zu versorgen. Dazu habe ich mir bereits vor einiger Zeit ein entsprechendes Programm für einen ATTiny2313 gestrickt, dass über den UART NMEA-Daten einliest, parst und per TWI zur Verfügung stellt. In einem Testszenario vor einiger Zeit klappte das auch noch prima, schließe ich den Controller jetzt aber an den vorhandenen I2C-Bus an, steigen alle anderen Sensoren (Gyro, Acc, Mag, Baro) aus; ich muss dazu sagen, dass der Bus mit 3,3V betrieben wird. Anscheinend legt mein ATTiny jedoch aktiv auf SCL und SDA sein VCC von 5V, so dass der Bus natürlich aus den Fugen gerät. Ich verwende den I2C-Code von Donald Blake und habe folgende Stelle im Code in Verdacht: https://github.com/wertarbyte/tiny-gps/blob/master/usiTwiSlave.c#L316 So wie ich es verstehe, wird damit doch 5V auf den Bus gelegt? Leider kenne ich mich mit der ganzen USI-Geschichte nicht sehr gut aus, vielleicht hat jemand mit mehr Ahnung ja eine Idee, woran es liegen könnte. Beste Grüße Stefan
Stefan Tomanek schrieb: > schließe ich den Controller jetzt aber an den vorhandenen I2C-Bus an, > steigen alle anderen Sensoren (Gyro, Acc, Mag, Baro) aus Der Controller muss, wenn er nix zu sagen hat, hochohmig am I²C-Bus hängen.
Ja, das ist mir schon klar. Laut Dokumentation verhalten sich SCL und SDA auch als Open-Collector-Ausgänge, ziehen den Bus also entweder gegen GND oder lassen ihn "floaten" (und durch die Pull-Ups auf HIGH gehen). Deshalb erstehe ich die von mir genannten Code-Stellen auch nicht, die j anscheinend die Ports auf HIGH legen, noch bevor der TWI-Modus aktiviert wurde.
Bei den Kommentaren zu diesem Code ist mal mindestens die Funktion von DDR und Port Register vertauscht. Bei einer Open Collector Ansteuerung dient das DDR-Register als invertierter Output, die Port Pins müssen immer 0 sein. DDR = 1 bedeutet Ausgang auf 0 ziehen, DDR = 0 bedeutet Ausgang offen, also 1 durch Pullup wenn kein anderer Port am Bus 0 ist. Der Programmierer hat also gar nicht verstanden, wie der USI funktioniert. Dass es zu Problemen mit anderen Slaves kommt, ist mehr als wahrscheinlich.
Hat jemand einen anderen USI/TWI-Code zur Hand, der wirklich auch mit mehreren Slaves funktioniert? :-)
Atmel Application Note AVR312 - Da stimmen die Kommentare zwar auch nicht, aber mindestens die Initialisierung ist richtig.
Sicher? Ich habe den Code hier gerade vor mir (USI_TWI_Slace.c):
1 | void USI_TWI_Slave_Initialise( unsigned char TWI_ownAddress ) |
2 | { |
3 | Flush_TWI_Buffers(); |
4 | |
5 | TWI_slaveAddress = TWI_ownAddress; |
6 | |
7 | PORT_USI |= (1<<PORT_USI_SCL); // Set SCL high |
8 | PORT_USI |= (1<<PORT_USI_SDA); // Set SDA high |
9 | DDR_USI |= (1<<PORT_USI_SCL); // Set SCL as output |
10 | DDR_USI &= ~(1<<PORT_USI_SDA); // Set SDA as input |
kommt das nicht aufs gleiche raus? Zumindest habe ich auch mit dieser Initialisierung VCC am SDA-Pin.
Ups, ich habe glaube ich Software TWI und USI verwechselt, vergiss meine Beiträge.
Stefan Tomanek schrieb: > kommt das nicht aufs gleiche raus? Zumindest habe ich auch mit dieser > Initialisierung VCC am SDA-Pin. Nimm mal probeweise die beiden Pull-Up Widerstände für SCL und SDA raus und miss noch mal.
Die Widerstände hängen am Master, d.h. auch wenn der Tiny gar nicht angeschlossen ist, pusht er die Spannung selbst hoch.
Hat jemand noch eine Idee? Ich habe mir noch ein paar andere USI/TWI-Libs angeguckt, aber es sieht eigentlich überall gleich aus, so auch in der Lib von Martin Junghans (u.a. http://www.das-labor.org/svn/microcontroller/src-atmel/lib/i2c/trunk/usi-twi_slave/usiTwiSlave.c):
1 | void usiTwiSlaveInit() |
2 | { |
3 | // In Two Wire mode (USIWM1, USIWM0 = 1X), the slave USI will pull SCL |
4 | // low when a start condition is detected or a counter overflow (only |
5 | // for USIWM1, USIWM0 = 11). This inserts a wait state. SCL is released |
6 | // by the ISRs (USI_START_vect and USI_OVERFLOW_vect). |
7 | DDR_USI |= (1 << PORT_USI_SCL) | (1 << PORT_USI_SDA); // Set SCL and SDA as output |
8 | PORT_USI |= (1 << PORT_USI_SCL); // Set SCL high |
9 | PORT_USI |= (1 << PORT_USI_SDA); // Set SDA high |
10 | DDR_USI &= ~(1 << PORT_USI_SDA); // Set SDA as input |
11 | USICR = |
12 | (1 << USISIE) | // Enable Start Condition Interrupt |
13 | (0 << USIOIE) | // Disable Overflow Interrupt |
14 | (1 << USIWM1) | (0 << USIWM0) | // Set USI in Two-wire mode, no USI Counter overflow hold |
15 | (1 << USICS1) | (0 << USICS0) | (0 << USICLK) |// Shift Register Clock Source = external, positive edge 4-Bit Counter Source = external, both edges |
16 | (0 << USITC); // No toggle clock-port pin |
17 | USISR = (1 << USI_START_COND_INT) | (1 << USIOIF) | (1 << USIPF) | (1 << USIDC); // clear all interrupt flags and reset overflow counter |
18 | } |
Selbst wenn das Problem mit der Unterschiedlichen Spannung am Bus nicht wäre (3,3V vs. 5V) würde die initialisierung deses Slaves doch jeden laufenden Transfer auf dem Bus zerschlagen?
OK, ich muss alles zurückziehen. Die Override-Register sorgen schon für das Open-Collector-Verhalten, sobald der USI-Modus geschaltet ist. Woran lag es schlussendlich? An der Taktfrequenz. Mit 8MHz kann der ATTiny mit dem Bus schritt halten und fügt sich harmonisch ein. Danke trotzdem für alle, die mitgeholfen haben :-)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.