Hallo, ich habe folgendes Problem: Ich nutzte einen AtmegaxxM1 um über den CAN Bus zu kommunizieren. Hierbei kann es vorkommen, dass ein Gerät nicht am Bus hängt, aber trotzdem laufen soll. Der Bootloader auf diesem Gerät sendet mir zu beginn eine "Hallo ich bin da" Nachricht aus dem Bootloader heraus. Dies ist wichtig und kann nicht drauf verzichtet werden. Das Problem ist, wenn ich nun das Gerät trenn und dann reset oder starte, bleibt er beim senden der ersten "Hallo hier bin ich" Nachricht hängen, weil der Bus nicht vorhanden ist. Im Datenblatt steht, dass im Register CANGSTA BOFF eine 1 steht, wenn der Bus off ist. Dh. ich könnte das senden ja abbrechen, sobald BOFF nicht NUll ist. Das funktioniert aber leider nicht. if(!(CANGSTA & 0b00000010)) { // Senden } else { // nicht senden } Ich frage mich daher, wann genau das BOFF Bit gesetzt wird, wenn der BUS off ist. Ich werde aus dem Dateblatt nicht schlau. Wie kann ich es hinbekommen, dass er das senden aufgibt, wenn kein Bus vorhanden ist?
Klemmen schrieb: > Ich nutzte einen AtmegaxxM1 um über den CAN Bus zu kommunizieren. Hmm, einen µC mit dem Namen finde ich bei Microchip nicht. > Im Datenblatt steht, dass im Register CANGSTA BOFF eine 1 steht, wenn > der Bus off ist. Dh. ich könnte das senden ja abbrechen, sobald BOFF > nicht NUll ist. Das funktioniert aber leider nicht. Kannst du nicht einfach abbrechen, wenn du deine "hallo"-Nachricht rausgeschickt hast? Wenn die nicht gesendet werden kann, gibt's halt Error-Frames und dann das Bus-off, aber worauf wartet dein Code dann? PS: > CANGSTA BOFF Klingt wie der Name eines Rappers :)
Rolf M. schrieb: > PS: >> CANGSTA BOFF > > Klingt wie der Name eines Rappers Hab auch erstmal nach den Registern gegoogelt. Da wird dir genau sowas als Ergebnis angezeigt :-).
Ich umschreibe es nochmal etwas anders Wenn ich die Interrupts aktiviere: CANGIE = ( 1 << ENIT ) | ( 1 << ENBOFF) | ( 1 << ENRX ) | ( 1 << ENTX ) | (1 << ENERR) | (1 << ENBX) | (1 << ENERG); Sollte ja wenn die generellen Interrupts aktiv sind, beim Trennen des Kabels ein BOFF Interrupt gesetzt werden. Wenn ich dann in der Interrupt Routine folgendes abfrage:
1 | ISR (CAN_INT_vect) { |
2 | if(CANGSTA & (1 << BOFF)) { |
3 | PORTB |= 1 << PORTB6; |
4 | } |
5 | else if(CANGSTA & (1 << ERRP)) { |
6 | PORTB |= 1 << PORTB6; |
7 | } |
8 | else if(CANGIT & (1 << BOFFIT)) { |
9 | // BUS OFF |
10 | PORTB |= 1 << PORTB6; |
11 | ... |
Sollte doch die LED, die an PORTB6 angeschlossen ist, angehen. Tut Sie aber nicht. Würde mich freuen, wenn mir jemand einen Tipp gibt.
Klemmen schrieb: > CANGIE = ( 1 << ENIT ) | ( 1 << ENBOFF) | ( 1 << ENRX ) | ( 1 << ENTX ) > | (1 << ENERR) | (1 << ENBX) | (1 << ENERG); Behandelst du diese sämtlichen Interrupt-Quellen denn auch alle korrekt? Sonst würde ich erst mal alles abschalten, was nicht behandelt wird. Und löschst du entsprechend Datenblatt die Interrupt-Flags? ==================== To acknowledge a MOb interrupt, the corresponding bits of CANSTMOB register (RXOK, TXOK,...) must be cleared by the software application. This operation needs a read-modify-write software routine. To acknowledge a general interrupt, the corresponding bits of CANGIT register (BXOK, BOFFIT,...) mustbe cleared by the software application. This operation is made writing a logical one in these interrupt flags(writing a logical zero doesn’t change the interrupt flag value). ==================== Wenn du das nicht tust, bleibt die Interrupt-Bedingung bestehen, und beim ersten CAN-Interrupt, der auftritt, wird die ISR immer und immer wieder als Endlosschleife aufgerufen.
:
Bearbeitet durch User
Im Grunde sind es nur die Register CANGIT (CANIT, BOFFIT, BXOK, SERG, CERG, FERG AERG) CANGSTA ( BOFF und ERRP ) CANSTMOB ( TXOK und RXOK) Die Prüfe ich auf Interrupt, der schlägt aber nicht aus. Ich verstehe auch den Sinn von BOFF und BOFFIT nicht. Wenn der Bus off ist, sollte ja der Interrupt BOFFIT auslösen und im Statusregister BOFF auf eins gesetzt werden. Würde es nicht reichen, wenn man nur das BOFFIT ausliest? Oder ist das gedacht, wenn man pollen will? Das man dann das BOFF liest? Deinen Vorschlag alle zum testen unwichtigen Interrupts zu deaktivieren, werde ich testen. Danke fürs den Tipp.
Klemmen schrieb: > Im Grunde sind es nur die Register > CANGIT (CANIT, BOFFIT, BXOK, SERG, CERG, FERG AERG) > CANGSTA ( BOFF und ERRP ) > CANSTMOB ( TXOK und RXOK) > > Die Prüfe ich auf Interrupt, der schlägt aber nicht aus. > > Ich verstehe auch den Sinn von BOFF und BOFFIT nicht. Wenn der Bus off > ist, sollte ja der Interrupt BOFFIT auslösen und im Statusregister BOFF > auf eins gesetzt werden. Würde es nicht reichen, wenn man nur das BOFFIT > ausliest? BOFFIT ist das Interrupt-Flag. Das wird gesetzt, wenn der CAN-Controller in den Zustand "Bus off" wechselt. Wenn diese Flag und das globale Interrupt-Flag gesetzt sind, springt der µC bei der nächsten Instruktion in die ISR. Da muss dann Code von dir stehen, mit dem du den Interrupt verarbeitest und dann (wichtig!) das Flag wieder löschst. Mit dem Löschen deaktivierst du nicht den Zustand "Bus off", sondern nur die Bedingung für den Interrupt. Wenn du das nicht machst, springt der µC nach Abarbeitung deiner ISR gleich wieder rein, weil das Flag ja immer noch gesetzt ist. Und das gilt für die Flags sämtlicher Interrupts, die du aktiviert hast. BOFF dagegen kann man gar nicht schreiben. Es enthält immer die Information darüber, ob der µC gerade im Zustand "Bus off" ist oder nicht. > Deinen Vorschlag alle zum testen unwichtigen Interrupts zu deaktivieren, > werde ich testen. Danke fürs den Tipp.
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.