Probleme mit TWI Kommunikation zwischen ATMEGAS

Gast #1983206
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
}
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren