Forum: Mikrocontroller und Digitale Elektronik CAN: Nachrichten gehen verloren


von Tobi (Gast)


Lesenswert?

Moin

ich habe vor an einen CAN-Bus mehrere AT90CAN128 zu hängen. Als CAN 
Software benutze ich den aktuellen Treiber von Atmel. Empfangen werden 
die Daten über eine SIG_CAN Interruptroutine.

CAN 1: sendet 100 CAN Nachrichten
CAN 2: empfängt und gibt die Bytes über den UART aus
CAN 3: empfängt maskiert (wertet also keine Nachricht aus)

So, jetzt das Problem:
Wenn CAN 1 100 Nachrichten schnell hintereinander sendet (CMD_TX_DATA) 
empfängt CAN 2 (CMD_RX) nur jede 12. Nachricht.
Kann ich irgendein Bit setzen oder irgendein Nachrichtentyp verwenden, 
damit der Sender mitbekommt, dass die Daten von CAN 2 nicht richtig 
empfangen wurden. Und er die Daten nochmal sendet.


Hier nachmal die wichtigsten Passagen vom Code. Der Rest ist der 
Standard von Atmel.

unsigned char can_get_MOB_int(void)
{
  unsigned char i;
  for(i=0;i < 8; i++)  // MOB 0 - 7 durchsuchen
  {
  if(!CHECKBIT(CANEN2,i)) return (i); // Falls Daten enthalten sind, die 
Nummer zurück geben
  }

  for(i=8;i < 15; i++)   // MOB 8 - 9 durchsuchen
  {
  if(!CHECKBIT(CANEN1,(i-8))) return (i); // Falls Daten enthalten sind, 
die Nummer zurück geben
  }

  return (0xFF);  // 0xFF zurückgeben, wenn nichts gefunden wurde
}

SIGNAL (SIG_CAN_INTERRUPT1)
{

  unsigned char temp;
         unsigned char buffer[8];

  unsigned long int u32_temp;

  st_cmd_t msg;    // Strukur für die CAN Message
  msg.pt_data = &buffer[0];
  msg.handle=can_get_MOB_int();//MOB finden
         can_get_status(&msg);  //Daten werden ausgelesen

  Can_get_ext_id(u32_temp)
  printf("%u %i=> %i,%i,%i,%i,%i,%i,%i,%u\n",(unsigned int) 
u32_temp,msg.handle,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],bu 
ffer[5],buffer[6],buffer[7]);

  SETBIT(CANCDMOB,7);  //MOB wieder für den empfang freigeben
  temp=CANSTMOB;      //im CAN Status Register den Receive Interrupt 
löschen
  CLEARBIT(temp,RXOK);
  CANSTMOB=temp;
}

Danke im Voraus
Tobi

von pschober (Gast)


Lesenswert?

Hallo Tobi
der Grund dafür, dass Du nur jede 12.te Nachricht empfängst, dürfte der 
Aufruf von printf im CAN Interrupt sein, welche den Interrupt ziemlich 
lange blockiert.

Gruss
Philipp

von Stefan K. (_sk_)


Lesenswert?

printf("%u %i=> %i,%i,%i,%i,%i,%i,%i,%u\n",(unsigned int)
u32_temp,msg.handle,buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],bu 
ffer[5],buffer[6],buffer[7]);

So ein printf-Monster im Interrupt - das ist wirklich mutig.


1. Im CAN-IR die Daten in ein Fifo schreiben
2. in main das Fifo leeren und auf den UART ausgeben
3. Das Fifo gross genug machen
4. die msg-Daten in main in einen String wandeln
5. den String per IR ausgeben
6. währenddessen einen 2.String von main vorbereiten lassen

bdw.:
wie schnell ist Dein CAN?
wie schnell ist Dein UART?
wie schnell ist Dein ATmega?

Gruß, Stefan

von Tobi (Gast)


Lesenswert?

Danke für die schnellen Antworten

Mein CAN läuft mit 100kHz
UART 9600
AT90CAN128 16MHz

Ich weiß, dass die printf Ausgabe den ganzen Controller ausbremst. Es 
soll auch in erster Linie zur Kontrolle sein und später auch 
rausfliegen. Aber trotzdem kann es sein, dass der Controller in 
irgendeiner Form beschäftigt ist und er Nachrichten vom CAN nicht 
mitbekommt.
Ich dachte, dass der CAN-Bus das vielleicht alles selber regeln kann. 
Also, wenn irgendeine Nachricht nicht "richtig" empfangen wurde er diese 
einfach nochmal schickt.

Ich habe jetzt den CAN-Controller nach der ISR disabled, die Daten 
ausgewertet und dann wieder enabled. Das funktioniert auch alles 
wunderbar, wenn es nur einen Sender und einen Empfänger gibt. Der Sender 
schickt die Nachrichten, bis diese empfangen werden. Es kommen also alle 
Daten an.
Wenn jetzt der 2. Empfänger dran ist, empfängt er hat eben die Daten 
solange der 1. Empfänger die Daten auswertet. Und so bekommt der 1. 
Empfänger auch nicht alle Nachrichten mit.

Tobi

von Stefan K. (_sk_)


Lesenswert?

>Mein CAN läuft mit 100kHz
>UART 9600

wie soll das gehen?
Dein String ist ca. 45 Byte = 450 Bit lang. Braucht bei 9600Baud ca. 
50ms. In der Zeit kann der CAN 39 komplette msgs verschicken!

>Also, wenn irgendeine Nachricht nicht "richtig" empfangen wurde er diese
>einfach nochmal schickt.

Den CAN schert es nicht, ob ein anderer Busteilnehmer mit de empfangenen 
Datenmengen Probleme hat (das ist auch ganz gut so, sonst könnte ein 
lahmer Busteilnehmer den kompletten Bus lahmlegen).

Ausnahme:
Wenn es nur einen empfangenden Busteilnehmer gibt und dieser sendet kein 
ACK auf die msg, dann wiederholt der Sender die msg ständig.
Das ist der Grund, warum Dir keine Daten verlorengehen, wenn nur 1 Tln 
am Bus hängt und dessen CAN disabled wird - der Sender wiederholt die 
Daten solange, bis der Empfänger wieder enabled wird. Dies ist aber ein 
Sonderfall am Bus, auf den Du nicht bauen kannst.

1. Warum 100khz?
   Lass den CAN nur so schnell laufen, wie Dein Programm auch arbeiten
   kann.

2. Warum nur 9600 Baud?
   115kbaud sind eigendlich kein Problem. Aber beachte: auch das wird 
Dir
   einen kontinuierlichen Datenempfang nicht sicherstellen, weil aus
   128 Bit auf dem CAN ca. 450 Bit auf der RS232 werden, weil Du die
   Binärdaten vom AVR in ASCII-Daten umwandelst.

3. printf aus der IR raus und ein Fifo einbauen!

Gruß, Stefan

von Tobi (Gast)


Lesenswert?

Danke

dass der UART rausfliegt ist keine Frage.

Und wenn ich das richtig verstanden habe, muss ich ich selber dafür 
sorgen, dass der CAN-Bus immer empfangstbereit ist. Werde jetzt mal ein 
FIFO programmieren.


Gruß
Tobi

von Peter D. (peda)


Lesenswert?

Du mußt mehrere MOBs zu einem Puffer zusammenfügen, damit Du einen 
auswerten kannst, während der andere schon reinkommt.

Aber Achtung, dabei kann sich die Paketreihenfolge vertauschen !


Meistens wird aber ein ganz einfaches Protokoll verwendet:
Von jedem Pakettyp (Identifier) wird nur ein Paket gesendet und dann auf 
eine Antwort (Bestätigung) gewartet, ehe das nächste gesendet wird 
(Ping-Pong-Prinzip).


Peter

von Tobi (Gast)


Lesenswert?

Das alles habe ich bisher mit einem aktiven MOB getestet, wenn ich mehr 
MOBs aktiviere erhalte ich natürlich mehr Nachrichten. Das ist klar. Ich 
wollte jetzt erstmal prinzipell das geklärt haben.

Dieses Pin-Pong-Prinzip habe ich mir auch schon überlegt, ist aber 
natürlich mit mehr Software verbunden.

Kann das vielleicht der CAN-Bus übernehmen?

Auf Seite 243/244 steht etwas von Automatic Reply. Aber wenn ich das 
richtig verstehe antwortet ein Teilnehmer mit einem Daten-Frame auf ein 
Remote-Frame.
Was ich suche ist eine automatische Bestätigung auf ein Daten-Frame.

Gruß
Tobi

von michael (Gast)


Lesenswert?

Hallo Dubbia!

Du musst das printf rausnehmen und durch FiFo ersetzen!

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.