Atmega16M1 CAN Bus OFF herausfinden

Gast #6333600
Lesenswert?

Hallo,

ich nutze einen Atmega16M1. Zumeist verwendet ich CAN. Es kann aber auch 
sein, dass ein Knoten getrennt wird, seine Arbeit aber weiter verrichten 
soll.

Dh. der Knoten ist vom Bus getrennt, es kann aber sein, dass er versucht 
Nachrichten auf den Bus zu schicken. Wenn er dies tut, bleibt er hängen. 
Sobald ich den Bus wieder verbinde geht es weiter.

Nun ist meine Frage, wie kann ich erkennen, ob der Bus gerade OFF ist, 
sodass erst garnicht versucht wird, eine Nachricht zu senden.

Im Register CANGSTA gibt es das BOFF Bit. Wenn ich aber vor senden 
folgendes prüfe:
if (CANGSTA & ( 1 << BOFF) == 0 {
// senden
}

Versucht er trotzdem zu senden. Merkt er erst das der Bus off ist, wenn 
er versucht hat zu senden? Wie kann ich hier rangehen um mein Problem zu 
lösen?
Gast #6333641
Lesenswert?

Ich habe jetzt eingestellt, dass der BUSSOFF Interrupt EN ist.
CANGIE = ( 1 << ENIT ) | (1 << ENBOFF) | ( 1 << ENRX );

Und die ISR sieht so aus:
1
ISR (CAN_INT_vect) {
2

3
    // if (CANGIT & (1 << CANIT)) {
4
        // PORTB |= (1 << PORTB6);
5
    // }
6
    if(CANGIT & (1 << BOFFIT)) {
7
        CANGIT |= (1 << BOFFIT);
8
        PORTB |= (1 << PORTB6);
9
    }
10
    else if (CANGSTA & (1 << BOFF)) {
11
        PORTB |= (1 << PORTB6);
12
    }
13
    else if (CANGSTA & (1 << ERRP)) {
14
        PORTB |= (1 << PORTB6);
15
    } else {
16
          // senden  
17
    }
18
}

An PB6 ist eine LED. Trenne ich das Gerät vom Bus, geht die LED aber 
nicht an. (LED funktioniert im sonstigen Programmablauf)
Gast #6333670
Lesenswert?

Lass ihn doch versuchen zu senden, stört doch nicht weiter.
Nur hängen bleiben muss die Software dabei natürlich auch nicht.
1
CANPAGE = (1<<4); // select MOB1
2
if(CANSTMOB & (1<<TXOK)) // fertig mit Senden?
3
{
4
  CANSTMOB &= ~(1<<TXOK); // reset flag
5

6
  CANMSG = 42;
7
  CANMSG = can_counter++;
8
  CANCDMOB |= (1<<CONMOB0); // Transfer einleiten
9
}

Das kann man so oft aufrufen wie man will, ob der CAN nun angeschlossen 
ist oder nicht.

Was man da drüber und drum herum natürlich noch machen kann ist zum 
Beispiel mit einem Timeout den CAN-Controller zu resetten.
Gast #6333686
Lesenswert?

Program schrieb:
> Wie kann ich den verhindern, dass mein Gerät versucht zu senden, obwohl
> es vom Bus getrennt ist. Oder ist das einfach nicht vorgesehen?

Ist nicht so richtig vorgesehen.

Wenn es aus Sicht des Systems ein Slave ist, könnte man mit dem Senden 
solange warten bis man dazu aufgefordert wird. Wenn man im Livebetrieb 
unterbricht gibt es halt für den Slave einen BUS-OFF - ist das schlimm? 
Ich denke nicht. Dann weiß der Knoten ja, dass da etwas faul ist und 
sich per LED oder sonstwie bemerkbar machen.

Der Kommunikationsmaster muss natürlich als Erster senden und würde 
einen BUS-OFF hinlegen wenn keiner zuhört. Das ist dann aber ja 
gewissermaßen richtig. Auch hier wäre eine Fehleranzeige angebracht.
Gast #6333704
Lesenswert?

Oh ja, Tipp, ich habe zwar lange den ATMega16M1 benutzt, bin aber wegen 
CAN-FD auf die ATSAMC21 / ATSAME51 umgestiegen.
Der ATSAMC21E18A-AU ist im gleichen Gehäuse wie der ATMega16M1-AU, 
kostet dabei aber weniger, läuft auch bei 5V, hat 256k FLASH, 48MHz und 
Peripherie ohne Ende.
Persönliche Seite #6334740
Lesenswert?

Nochmal zum nicht funktionierenden Bus:
Wenn es keinen Bus gibt (oder auch keinen anderen Busteilnhemer, der am 
Ende die CAN-Nachricht bestätigt), dann gibt es für diese Nachricht kein 
TXOK.
Das MOB wird damit auch nicht wieder frei zum Verschicken weiterer 
Nachrichten.
Ich vermute, dass dein Code bei der Suche nach einem freien MOB hängen 
bleibt. Oder kurz danach, wenn keines gefunden wurde.

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