Forum: Compiler & IDEs Probleme mit TWI Kommunikation zwischen ATMEGAS


von Jakob (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute

Ich versuche jetzt schon seit Wochen immer wieder mal eine Saubere 
TWI-Kommunikation zwischen einem Master und zwei Slaves aufzubauen ...
Mittlerweile bin ich mal so weit dass ich es hinbekommen habe zwei Bytes 
zu verschicken und zwei Bytes zu empfangen ... nur macht danach mein 
Master komplett dicht und ich muss alle drei Teilnehmer reseten um das 
Programm nochma schnurren lassen zu können ...

Erst mal zum konkreten Vorhaben

Der Master hat zwei Bytes (HauptVektor, ForceVektor) die er an die 
Slaves verschicken möchte.
   Der Hauptvektor wird über General Call an beide gleichzeitig 
verschickt
   Der Forcevektor wird nur an den ersten Slave geschickt
(Die "Vektoren" sind einfach irgendwelche codierten Zusätnde die 
praktischerweise in Bytes untergebracht sind)

Danach holt sich der Master zwei Bytes vom ersten Slave in einem Zug
   Einmal den den den Sensorvektor und den Motorvektor

Ab jetzt ist keine TWI Operation mehr möglich. Ich denke dass es am 
Master liegen muss.

Eigentlich müsste der Master dann noch zwei Bytes vom nächsten Slave 
holen die Funktion hängt sich aber beim setzten der Startbedingung auf.

Was ist mein Fehler ... wer kann mir helfen.


Ich denke das Problem liegt an folgendem Codeschnipsel
weiter unten sind weitere Teile des Codes für den Master und für einen 
Slave dargestellt ... Im Anhang ist dann noch das ganze Programm für den 
Master.

Vielen Dank schon mal für Eure Hilfe
1
// Master als Receiver ==========================================================
2
3
4
void getValue(unsigned char SlaveAdress, char numLoops)
5
6
{
7
8
unsigned char i = 0;
9
10
  for(i=0; i<=2; i++)              // Löschen des Variablenvektors zu Beginn
11
  {
12
    Value3[i]=0;
13
  }
14
15
    TWCR =  START;              // Sende Startkondition
16
17
  do {}
18
  while (!(TWCR & (1<<TWINT)));        // Bis TWINT Flag gesetzt ist
19
 
20
21
22
  if ((TWSR & 0xF8) == TW_START)        // Startbedingung gesendet
23
  {
24
25
    TWDR = (SlaveAdress | TW_READ);      // Slaveadresse und Schreibbedingung
26
    TWCR = TRANSACK;            // Aktivieren des Sendevorgangs
27
    
28
    do {}
29
    while (!(TWCR & (1<<TWINT)));
30
31
    if ((TWSR & 0xF8) == TW_MR_SLA_ACK)    // Slaveadresse mit Lesebedingung gesendet
32
    {                    // ACK vom Slave bekommen
33
34
35
      for(i=1; i<=numLoops; i++)
36
      {
37
38
        TWCR = TRANSACK;        // Sendebefehl mit Acknowledge-Anweisung
39
40
41
        do {}
42
        while (!(TWCR & (1<<TWINT)));
43
44
        if ((TWSR & 0xF8) == TW_MR_DATA_ACK)  // Datenpacket von Slave wurde erhalten
45
        {                    // ACK wurde an Slave gesendet
46
47
          Value3[i] = TWDR;          // den gegenwertigen Registerwert in eine Temporäre Variable übernehmen
48
49
        }
50
51
        else if ((TWSR & 0xF8) == TW_MR_DATA_NACK)  // Datenpacket von Slave wurde erhalten
52
        {                    // Kein ACK wurde an Slave gesendet
53
          displayString("Daten Fehler",0,"reagiert nicht",0,500);   
54
        }
55
        else
56
        {
57
             displayString("SRG1 Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
58
        }
59
      }
60
    }
61
    else if ((TWSR & 0xF8) == TW_MR_SLA_NACK)  // Slaveadresse mit Lesebedingung gesendet
62
    {                    // Kein ACK vom Slave bekommen
63
         displayString("Slave Fehler",0,"reagiert nicht",0,500);
64
    }
65
    else
66
    {
67
         displayString("SRG2 Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
68
    }
69
  }
70
  else 
71
  {
72
       displayString("STA Fehler",0,"nicht gesendet",0,500);
73
  }
74
75
  TWCR = STOP;                // Transmit Stop
76
  _delay_us(50);
77
78
}
















Hier noch das Programm zum Master
weiter unten bilde ich noch das Programm zum ersten Slave ab
1
int main(void)
2
{
3
4
  initAll();                // Initialisieren diverser Funktionen
5
  sensorVektor   = 0;  
6
  motorVektor   = 0;  
7
  panelVektor   = 0;  
8
  akkuVektor     = 0;  
9
10
11
  while(1)                // unendliche Schleife
12
  {
13
14
      displayString("waiting ",0,"for user",0,500);
15
    do
16
    {
17
      readAllButtons();
18
    }
19
    while(sw1_slope == 0);        // Warte auf Eingabe
20
    sw1_slope = 0;    
21
22
    hauptVektor = 0b00110001;      // Zustandsvektor der Hauptplatine
23
    forceVektor = 0b00000001;
24
25
     displayString("Send",0,"in progress",0,1);
26
27
    sendData();              // Versenden des eigenen Zustandsvektors und der ForceBefehle
28
29
    displayString("Get",0,"in progress",0,1);
30
    
31
    getData();              // 
32
33
     displayString("Sensorvektor",0,"",0,0);
34
    printValue(sensorVektor,1000);
35
     displayString("Motorvektor",0,"",0,0);
36
    printValue(motorVektor,1000);
37
     displayString("Panelvektor",0,"",0,0);
38
    printValue(panelVektor,1000);
39
     displayString("Akkuvektor",0,"",0,0);
40
    printValue(akkuVektor,1000);
41
42
  }
43
  return 0;
44
45
}
46
47
48
49
// Daten senden ========================================================================
50
51
void sendData(void)              // Versenden des eigenen Zustandsvektors und der ForceBefehle
52
{
53
54
    displayString("sende Haupt",0,"in progress",0,1000);
55
56
  sendValue(0, hauptVektor);        // Versenden des Eigenen Zustandes über General Call
57
58
       displayString("Sende Force",0,"in progress",0,1000);
59
60
  sendValue(80, forceVektor);        // Versenden der ForcWerte an die Motorsteuerung (SensorCPU)
61
62
63
}
64
65
66
// Werteanforderung  ========================================================================
67
68
void getData(void)          // Start der Funktion
69
{
70
71
  displayString("Hole Sensor",0,"in progress",0,1000);
72
73
  getValue(80,2);      // Einholen der Zusatndsvektoren vom Sensor
74
  sensorVektor = Value3[1];
75
  motorVektor = Value3[2];
76
77
  displayString("Hole Spannung",0,"in progress",0,1000);
78
79
  getValue(96,2);      // Einholen der Zusandsvektoren vom Panel
80
  panelVektor = Value3[1];
81
  akkuVektor   = Value3[2];
82
83
}
84
85
86
87
/*********************************************************************************************/
88
// TWI Master Übergriffe ==================================================================
89
/*********************************************************************************************/
90
91
92
// Master als Transmitter ==========================================================
93
94
void sendValue(unsigned char SlaveAdress, unsigned char Value)
95
96
{
97
98
99
  TWCR =  START;              // Sende Startkondition
100
  do {}
101
  while (!(TWCR & (1<<TWINT)));        // Bis TWINT Flag gesetzt ist
102
103
104
  if ((TWSR & 0xF8) == TW_START)        // Startbedingung gesendet
105
  {
106
107
108
    TWDR = (SlaveAdress | TW_WRITE);    // Slaveadresse und Schreibbedingung
109
    TWCR = TRANSMIT;            // Aktivieren des Sendevorgangs
110
    
111
    do {}
112
    while (!(TWCR & (1<<TWINT)));
113
114
115
    if ((TWSR & 0xF8) == TW_MT_SLA_ACK)    // Slaveadresse mit Schreibbedingung gesendet
116
    {                    // ACK vom Slave bekommen
117
118
119
      TWDR = Value;            // Übermittlungswert in Schiftregister
120
      TWCR = TRANSMIT;          // Aktivieren des Sendevorgangs
121
 
122
123
      do {}
124
      while (!(TWCR & (1<<TWINT)));    // Bis TWINT Flag gesetzt ist
125
126
        if ((TWSR & 0xF8) == TW_MT_DATA_ACK)// Daten wurde versendet
127
        {                  // ACK vom Slave bekommen
128
129
        }
130
        else if ((TWSR & 0xF8) == TW_MT_DATA_NACK)// Daten wurde versendet
131
        {                  // Kein ACK vom Slave bekommen
132
             displayString("Daten Fehler",0,"reagiert nicht",0,500);   
133
        }
134
        else
135
        {
136
             displayString("SRG Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
137
        }                  // Registerinhalt passt überhaupt nicht zu dem Kontext 
138
    }
139
    else if ((TWSR & 0xF8) == TW_MT_SLA_NACK)  // Slaveadresse mit Schreibbedingung gesendet
140
    {                    // Kein ACK vom Slave bekommen
141
         displayString("Slave Fehler",0,"reagiert nicht",0,500);
142
    }
143
    else
144
    {
145
         displayString("SRG Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
146
    }                      // Registerinhalt passt überhaupt nicht zu dem Kontext
147
  }
148
  else 
149
  {
150
       displayString("STA Fehler",0,"nicht gesendet",0,500);
151
  }
152
153
154
  TWCR = STOP;        // Transmit Stop          
155
  _delay_us(50);
156
157
158
}
159
160
161
// Master als Receiver ==========================================================
162
163
164
void getValue(unsigned char SlaveAdress, char numLoops)
165
166
{
167
168
unsigned char i = 0;
169
170
  for(i=0; i<=2; i++)              // Löschen des Variablenvektors zu Beginn
171
  {
172
    Value3[i]=0;
173
  }
174
175
    TWCR =  START;              // Sende Startkondition
176
177
  do {}
178
  while (!(TWCR & (1<<TWINT)));        // Bis TWINT Flag gesetzt ist
179
 
180
181
182
  if ((TWSR & 0xF8) == TW_START)        // Startbedingung gesendet
183
  {
184
185
    TWDR = (SlaveAdress | TW_READ);      // Slaveadresse und Schreibbedingung
186
    TWCR = TRANSACK;            // Aktivieren des Sendevorgangs
187
    
188
    do {}
189
    while (!(TWCR & (1<<TWINT)));
190
191
    if ((TWSR & 0xF8) == TW_MR_SLA_ACK)    // Slaveadresse mit Lesebedingung gesendet
192
    {                    // ACK vom Slave bekommen
193
194
195
      for(i=1; i<=numLoops; i++)
196
      {
197
198
        TWCR = TRANSACK;        // Sendebefehl mit Acknowledge-Anweisung
199
200
201
        do {}
202
        while (!(TWCR & (1<<TWINT)));
203
204
        if ((TWSR & 0xF8) == TW_MR_DATA_ACK)  // Datenpacket von Slave wurde erhalten
205
        {                    // ACK wurde an Slave gesendet
206
207
          Value3[i] = TWDR;          // den gegenwertigen Registerwert in eine Temporäre Variable übernehmen
208
209
        }
210
211
        else if ((TWSR & 0xF8) == TW_MR_DATA_NACK)  // Datenpacket von Slave wurde erhalten
212
        {                    // Kein ACK wurde an Slave gesendet
213
          displayString("Daten Fehler",0,"reagiert nicht",0,500);   
214
        }
215
        else
216
        {
217
             displayString("SRG1 Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
218
        }
219
      }
220
    }
221
    else if ((TWSR & 0xF8) == TW_MR_SLA_NACK)  // Slaveadresse mit Lesebedingung gesendet
222
    {                    // Kein ACK vom Slave bekommen
223
         displayString("Slave Fehler",0,"reagiert nicht",0,500);
224
    }
225
    else
226
    {
227
         displayString("SRG2 Fehler",0,"",0,500);  // Genereller Serviceregisterfehler 
228
    }
229
  }
230
  else 
231
  {
232
       displayString("STA Fehler",0,"nicht gesendet",0,500);
233
  }
234
235
  TWCR = STOP;                // Transmit Stop
236
  _delay_us(50);
237
238
}
239
240
241
242
/*********************************************************************************************/
243
// Initialisierungsroutinen ==================================================================
244
/*********************************************************************************************/
245
246
247
// TWI Initialisierung
248
249
void setTWIMaster(void)  
250
{
251
252
  sei();              // Generelles einschalten der Interrupts
253
  TWCR = (1<<TWEN);        // TWI Schnittstelle schon mal einschalten
254
  TWBR = 0x10;          // BitrateRegister auf 16 setzten
255
  TWSR = 0x02;          // TWI Prescaler auf 16 setzen
256
257
                  // Mit dieser Einstellung lassen sich immer noch 
258
                  // ca. 1400 Pakete pro Sekunde verschicken
259
}

nun noch das dazugehörige Slaveprogramm
1
--------------------------------------------------
2
3
4
5
int main(void)
6
{
7
8
  initAll();                  // Initialisieren diverser Funktionen
9
  
10
    sensorVektor = 0b00100101;
11
    motorVektor = 0b00000001;
12
    hauptVektor   = 0;
13
    forceVektor    = 0;
14
15
    DDRB |= (1<<DDB2);
16
    PORTB |= (1<<PB2);
17
18
    displayString("Warte auf Master",0,"",0,0);
19
20
  while(1)                  // unendliche Schleife
21
  {
22
    displayString("Hauptvektor",0,"",0,0);
23
    printValue(hauptVektor,1000);
24
    displayString("Forcevektor",0,"",0,0);
25
    printValue(forceVektor,1000);
26
27
28
  }
29
  return 0;
30
31
}
32
33
ISR (TWI_vect)
34
{
35
36
  TWCR = (1<<TWEA) | (1<<TWEN);
37
  cli();
38
39
  if ((TWSR & 0xF8) == TW_ST_SLA_ACK)
40
  giveValue();
41
  else
42
  receiveValue();
43
44
  sei();
45
  TWCR |= (1<<TWEA) | (1<<TWEN) | (1<<TWIE);  // Setze das TWI Statusregister
46
  TWDR = 0;
47
48
}
49
50
/*********************************************************************************************/
51
// TWI Master Zugriffe ==========================================================================
52
/*********************************************************************************************/
53
54
55
// Slave als Receiver ==========================================================
56
57
void receiveValue()
58
{
59
60
  if ((TWSR & 0xF8) == TW_SR_GCALL_ACK)    // General Call erfasst 
61
  {                      // ACK wurde zurückgesendet
62
63
64
    TWCR |= (1<<TWEA);
65
    while (!(TWCR & (1<<TWINT)));
66
67
    if ((TWSR & 0xF8) == TW_SR_GCALL_DATA_ACK)  // Daten erhalten (nach dem generellen Ansprechen durch Master)
68
    {                       // ACK wurde zurückgesendet
69
70
      hauptVektor = TWDR;            // Übernehmen des Datenregisters in den Zustands-Hauptvektor
71
72
    }
73
    else if ((TWSR & 0xF8) == TW_SR_GCALL_DATA_NACK)  // Daten erhalten (nach dem generellen Ansprechen durch Master)
74
    {                      // Kein ACK wurde zurückgesendet
75
         displayString("Slave Fehler",0,"NACK nach GC",0,500);
76
    }
77
78
  }
79
80
  else if ((TWSR & 0xF8) == TW_SR_SLA_ACK)      // Eigene Slave-Adresse mit Schriebbedingung erhalten
81
  {                      // ACK wurde zurückgesendet
82
83
    TWCR |= (1<<TWEA);
84
85
    while (!(TWCR & (1<<TWINT)));
86
87
88
    if ((TWSR & 0xF8) == TW_SR_DATA_ACK)    // Daten erhalten (nach dem Ansprechen durch Master)
89
    {                      // ACK wurde zurückgesendet
90
91
      forceVektor = TWDR;            // Übernehmen des Datenregisters in den Forcevektor
92
93
    }
94
    else if ((TWSR & 0xF8) == TW_SR_DATA_NACK)    // Daten erhalten (nach dem Ansprechen durch Master)
95
    {                      // Kein ACK wurde zurückgesendet
96
         displayString("Slave Fehler",0,"NACK nach SLA+W",0,500);
97
    }
98
99
  }
100
101
102
  TWCR = ((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));
103
104
}
105
106
107
108
// Slave als Transmitter ==========================================================
109
110
111
112
113
void giveValue(void)
114
{
115
116
117
118
  if ((TWSR & 0xF8) == TW_ST_SLA_ACK)      // Eigene Slave-Adresse mit Lesebedingung erhalten
119
  {                      // ACK wurde zurückgesendet
120
121
    TWDR = sensorVektor;          // Einladen des Sensor-Zustandvektors in das Senderegister
122
123
124
    TWCR = TRANSACK
125
    while (!(TWCR & (1<<TWINT)));
126
127
128
    if ((TWSR & 0xF8) == TW_ST_DATA_ACK)    // Daten im TWDR wurden versendet
129
    {                    // ACK vom Master wurde erhalten
130
131
      TWDR = motorVektor;          // Einladen des Sensor-Zustandvektors in das Senderegister
132
133
      TWCR = TRANSACK;
134
      while (!(TWCR & (1<<TWINT)));
135
136
137
      if ((TWSR & 0xF8) == TW_ST_DATA_NACK)    // Daten im TWDR wurden versendet
138
      {
139
           displayString("Slave Fehler",0,"NACK nach Daten",0,500);
140
      }
141
142
    }
143
144
    else if ((TWSR & 0xF8) == TW_ST_DATA_NACK)    // Daten im TWDR wurden versendet
145
    {                      // Kein ACK vom Master wurde erhalten
146
         displayString("Slave Fehler",0,"NACK1 nach Daten",0,500);
147
    }
148
149
    else if ((TWSR & 0xF8) == TW_ST_LAST_DATA)    // Letztes Datenpacket im TWDR wurden versendet
150
    {                      // Kein ACK vom Master wurde erhalten
151
         displayString("Slave Fehler",0,"NACK2 nach Daten",0,500);
152
    }
153
154
155
  }
156
157
  TWCR = ((1<<TWINT)|(1<<TWEA)|(1<<TWEN)|(1<<TWIE));    // Setze das TWI Statusregister
158
159
}
160
161
162
163
164
/*********************************************************************************************/
165
// Initialisierungsroutinen ==================================================================
166
/*********************************************************************************************/
167
168
169
170
// TWI Initialisierung
171
172
void setTWISlave(unsigned char SlaveAdress)  
173
{
174
  sei();                    // Generelles einschalten der Interrupts
175
  TWAR = (SlaveAdress | 1);            // Setzen der Slave-Adresse mit General Call Enable
176
  TWAMR = SlaveAdress;            // Setzten der Adressenmaskierung
177
  
178
  TWDR = 0;
179
180
  TWCR = (1<<TWEA) | (1<<TWEN) | (1<<TWIE);  // Setze das TWI Statusregister
181
                        // TWI ACK und Interrupt wird eingeschaltet 
182
}

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.