Hallo zusammen,
ich mache gerade meine ersten Gehversuche mit dem I2C-Bus an einem
ATmega32 und bin bis jetzt schon sehr zufrieden. Im Moment habe ich aber
eine Phase, wo ich etwas ratlos bin.
Die folgende Routine soll nach allen Adressen am I2C scannen:
1 | /* In main: */
|
2 | i2c_init();
|
3 |
|
4 | /* Check for I2C devices */
|
5 | for(uint16_t i=0x00; i<0xFF; i++) {
|
6 | uint8_t check = i2c_checkAddress((uint8_t) i);
|
7 |
|
8 | if(check==0) {
|
9 | snprintf(strOut,40,"I2C=%2x ",i);
|
10 | glcd_putstr(strOut);
|
11 | }
|
12 | _delay_ms(20); // <-- hier ist das Problem
|
13 | }
|
Wie man sieht, werden auch ungültige Adressen gescannt- und jede Adresse
zweimal (einmal zum Lesen und einmal zum Schreiben) - aber erst einmal
liegt mein Problem neben meinem nervigen
Deutsch-Englisch-Mischkommentaren woanders.
Hier sind die I2C-Routinen:
1 | /* I2C-Bus inititalisieren (ATmega32) */
|
2 | void i2c_init(void) {
|
3 | /*set bus speed (ca. 100kHz bei 16MHz) */
|
4 | TWSR |= (0<<TWPS1)|(0<<TWPS0);
|
5 | TWBR = 0x50;
|
6 |
|
7 | /* Prepare Pins */
|
8 | DDRC &= ~((1<<DD0)|(1<<DD1));
|
9 | PORTC |= (1<<PC0) | (1<<PC1); // Pull-Ups extern, aber schadet auch nicht
|
10 | }
|
11 |
|
12 |
|
13 | /* Check if I2C Adress is present */
|
14 | uint8_t i2c_checkAddress(uint8_t address) {
|
15 |
|
16 | uint8_t retVal = 0;
|
17 |
|
18 | // Test I2C Interface with PCF8574
|
19 | TWCR = ((1<<TWINT)|(1<<TWSTA)|(1<<TWEN)); // TWI aktivieren und Start-Condition ausloesen
|
20 | while(!(TWCR & (1<<TWINT) )); // warten auf START-Condition
|
21 | if((TWSR & 0xF8) != TW_START) return (TWSR & 0xF8); // Wenn keine Start-Conditions gesendet wurde abbrechen
|
22 |
|
23 | TWDR = address & (0xFE); // Adresse + Schreibbit ins Datenregister
|
24 | TWCR = ((1<<TWINT)|(1<<TWEN)); // senden
|
25 | while(!(TWCR & (1<<TWINT))); // warten auf ACK oder NACK
|
26 | if((TWSR & 0xF8) != TW_MT_SLA_ACK) retVal = 2; // Wenn kein Slave reagiert abbrechen
|
27 | TWCR = ((1<<TWINT)|(1<<TWSTO)|(1<<TWEN)); // STOP condition
|
28 | return retVal;
|
29 | }
|
Der Delay in der Scan-Schleife ist notwendig, ich weiß nur noch nicht so
genau warum. Vermutlich ist der I2C noch nicht wieder im Ruhezustand,
wobei mir noch nicht klar ist, warum- schließlich wird die
STOP-Kondition schon gesendet worden sein.
Gibt es eine Möglichkeit festzustellen, daß der ATmega noch sendet, z.B.
ein Statusbit? Leider finde ich gerade weder im Datenblatt noch im
AVR-TWI-Artikel den richtigen Hinweis.
Viele Grüße
Nicolas