Forum: Haus & Smart Home Fehler für Can_Bus


von gast (Gast)


Lesenswert?

hallo,
ich programmiere mit dem Mikrocontroller at90can128 und versuche 
CAN_Felher zu behandeln. Ich möchte eine Meldung bekommen, wenn ich  z.B 
die CAN-Kabel ziehe.
Ich habe die folgende Funktion implementiert

#define CAN_BUS_OFF  0x00
#define CAN_PASSIVE  0x01
#define CAN_SUCCESS  0x02


int8_t AtCanGetBusState(void)
 {
   if (CANGSTA & (1<<BOFF))
     return CAN_BUS_OFF;
   if (CANGSTA & (1<<ERRP))
     return CAN_PASSIVE;
   return CAN_SUCCESS;
}
jetzt bekomme ich die Meldung nach dem ich die Kabel wieder eingesteckt 
habe.
Gibt es eine Möglichkeit diese Funktion in beliebige Zeit aufzurufen und 
nicht in eine bestimmte Stelle im main aufzurufen. Ich meine beim Laufen 
des Programms wird plötzlich die Kabel gezogen und in der Zeitpunkt 
bekomme ich die passende Rückgabe Wert.
Auf alle Hilfe bin ich sehr dankbar

von Juergen H. (harms)


Lesenswert?

Ich glaube, dass einfach Bus-Kabel ziehen an sich von einem 
CAN-Controller noch nicht als Fehler empfunden wird. Das Problem kommt, 
wenn der Controller ein Meldung sendet und - weil das Kabel gezogen ist 
- niemand am Bus antwortet.

Vorschlag: miss die Zeit, zu der Meldungen zum Senden abgelegt werden 
(z.B. in einer Tabelle mit 15 Eintraegen, einem pro MOb) und, in Deiner 
Warteschleife, schau nach ob eine MOb "zu lange" schon eine gesendet 
werdende Meldung hat. Wenn ja, dann hast Du Deinen Fehler, und Du kannst 
diese Meldung loeschen.

"Zu lange" laesst sich aus der Bitrate und Reserven fuer Behandlung im 
Sender und Empfaenger abschaetzen. Ich verwende zu diesem Zweck das 
obere Bit des CAN Timers (CANTIMH), mein Timer laeuft mit 10 kBps (Bus 
Takt = 100kBps). Hier ist die Prozedur CanCheckWait, die ich in meiner 
Warteschleife periodisch aufrufe (wenn nichts zu tun ist, alle 10 msec - 
jedes Mal wird eine neue MOb geprueft)- meine Tabelle ist in 
can_status.cs_stamp (uint8_t):
1
// Check next MOB for send-hang
2
// ----------------------------
3
//  Consider an MOB as hanging if xmit is not terminated after > 75 msec
4
//
5
//  Return the MOB ordinal if the MOB hangs
6
//  Return -1 if the MOB is OK
7
8
int8_t CanCheckWait ()
9
{
10
    uint8_t    x_mob ;      // ordinal of MOB to check
11
    int8_t    x_wait ;
12
13
    static uint8_t  next_mob = 0 ;    // next MOB to check
14
15
      // Determine which MOB to check
16
      //  - the variable next_mob does a circular walk-trough { 0 .. 14 }
17
      //  - do nothing if the MOB is not transmitting
18
19
    if ( next_mob > 14 ) next_mob = 0 ;    // circular overflow modulo 14
20
    x_mob = next_mob++ ;
21
    CANPAGE = x_mob << 4 ;
22
    if ( ( CANCDMOB & _BV(CONMOB0) ) == 0 ) return -1 ; // OK if not sending
23
24
      // Check the time spent since the launch of the transmission:
25
      //  - cs_stamp is the value of CANTIMH at transmission launch,
26
      //  - the high byte of the CAN-timer (CANTIMH) has increments of
27
      //    25.6 msec (at 10kHz = 0.1 msec increments of CANTIML),
28
      //  - sampling jitter = 25.6 msec due to only considering CANTIMH.
29
      //
30
      // x_wait > 3 ... frame hold detection at 76.8 ... 102.4 mseconds
31
32
    x_wait = CANTIMH - can_status.cs_stamp[x_mob] ;
33
    if ( x_wait < 0 ) x_wait += 256 ;    // handle counter wrap-around
34
    if ( x_wait > 3 ) return x_mob ;
35
    return -1 ;
36
}

von gast (Gast)


Lesenswert?

hallo Juergen,
ich versuche deine Code zu verstehen und auch bei mir zu implementieren 
und melde ich mich wieder.
Ich danke Dir

von gast (Gast)


Lesenswert?

hallo juergen,
habe ich das Datenblatt über Timer/Counter gelesen, weil ich zum ersten 
mal damit beschäftige. In deiner code sehe ich nicht wo Du die Register 
für Timer/Counter gesetzt hat. Wie wählst Du das Timer? Im Datenblatt 
steht dass CANTIML bzw CANTIML nur Leseregister sind.Du sagst, dass Du 
obere Bit des CAN Timers (CANTIMH) verwendest. Außerdem verstehe ich 
diese Zeile: x_wait = CANTIMH - can_status.cs_stamp[x_mob] ;
Bitte kannst Du mir noch einmal mehr Eklärungen geben. Wie muss ich 
zuesrt das Timer setzen?

Ich danke Dir

von Matthias (Gast)


Lesenswert?

Also wenn der Controller sendet und kein ACK bekommt, geht der erstmal 
von

ACTIVE nach ERROR_PASSIVE. Das kann man sich auch mit einem IRQ in einer 
Variablen signalisieren lassen und dann per Vergleicher in der Mainloop, 
eine Änderung detektieren. Dann sollte man in jedem Fall mitbekommen, 
wenn man
vom CAN "abgekoppelt wird". Das schöne ist, dass wenn man das Kabel 
wierder einsteckt, nach einer gewissen Anzahl fehlerfreier Nachrichten, 
der Zustand automatisch wider in den ACTIVE geht.

von Juergen H. (harms)


Lesenswert?

Da habe ich es mir vielleicht etwas leicht gemacht: ich hatte 
verstanden, das der Zustand von ACTIVE nach ERROR_PASSIVE kippt, wenn es 
zufolge IRGENDEINES Fehlers 127mal schief geht, und das als "zu 
kompliziert" links liegen lassen - mein Hauptproblem war, nach 
haengengebliebenen MObs zu fischen. Muss ich mir genauer anschaun.

Zur urspruenglich gestellten Frage: zum Erkennen des Fehlers ist das 
einfacher - aber was geschieht mit dem MOb das der Kontroller nicht los 
wird? - Deine Wahl.

Antwort zu den spezifischen Fragen. Geh zum Artikel in 
http://www.mikrocontroller.net/articles/CAN_Bibiliothek_f%C3%BCr_AT90CAN_Prozessoren
und hole Dir in den Links am Ende die Dateien Can.c und Can.h. Suche 
darin nach can_status.cs_stamp - das zeigt Dir wie diese Variable 
gehandhabt wird ( und wie sie beim Senden eines Frames gesetzt wird). In 
CanInit siehst Du wie CANTCON initialisiert wird - das bestimmt den Takt 
fuer CANTIM, CANTIMH und CANTIML laufen dadurch "von selber". Die Zeile 
mit xmit_wait: sie rechnet die abgelaufene Zeit seit dem Senden aus. In 
can_status.cs_wait liegt der Zeitpunkt (CANTIMH Einheiten) beim Senden, 
das wird mit dem momentanen Wert von CANTIMH verglichen 
(ueberlauf-behandelt) und ergibt "wie alt" der Sendeprozess ist - und 
can_status.cs_stamp ist eine Tabelle, indiziert mit dem MOb Index.

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
Noch kein Account? Hier anmelden.