Forum: Mikrocontroller und Digitale Elektronik TWI AVR Problem bei Arbitrierung Multimaster Betrieb


von Sebastian S. (bachelor)


Lesenswert?

Hallo Leute,

ich habe zwei Atmega32 mit TWI verbunden.

Das senden und empfangen einzeln funktioniert super, habe ganze 
mittlerweile im Mulitmaster Betrieb im Betrieb. Der funktioniert auch 
noch so lange die  Arbitrierung nicht einschreiten muss weil beide 
Controller zu gleichen Zeit anfangen zu senden.
Aus irgendwelchen Gründen kommt die Arbitrierung nicht und der SDA Pin 
bleibt auf Low.
1
//Senden starten. 
2
3
    TWBR = 0b00000001;//Frequenzeinstellung TWI
4
    TWSR = (1 << TWPS1) | (1 << TWPS0); //Initialisierung TWI
5
    debug("\r");
6
      debug("Start senden ");
7
    TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN) | (1<<TWIE)| (0<<TWEA);
8
    TWI_zeichen = zeichen;

1
ISR(TWI_vect)
2
{
3
  switch (TWSR & 0xF8) { //TWI Start erfolgreich gesendet
4
      
5
    //Empfangs Mode
6
    
7
    case 0x60:   // Adresse empfangen und acknowledge gesendet
8
      debug("");
9
      debug("SLA+W empfangen");
10
      TWCR = (1<<TWINT) | (1<<TWEA)| (1<<TWEN)|(1<<TWIE) ;
11
    break;
12
    
13
    case 0x80: // Daten empfangen und acknowledge gesendet
14
      debug("Daten empfangen");
15
      //debug(TWDR);
16
      TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWEA)|(1<<TWIE);
17
    break;
18
    
19
    case 0xA0: // Stop empfangen warte auf neue Adressierung
20
      debug("Stop empfangen");
21
      TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(0<<TWSTO)|(0<<TWSTA)|(1<<TWIE);
22
    break;
23
    
24
    //Senden Mode
25
    
26
    case 0x08:   
27
      //debug("TWI Start erfolgreich gesendet Interrupt");
28
      TWDR = 0x02; //Adresse 1 _ write 0
29
      TWCR = (1<<TWINT) | (1<<TWEN)| (1<<TWIE);
30
    
31
    break;
32
    
33
    case 0x38: 
34
      debug("Aribitration lost");
35
    break; 
36
    
37
    case 0x68: 
38
      debug("Aribitration lost");
39
    break; 
40
    
41
    case 0x78: 
42
      debug("Aribitration lost");
43
    break; 
44
    
45
    case 0xB0: 
46
      debug("Aribitration lost");
47
    break;
48
    
49
    //Slave auf Adresse geantwortet 
50
    case 0x18:
51
      //debug("Slave auf Adresse geantwortet");
52
    
53
      //debug("Daten an Slave senden");
54
      TWDR = TWI_zeichen;
55
      TWCR = (1<<TWINT) | (1<<TWEN)| (1<<TWIE);
56
    break;
57
    //Daten von Slave akzeptiert
58
    case 0x28:
59
      //debug("Daten von Slave akzeptiert");
60
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)|(0<<TWSTA)|(1<<TWIE);
61
      debug("Stop gesendet");
62
      _delay_ms(75); //Abwarten bis Stop gesendet
63
      TWCR = (1<<TWEA) |(0<<TWSTO);  //Busfreigabe
64
      TWAR = 0b00000111; //Adresse setzten
65
      TWSR = (0 << TWPS1) | (0 << TWPS0);
66
      TWCR = (1<<TWINT)|(1<<TWEA) | (1<<TWEN) | (1<<TWIE);
67
    break;
68
    
69
  }
70
}//Ende (TWI_vect)

debug wird per RS232 ausgegeben.

Kann mir jemand weiterhelfen?

Gruß Sebastian

von Gast (Gast)


Lesenswert?

Hallo,

der eingestellte Code ist schon mal ein Anfang...

aber wenn du aus "case 0x60: usw." so was wie "case TW_REP_START:" 
machen könntest, würde so mancher hier im Forum eher einen Blick darauf 
werfen.
Symbolische Bezeichnungen sind einfacher zu interpretieren wie 
Bitmuster.

von Sebastian S. (bachelor)


Lesenswert?

Danke für deine Antwort! Das hilft mir jedoch nicht weiter!

Weiß vielleicht sonst jemand muss ich die Arbitrierung extra 
einschalten, habe ich im Datenblatt etwas überlesen?

Gruß Sebastian

von Sebastian S. (bachelor)


Lesenswert?

Hallo,

habe das Problem mittlerweile gelöst.

Man sollte auch die Restlichen Status Codes abfragen! Dann würde 
auffallen das nicht die Arbitrierung sonder etwas anderes einen Fehler 
ausgelöst hat.

Für alle die den Thread zufällig finden, hier die Lösung.
1
volatile char TWI_zeichen;
2
volatile char TWI_empfangen = ' ';
3
volatile char TWI_status = 0;
4
volatile int TWI_aktiv = 0;
5
6
ISR(TWI_vect) /* Interrupt TWI _vect muss immer an den Namen im Datenblatt angehängt werden
7
          Leerzeichen werden durch _ ersetzt */
8
{
9
  TWI_status = (TWSR & 0xF8);
10
  switch (TWSR & 0xF8) {
11
      
12
    //Empfangs Mode
13
    
14
    case 0x60:   // Adresse empfangen und acknowledge gesendet
15
      TWI_aktiv = 1;
16
      //lcd_gotoxy(0,30);
17
      //lcd_writestringP(PSTR("SLA+W empfangen"));
18
      TWCR = (1<<TWINT) | (1<<TWEA)| (1<<TWEN)|(1<<TWIE) ; //Bisher hat TWEN gefehlt!
19
    break;
20
    
21
    
22
    case 0x70: 
23
      lcd_gotoxy(0,0);
24
      lcd_writestringP(PSTR("70"));
25
    break;
26
    
27
    case 0x80: // Daten empfangen und acknowledge gesendet
28
      //lcd_gotoxy(0,40);
29
      //lcd_writestringP(PSTR("Daten empfangen"));
30
      
31
      TWI_empfangen = TWDR;
32
      TWCR = (1<<TWEN)|(1<<TWINT)|(1<<TWEA)|(1<<TWIE);
33
    break;
34
    
35
    case 0x88: 
36
      lcd_gotoxy(0,0);
37
      lcd_writestringP(PSTR("88"));
38
    break;    
39
    
40
    case 0x90: 
41
      lcd_gotoxy(0,0);
42
      lcd_writestringP(PSTR("90"));
43
    break;
44
    
45
    case 0x98: 
46
      lcd_gotoxy(0,0);
47
      lcd_writestringP(PSTR("98"));
48
    break;
49
    
50
    case 0xA0: // Stop empfangen warte auf neue Adressierung
51
      //lcd_gotoxy(0,60);
52
      //lcd_writestringP(PSTR("Stop empfangen"));
53
      TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(0<<TWSTO)|(0<<TWSTA)|(1<<TWIE);
54
      TWI_aktiv = 0;
55
    break;
56
    
57
    //Senden Mode
58
    
59
    case 0x08:   
60
      //TWI_aktiv = 1;
61
      //lcd_gotoxy(0,40);
62
      //lcd_writestringP(PSTR("              "));
63
      TWDR = 0x06; //Adresse 3 _ write 0
64
      TWCR = (1<<TWINT) | (1<<TWEN)| (1<<TWIE);
65
      //lcd_gotoxy(0,40);
66
      //lcd_writestringP(PSTR("Start gesendet"));
67
      
68
    break;
69
    
70
    case 0x10: 
71
      lcd_gotoxy(0,0);
72
      lcd_writestringP(PSTR("10"));
73
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE);
74
    break;    
75
    
76
    case 0x38: 
77
      lcd_gotoxy(0,20);
78
      lcd_writestringP(PSTR("Aribitration lost"));
79
    break;
80
    
81
    case 0x68: 
82
      lcd_gotoxy(0,20);
83
      lcd_writestringP(PSTR("Aribitration lost"));
84
    break;    
85
    
86
    case 0x78: 
87
      lcd_gotoxy(0,20);
88
      lcd_writestringP(PSTR("Aribitration lost"));
89
    break;      
90
    
91
    case 0xB0: 
92
      lcd_gotoxy(0,20);
93
      lcd_writestringP(PSTR("Aribitration lost"));
94
    break;  
95
    
96
    
97
    //Slave auf Adresse geantwortet
98
 
99
    case 0x18:
100
      //debug("Slave auf Adresse geantwortet");
101
    
102
      //debug("Daten an Slave senden");
103
      TWDR = TWI_zeichen;
104
      TWCR = (1<<TWINT) | (1<<TWEN)| (1<<TWIE);
105
    break;
106
    
107
    case 0x20: 
108
      lcd_gotoxy(0,0);
109
      lcd_writestringP(PSTR("20"));
110
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE);
111
    break;
112
    
113
    //Daten von Slave akzeptiert
114
    case 0x28:
115
      //debug("Daten von Slave akzeptiert");
116
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)|(0<<TWSTA)|(1<<TWIE);
117
      //Stop gesendet
118
      _delay_ms(40);//Abwarten bis Stop gesendet
119
      TWCR = (1<<TWEA) |(0<<TWSTO);  //Busfreigabe
120
      TWAR = 0b00000011; //Adresse setzten
121
      TWSR = (0 << TWPS1) | (0 << TWPS0);
122
      TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE);
123
      TWI_aktiv = 0;
124
    break;
125
    
126
    case 0x30:
127
      lcd_gotoxy(0,0);
128
      lcd_writestringP(PSTR("30"));
129
      TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWSTA);
130
    break;
131
    
132
  }
133
}

Aufruf der Start-Bedingung als Funktion
1
int f_TWI_send_zeichen(char zeichen) {
2
    if(TWI_aktiv == 0){
3
      TWI_aktiv = 1;
4
      TWBR = 0b00000001;//Frequenzeinstellung TWI
5
      TWSR = (1 << TWPS1) | (1 << TWPS0); //Initialisierung TWI
6
      //lcd_gotoxy(0,30);
7
      //lcd_writestringP(PSTR("Ss"));
8
      TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN) | (1<<TWIE);
9
10
      TWI_zeichen = zeichen;
11
    }
12
  return 1;
13
}

Gruß Sebastian

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.