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