Forum: Mikrocontroller und Digitale Elektronik ATMEGA8 - I2C bleibt bei "while(!(TWCR & (1<<TWINT)));" hängen


von Tim H. (h0rbie)


Lesenswert?

Guten Abend,

ich habe folgendes Problem. Ich will mit meinem ATMEGA8 einen PCF8574 
Port Expander ansprechen. Die Adresse ist auf 0x40 eingestellt. Zudem 
verwende ich die lib von Peter Fleury. Angeschlossen ist soweit alles 
korrekt (Pins über 4,7k an +5V als Pullup), habe soweit alle Spannungen 
durchgemessen. Der Controller bleibt nun einfach bei dieser Zeile hängen
1
while(!(TWCR & (1<<TWINT)));

nachdem die Start-Bedingung mit
1
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);

gesendet wurde. Mit einem Oszilloskop habe ich schon nachgesehen, ob 
überhaupt etwas auf den Pins passier, leider bleiben diese komplett tot. 
Daher bleibt wohl auch das Programm hier stehen. Taktrate ist auch 
angepasst im Header und mein C Programm sieht wie folgt aus:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
#include "i2cmaster.h"
5
6
#define PCF8574_ADDR 0x40
7
8
int main(void)
9
{
10
    sei(); // Enable Interrupts
11
12
    i2c_init(); // I2C initialisieren
13
    _delay_ms(500);
14
    
15
    i2c_start(PCF8574_ADDR | I2C_WRITE);
16
    i2c_write(0xFF);
17
    i2c_stop();
18
19
    while(1)
20
    ;
21
22
    return 0;
23
}

Durch LED ansteuern habe ich auch bereits getestet, dass das Programm 
wirklich bei oben genannter Stelle hängen bleibt. Zudem ist noch meine 
Frage, ob ich über sei() überhaupt die Interrupts global aktivieren muss 
für die TWI Kommunikation? Habe I2C bisher nur mit einem Cortex M3 
verwendet.

MfG
H0rBie

: Bearbeitet durch User
von Jörg E. (jackfritt)


Lesenswert?

Wie lang sind die Leitungen am Bus? Probier mal 1k Abschlusswiderstände. 
Wie schnell läuft dein Bus?

von Tim H. (h0rbie)


Lesenswert?

Hallo Jörg,

die Geschwindigkeit ist laut dem define auf 100kHz gesetzt, die Leitung 
insgesamt ca. 30cm. Mich wundert allerdings, dass ich nichtmal auf dem 
Oszilloskop auf SDA oder SCL etwas sehen kann. Als wenn der Controller 
überhaupt gar nicht erst etwas überträgt.

von Jörg E. (jackfritt)


Lesenswert?

Wenn nichts zu messen ist, wird wohl was am Code noch nicht stimmen. Den 
kenn ich leider nich.

von Tim H. (h0rbie)


Lesenswert?

Hier der Code, hab das ganze nochmal ganz rudimentär versucht und mir 
ist aufgefallen, dass der SCL Pin nun auf 3,3V festhängt und SDA auf 5V. 
Ohne den AVR sind beide sauber auf 5V gezogen über die Pullup 
Widerstände. Habe die Stelle im Quellcode markiert, an der es hängen 
bleibt.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <util/delay.h>
4
5
#define PCF8574_ADDR 0x40
6
7
int main(void)
8
{
9
    uint8_t i = 0;
10
    DDRB = 0xFF; // Port B Ausgänge
11
12
    sei(); // Enable Interrupts
13
    _delay_ms(500);
14
15
    /* Blinken, dass resettet wurde */
16
    for(i = 0; i < 10; i++){
17
        PORTB |= (1 << PB0);
18
        _delay_ms(50);
19
        PORTB &= ~(1 << PB0);
20
        _delay_ms(50);
21
    }
22
23
/*****************************************************************/
24
25
    TWSR = 0;  // no prescaler
26
    TWBR = 52; // speed for 100kHz @ 12MHz CPU clock
27
28
    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
29
    while(!(TWCR & (1<<TWINT))); // Hier hängt es schon fest.
30
    _delay_ms(50);
31
32
    TWDR = (0x20<<1) | 0;
33
    TWCR = (1<<TWINT) | (1<<TWEN);
34
    _delay_ms(50);
35
36
    TWDR = 0x0F;
37
    TWCR = (1<<TWINT) | (1<<TWEN);
38
    _delay_ms(50);
39
40
    TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
41
    _delay_ms(50);
42
43
    PORTB |= (1 << PB0);
44
45
    while(1)
46
    ;
47
48
    return 0;
49
}

von Tim H. (h0rbie)


Lesenswert?

Okay ich habe nochmal weitergetestet ohne den Expander. Er scheint 
kaputt zu sein, denn ohne diesen läuft die Kommunikation bis zum Ende 
durch.

von Tim H. (h0rbie)


Lesenswert?

Okay das Problem ist gelöst. Es gab einen winzigen Kontakt von +5V auf 
SDA, den man nur mit einer Lupe erkennen konnte. Hab ich wohl übersehen 
beim Backen. Trotzdem danke :)

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
Noch kein Account? Hier anmelden.