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 | }
|