Hallo! Ich habe bei deiner Umsetzung einer Aufgabe ein Problem. Hier ein Fragment von meinem Code. In der Textdatei im Anhang ist er komplett: void CAN1_RX0_IRQHandler (void) { CAN_Receive(CAN1, CAN_FIFO0, &RxMsg); if (counter1 == 10) { TxMsg.StdId = 0x11D; TxMsg.ExtId = 0; TxMsg.DLC = 1; TxMsg.IDE = CAN_ID_STD; TxMsg.RTR = CAN_RTR_DATA; // send number of received messages TxMsg.Data[0] = counter2; CAN_Transmit(CAN1, &TxMsg); GPIO_ToggleBits(GPIOD,GPIO_Pin_12); } if(RxMsg.StdId == 0x67) { counter1++; } else if(RxMsg.StdId == 0x52) { counter2++; } } // end of fragment Ich will eine Nachricht mit bestimmten Inhalt senden, sobald ich die Nachricht mit der ID 0x67 zehnmal empfangen habe. Mit dem CANalyzer konnte ich bisher noch nicht das entsprechende Resultat erzielen. Wie kann ich sicherstellen, dass ich genau 10 messages zähle, abreche und dann keine weitere 0x67 Nachricht beim neuen Zählanlauf übersehe (mit dem Raussenden der Nachricht würde eventuell eine 11. (die neue erste msg des Folgezyklus) Nachricht übersehen. Kann mir jemand Tipps geben oder hat ähnliche Probleme bereits gelöst? Danke, Gruß Korke
Dein ISR empfängt erstmal 10 Msgs mit (RxMsg.StdId == 0x67). Bei der 10. dieser Msgs passiert noch: garnichts. Erst NACH der 10. msg wird JEDE empfangene msg eine Antwort erzeugen. Dies passiert so lange, bis eine 11. msg mit (RxMsg.StdId == 0x67) empfangen wird. Diese wird noch einmal eine Antwort senden, danach wird aber (counter1 > 10) und damit wird nie wieder eine AntwortMsg verschickt (korrekter: erst nach 2^32 empfangenen msgs). Gruß, Stefan
Deine Counter sind zwar 32 Bit breit definiert:
1 | uint32_t counter1 = 0; // counter for message 1 |
Deine msg versendet davon aber nur 8 Bit:
1 | TxMsg.Data[0] = counter2; |
Gruß, Stefan
Hi, Wenn du die CAN Nachricht erst auf die ID 0x67 prüfst , dann den Zähler erhöhst. Mit dem Zähler kannst du dann den Rest einer Division durch nehmen und den auf
1 | if((counter1 % 10) == 0) |
prüfen. Damit sollte es gehen , wenn sende Puffer und Empfangspuffer getrennt sind. Welche ID hat deine Antwort ? Wenn die größer als 0x67 ist kann theoretisch die Nachtichten der IDs <= 0x67 deine Antwort überschreiben. Gruß JackFrost
Bastian W. schrieb: > Wenn die größer als 0x67 > ist kann theoretisch die Nachtichten der IDs <= 0x67 deine Antwort > überschreiben. Nein, bei CAN werden keine msgs überschrieben. Die msg mit der niedrigeren Priorität wird bei gleichzeitigem Sendeversuch später gesendet bzw. wiederholt. Die höchste Priorität hat beim CAN-Bus eine msg mit der Priorität 0x00. Gruß, Stefan
Ich würde nun das probieren. Leider komme ich aber erst morgen wieder an CANalyzer: void CAN1_RX0_IRQHandler (void) { CAN_Receive(CAN1, CAN_FIFO0, &RxMsg); if ((counter1 % 10) == 0) { TxMsg.StdId = 0x11D; TxMsg.ExtId = 0; TxMsg.DLC = 1; TxMsg.IDE = CAN_ID_STD; TxMsg.RTR = CAN_RTR_DATA; // send number of received messages TxMsg.Data[0] = counter2; CAN_Transmit(CAN1, &TxMsg); GPIO_ToggleBits(GPIOD,GPIO_Pin_12); } if(RxMsg.StdId == 0x67) { counter1++; } else if(RxMsg.StdId == 0x52) { counter2++; } } // end of fragment Ich habe bezüglich den 8 Bit, die die Message höchstens versenden kann, leider keinen Schimmer, wie ich darangehen soll. Wenn ich über die 2^8 hinaus bin, sehe ich ein, dass es dann ohnehin nicht mehr funktioniert.
So wie Du das machst, wird die Antwort-msg immer dann geschickt, wenn counter1 durch 10 teilbar ist. Zusätzlich: Da zuerst die Abfrage "durch 10 teilbar" und danach "counter1++" kommt, geschieht das erst bei der 11. empfangenen 0x67-msg! Du willst aber nur dann die Antwort senden, wenn die empfangene msg eine (RxMsg.StdId == 0x67) ist UND der counter durch 10 teilbar ist. Also:
1 | if(RxMsg.StdId == 0x67) |
2 | {
|
3 | counter_0x67++; |
4 | |
5 | if ((counter_0x67 % 10) == 0) |
6 | {
|
7 | // todo: Antwort-msg auf 0x67 senden
|
8 | // todo: Led togglen
|
9 | }
|
10 | }
|
11 | |
12 | if(RxMsg.StdId == 0x52) |
13 | {
|
14 | counter_0x52++; |
15 | |
16 | if ((counter_0x52 % 10) == 0) |
17 | {
|
18 | // todo: Antwort-msg auf 0x52 senden
|
19 | // todo: Led togglen
|
20 | }
|
21 | }
|
Ich habe mal Deine counter umbenannt, dann ist der Zusammenhang intuitiver. Korke schrieb: > Ich habe bezüglich den 8 Bit, die die Message höchstens versenden kann, > leider keinen Schimmer, wie ich darangehen soll. Wenn ich über die 2^8 > hinaus bin, sehe ich ein, dass es dann ohnehin nicht mehr funktioniert. Du kannst Deine uint32_t counter (4 Byte) entweder in TxMsg.Data[0] bis TxMsg.Data[3] speichern. Wenn Du nicht weisst, wie das geht, dann kannst Du immer noch Deine counter-Definition auf uint8_t ändern. Dann läuft der Counter zwar schneller über, aber das Programm ist formal richtiger ... Viele Grüße, Stefan
:
Bearbeitet durch User
Ist es eventuell besser die Variablen, die global deklariert sind, in die main zu packen? Was wäre ein Grund dafür? - Wir konnten nur antworten, dass wir es bisher immer so gemacht haben.
Korke schrieb: > Ist es eventuell besser die Variablen, die global deklariert sind, in > die main zu packen? > > Was wäre ein Grund dafür? - Wir konnten nur antworten, dass wir es > bisher immer so gemacht haben. Autsch, ich hoffe mal nicht an einer Uni. Mein Prof hätte mich bei so einer Antwort aus dem Kurs geschmissen mit der Empfehlung nächstes Jahr erneut zu belegen... Denk mal nach, Stichwort Gültigkeitsbereich Gehört zum allerersten Grundstoff.
Probier es einfach aus. Die Variablen, die Du in der main() definierst, sind in der ISR nicht bekannt. Das wird also nicht funktionieren, der Compiler wird Dir einen Error bringen. Die eigendliche Domäne globaler Variablen ist die Kommunikation zwischen Interrupts und dem "normalen" Programm. Viele Grüße, Stefan
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.