Forum: Mikrocontroller und Digitale Elektronik CAN-USB SJA1000T <-> AT90CAN128


von Johannes H. (kuriboh)


Lesenswert?

Mein Ziel ist es ein CAN-Board (1) AT90CAN128 über ein Flachbandkabel 
(mit 120 Ohm an jedem Ende zwischen CAN_H und CAN_L) mit einem CAN-USB 
SJA1000T Adapter (2) anzusteuern

Ich kann keine Nachricht vom PC aus versenden, weder mit angeschlossenem 
noch mit abgehängtem CAN-Board (1).

Der CAN-USB (2) Adapter zeigt mit seiner roten LED immer einen 
BUS-Fehler an sobald ich versuche zu senden.

Auf dem CAN-Board läuft ein selbstgeschriebender Code (3). Die 
konfiguration des SJA1000T ist BRT0 = 04; BRT1 = BA;

Ich suche seit 2 Wochen den Fehler und komme nicht mehr weiter, die 
Forensuche liefert interessantes aber leider nichts passendes. Der 
Händler verweist mich auf den Entwickler, der Entwickler hat mir noch 
nicht antworten können.

(1) http://www.olimex.com/dev/pdf/AVR/AVR-CAN.pdf
(2) http://elmicro.com/files/lawicel/canusb_manual.pdf
(3)
1
#include <avr/io.h>
2
#include <stdio.h>
3
#include <avr/interrupt.h>
4
#include <avr/pgmspace.h>
5
#include "avr/wdt.h"
6
7
void LedInit () {
8
  DDRE = 0x10;
9
  PORTE = 0x00; /*Die Logik der LED ist invertiert 0=AN*/
10
}
11
12
ISR ( CANIT_vect )
13
{
14
  cli(); /* Interrupts abschalten */
15
  if (PORTE == 0xFF){PORTE = 0x00;}
16
      else {PORTE = 0xFF;};
17
18
  
19
  /*Reset the Object for further use - wir wissen dass es objekt 1 war*/
20
  CANCDMOB = 0x88; /* Empfang und DLC 8 Byte */
21
  CANIDT4 = 0x00; /*RTRTAG, RB0TAG*/
22
  CANIDT3 = 0x00; /*Initialized for compatibility Reasons, does nothing*/
23
  CANIDT2 = (uint8_t) (0x124 << 5); // 0001 0010 0(100 X XXXX)  
24
  CANIDT1 = (uint8_t) (0x124 << 3); // (0001 0010 0)100
25
  for ( uint8_t i_msg = 0; i_msg < 8 ; i_msg++){
26
      CANMSG = 0x00; /* Messageobjekt löschen */
27
      /* Der µC inkrementiert INDX automatisch. 
28
      Im übertragenen Sinn enthält 
29
      CANMSG[INDX] die Nachrichten.
30
      CANPAGE:3 enthält NOT(AINC)*/
31
    }
32
  sei(); /* Interrrupts einschalten */
33
}
34
35
void CanInit ()
36
{
37
    CANGCON = 0x01 ; /* Reset CAN interface */
38
  CANGIE = 0x00; /* CAN interrupts zunächst aus */
39
  
40
// Disable Message Objects
41
    for ( uint8_t i_mob = 0; i_mob < 15; i_mob++ ) {
42
    /* Select the right MOB-Page */
43
    CANPAGE = i_mob << 4 ;
44
    /* Reset and Disable MOB */
45
    CANSTMOB = 0; //Status Register
46
    CANCDMOB = 0; //Control Register
47
    CANIDT1 = 0x00; //IDT
48
    CANIDT2 = 0x00; //IDT
49
    CANIDT3 = 0x00; //IDT
50
    CANIDT4 = 0x00; //IDT
51
    CANIDM4 = 0x00; //Maske
52
    CANIDM3 = 0x00; //Maske
53
    CANIDM2 = 0x00; //Maske
54
    CANIDM1 = 0x00; //Maske
55
    for ( uint8_t i_msg = 0; i_msg < 8 ; i_msg++){
56
      CANMSG = 0x00; /* Messageobjekt löschen */
57
      /* Der µC inkrementiert INDX automatisch. 
58
      Im übertragenen Sinn enthält 
59
      CANMSG[INDX] die Nachrichten.
60
      CANPAGE:3 enthält NOT(AINC)*/
61
    }
62
    
63
  }
64
/* Initialiesieren von MOB-PAGE 1 auf Empfang*/
65
  CANPAGE |= 1 << 4 ; /* MOB-Page 1 auswählen */
66
  CANCDMOB = 0x88; /* Empfang und DLC 8 Byte */
67
  CANIDT4 = 0x00; /*RTRTAG, RB0TAG*/
68
  CANIDT3 = 0x00; /*Initialized for compatibility Reasons, does nothing*/
69
  CANIDT2 = (uint8_t) (0x124 << 5); // 0001 0010 0(100 X XXXX)  
70
  CANIDT1 = (uint8_t) (0x124 << 3); // (0001 0010 0)100
71
  CANIDM4 = 0x00; /*RTRMSK, IDEMSK*/
72
  CANIDM3 = 0x00; /*Initialized for compatibility Reasons, does nothing*/
73
  CANIDM2 = (uint8_t) (0x7F0 << 5); // 0111 1111 0(000 X XXXX) 
74
  CANIDM1 = (uint8_t) (0x7F0 << 3); // 0(111 1111 0)000
75
    /* Resulting Span
76
    Mask 0x7F0 111 1111 0000
77
    IDT  0x124 001 0010 0100
78
    Results in
79
    First IDT 001 0010 0000 = 0x120
80
    Last IDT 001 0010 1111 = 0x12F */
81
82
/* General Interrupt Mask*/
83
CANGIE = 0xA0;
84
/* MOB Interrupt Mask*/
85
CANIE2 =0x02;
86
CANIE1 =0x00;
87
/*Set Bit Timing BPR 4, PRS 6, PHS1 3, PHS2 3, SJW 0 */
88
CANBT1 = 0x08;
89
CANBT2 = 0x0C;
90
CANBT3 = 0x37;
91
92
    // Start CAN interface
93
94
    CANGCON = _BV(ENASTB) ;
95
96
      // (Active wait!!) Wait until the CAN interface is ready
97
98
    while ( !( CANGSTA & ( 1 << ENFG ) ) ) ;
99
}
100
101
void InitDevices(){
102
cli(); /* Interrupts aus */
103
MCUSR = 0;
104
wdt_disable();  //Watchdog abschalten
105
CanInit (); /* CAN initialisieren */
106
LedInit();
107
sei(); /* Interrupts ein */
108
}
109
110
int main(void) 
111
{  InitDevices();
112
  while(1){}
113
  return 0;
114
}

von Johannes H. (kuriboh)


Lesenswert?

Ein anderer Testaufbau:

Ich habe auf dem Can-Board von oben den Code aus 
Beitrag ""Hello World" für CAN mit AT90CAN in C"
CAN_Hello_World.zip
laufen mit der einzigen Änderung 8MHz in dem config header.

Wenn der Adapter der einzige Knoten am Bus ist oder er in der Luft hängt 
erhalte ich folgenden Fehler:
"BUS_ERROR"

Wenn das AT90USB128 Board am Bus hängt erhalte ich
"BUS_ERROR"
"ERROR_WARNING"
"ERROR_PASSIVE"

Was kann ich noch tun?
Ich muss meine Diplomarbeit abschließen und es klappt einfach nichts 
mehr.

Gibt es eine Mindestlänge für den CAN-BUS?
Mein Flachbandkabel ist 10 cm lang, auf jeder Seite hängen 120 Ohm 
zwischen CAN_H und CAN_L.

Welche Ursachen kann "BUS_ERROR" haben?

von Johannes H. (kuriboh)


Lesenswert?

Ich habe einen weiteren CANUSB Adapter gekauft:
http://elmicro.com/files/lawicel/canusb_manual.pdf
der gleiche Fehler.

Hat jemand Ideen für weitere grundsätzliche Test mit denen ich dem 
Fehler auf die Spur kommen kann?

von madler (Gast)


Lesenswert?

Wenn Du nur einen Knoten hast, werden die gesendeten CAN-Nachrichten von 
niemanden bestaetigt, das wird Dein Adapter wohl als Fehler melden.
Da ich keinen Deiner Adapter kenne, kann ich Dir aber nicht sagen, was 
es genau fuer eine Meldung gibt.

Wenn Du einen zweiten Adapter ranhaengst, musst Du in diesem auch 
konfigurieren, das er die von Dir gesendeten Pakete akzeptiert und 
bestaetigt (acceptance mask heisst das oft).

Das Kabel kann nicht zu kurz sein. Wenn Du Sorgen hast wegen der 
Uebertragung schalte doch auf zB 100KBit/s um.

Ansonsten wuerde ich empfehlen mal mit einem Oszi auf dem Bus zu 
lauschen, was dort zu sehen ist (insbesondere ACK-Slot), erklaert Dir zB 
der wikipedia-Artikel zu CAN.

von Johannes H. (kuriboh)


Angehängte Dateien:

Lesenswert?

Ich komme erst Mittwoch zu einem Oszi.

Ich habe meinen Code komplett überarbeitet und anhand von Beispielen 
einen neuen geschrieben der die AVR Biliothek verwendet.

Folgende zwei Knoten habe ich:
(1) http://www.olimex.com/dev/pdf/AVR/AVR-CAN.pdf
(2) http://elmicro.com/files/lawicel/canusb_manual.pdf

(1) AVR-CAN ist mit angefügtem Code versehen.
(2) canusb ist mit 100 kBit an den Bus angeschlossen.

Das Experiment funktioniert nun genau anders herum:
Einmal pro Sekunde sendet Knoten (1) eine Nachricht und Toggelt seine 
LED
Knoten 2 soll die Nachricht empfangen. Am PC sehe ich keine Nachrichten.

Hat jemand einen AT90CAN128 zur Hand und kann den Code in einem anderen 
CAN Aufbau testen?
AT90CAN128, FOSC 16 MHz, CAN_BAUDRATE 100 kBit/s, Eine LED an PE4

von Johannes H. (kuriboh)


Angehängte Dateien:

Lesenswert?

Ich fühle mich als ob ich keinen Ansatzpunkt mehr habe. Ich habe 
mittlerweile alle Beiträge die AT90CAN im Betreff haben durchgelesen und 
erkenne das Problem nicht.

Ich habe noch ein Minimalbeispiel geschrieben.
Diesmal soll der USBAdapter irgendwas an den AT90CAN senden. Wieder 
BUS_ERROR beim Senden auf Seite des USBAdapters. Zur Sicherheit poste 
ich das Minimalbeispiel, morgen Abend baue ich ein neues Kabel...

von (prx) A. K. (prx)


Lesenswert?

Wie schon erwähnt wurde muss in einem CAN Bus neben der sendenden Node 
noch eine weitere empfangsbereite Node sein, sonst gibt es mit 
Sicherheit einen Bus Error, weil das ACK Bit nicht gesetzt wird. 
Allerdings setzt jede Node, die den Frame als korrekt ansieht, dieses 
Bit. Nicht nur diejenige, die sich dafür auch inhaltlich interessiert. 
Filter sind hierbei also nicht relevant.

Wenn in einer korrekten CAN Verdrahtung bei gleicher Bitrate stets ein 
Bus Error auftritt, dann kommt man nicht umhin, sich das Signal mal 
anzusehen.

Hier sieht es aber eher so aus, als ob der AVR nicht wirklich am Bus 
teilnimmt, oder mit der falschen Rate.

von Harald (Gast)


Lesenswert?

Grundsätzlich solltest Du mal einen Test machen, ob es mit einer 
fertigen CAN-Library funktioniert:
http://www.kreatives-chaos.com/artikel/universelle-can-bibliothek

Ich habe diese LIB mal für einen AT90CAN128 angewendet, sie funktioniert 
hervorragend und auf Anhieb.

Du solltest Dir schnellstens Zugang zu einem digitalen Scope verschaffen 
(sollte kein Problem sein, wenn das deine Diplomarbeit ist), dann kannst 
Du die reale Bitrate ausmessen. Alternativ mit dem PC-Tool mal alle 
Bitraten durchgehen, vielleicht kommt man so auf den Fehler.

von madler (Gast)


Lesenswert?

Hmmm. Habe gerade mal ueber Deinen Code (09CAN_TRY_ACK) geschaut, sieht 
ja eigentlich gut aus.
Ich bekomme meine CAN128 Platine leider erst Ende des Monats...

Nur nicht aufgeben, es liegt bestimmt an etwas ganz bloedem.
Du solltest jetzt Schritt fuer Schritt vorgehen und da wuerde ich auf 
der untersten Ebene anfangen, dh mal das Oszi dranhalten.
Sendet der CAN128 mit Deinem/dem HelloWorld-Testprogramm, kommts am 
richtigen Pin am CAN-Adapter an, stimmt die Baudrate, etc? Dann ev die 
andere Richtung. Wenn das Senden mit dem CAN128 dann klappt sollte auch 
empfangen klappen.

Nochmal zum Verstaendnis: Was meintest Du oben mit "8MHz in dem config 
header" umgeaendert? Alle Hardware und Beispiele haben und brauchen doch 
16Mhz oder?
Und hast Du jetzt zwei CAN-Adapter (und den CAN128) oder nur einen?
Hast Du mal die Pin-Belegung des CAN-Adapters irgendwo ueberprueft, ich 
sehe die im PDF nirgendwo.

von Plan (Gast)


Lesenswert?

Weil Du ja jetzt noch kein Oszi hast, Du kannst ja mal LEDs an die Rx Tx 
Pins an schließen. Dann siehst Du wenigstens ob ein Telegramm raus 
geht...

von Johannes H. (kuriboh)


Lesenswert?

@ madler, Ich glaube Du hast Da was wichtiges aufgestöbert. Ich habe 
laufend vorausgesetzt dass die Schnittstelle genormt ist. Es scheint mir 
als ob das Olimex Board falsch verbunden ist.

Standard http://www.interfacebus.com/Can_Bus_Connector_Pinout.html
canusb http://www.canusb.com/products.htm
AVR-CAN http://www.olimex.com/dev/pdf/AVR/AVR-CAN.pdf
@ madler, Ich glaube Du hast Da was wichtiges aufgestöbert. Ich habe 
laufend vorausgesetzt dass die Schnittstelle genormt ist. Es scheint mir 
als ob das Olimex Board falsch verbunden ist.

Standard http://www.interfacebus.com/Can_Bus_Connector_Pinout.html
canusb http://www.canusb.com/products.htm
AVR-CAN http://www.olimex.com/dev/pdf/AVR/AVR-CAN.pdf
1
  Standard   canusb          AVR-CAN
2
1 Reserved   12V / 5V / nc   NC
3
2 CAN_L      CAN_L           TXD0
4
3 CAN_GND    CAN_GND / nc    RXD0
5
4 Reserved   nc              NC (not connected through R14 to pin 6)
6
5 CAN_SHLD   nc              GND 6 NC (not connected through R14 to pin 4)
7
6 GND        CAN_GND / nc    NC (not connected through R13 to pin 8)
8
7 CAN_H      CAN_H           NC (not connected through R13 to pin 7)
9
8 Reserved   nc              NC (not connected through R13 to pin 7)
10
9 CAN_V+     12V / 5V / nc   NC
Danke für all die Tips, ich werde das Heute durchprobieren.
-Verbindungen im Olimexboard durchmessen
-physikalische Verbindeung erneuern
-LEDs and den Bus hängen
-Den CAN Status mit LEDs herausleiten
-Die CAN Bibliothek verwenden (universelle-can-bibliothek)

Um einige offenen Fragen zu beantworten:
8MHz waren falsch, das CAN-Board ist mit externen 16 MHz getaktet. Ich 
mache das mittlerweile richtig, sollte auch in der 09CAN_TRY_ACK richtig 
enthalten sein.

Insgesamt habe ich folgende Hardware zuhause:
Drei mal http://www.olimex.com/dev/pdf/AVR/AVR-CAN.pdf
Zwei mal http://elmicro.com/files/lawicel/canusb_manual.pdf

EDIT: Postingfehler

von pcb (Gast)


Lesenswert?

Schaue doch eine halbe Seite im Datenblatt tiefer:
1
  Standard | canusb        | AVR-CAN:     ABER!!   AVR-CAN: CAN
2
                              RS232 Buchse:    |   CAN Stecker:
3
1 Reserved   12V  5V  nc     NC                     NC
4
2 CAN_L      CAN_L           TXD0                   CANL
5
3 CAN_GND    CAN_GND / nc    RXD0                   GND
6
4 Reserved   nc              NC                     NC
7
5 CAN_SHLD   nc              GND                    NC  
8
6 GND        CAN_GND / nc    NC                     GND
9
7 CAN_H      CAN_H           NC                     CANH
10
8 Reserved   nc              NC                     NC
11
9 CAN_V+     12V  5V  nc     NC                     VIN

von Johannes H. (kuriboh)


Lesenswert?

Ah, Wunschdenken...
Ich habe mich über das falsch verbundene so gefreut - ich hatte es aus 
dem RS232 übernommen... Hier die richtige Tabelle (Editierberechtigt zum 
obigen Post bin ich wohl nicht mehr.

Standard http://www.interfacebus.com/Can_Bus_Connector_Pinout.html
canusb http://www.canusb.com/products.htm
AVR-CAN http://www.olimex.com/dev/pdf/AVR/AVR-CAN.pdf
1
  Standard   canusb          AVR-CAN
2
1 Reserved   12V / 5V / nc   NC
3
2 CAN_L      CAN_L           CANL
4
3 CAN_GND    CAN_GND / nc    GND
5
4 Reserved   nc              NC
6
5 CAN_SHLD   nc              NC
7
6 GND        CAN_GND / nc    GND
8
7 CAN_H      CAN_H           CANH
9
8 Reserved   nc              NC
10
9 CAN_V+     12V / 5V / nc   VIN

(EDIT: Ah, es gab gleich eine Antwort - darum nicht berechtigt ^^)

von Johannes H. (kuriboh)


Lesenswert?

So,... Errorcodes habe ich mir noch nicht herausgelegt, aber:
1. Olimex CAN-AVR hat bereits einen eingebauten 120 Ohm Terminator. Ich 
hatte demnach grundsätzlich zuviele Endwiederstände im System.
2. Eine LED die zwischen CAN_L und CAN_H hängt geht in Dauerleuchten 
über wenn der Adapter versucht zu senden.
3. Eine LED die zwischen CAN_L und CAN_H hängt leuchtet gar nicht wenn 
der AVR-CAN versucht zu senden.

Ich vermute dass hier der Hund begraben ist.
Muss ich zu irgendeinem Zeitpunkt definieren WO genau die CAN Pins sind?

von Johannes H. (kuriboh)


Lesenswert?

"Nur nicht aufgeben, es liegt bestimmt an etwas ganz bloedem."

Ich habe den Fehler gefunden, die meisten codes die ich geschrieben habe 
sind fehlerfrei. Problem war die Versorgungsspannung.

Das Olimex hat einen Versorgungsbereich von 5V bis 9V, da ich recht 
vorsichtig bin habe ich 5V eingestellt - vermutlich aus 
Messgenauigkeitsgründen waren das wohl real unter 5V. Ich bin auf 5V3 
hoch gegangen und sofort funktionieren meine Codes.

Für die Nachwelt, und um auch was beizutragen, werde ich für das 
Olimex-Board CAN-AVR AT90CAN128 vier Minimalbeispiele mit WinAVR in GCC 
erzeugen und hier posten. (Die Schlagwörter sind für Suche.)

1. Senden einer Nachricht auf Knopfdruck.
2. Empfang einer Nachricht über Interrupt.
3. Empfan einer Nachricht über Polling.
4. Antwort auf eine RTR Nachricht.

Ich bedanke mich für die Hilfe und bin offen für weitere 
Minimalbeispielvorschläge.

von Johannes H. (kuriboh)


Angehängte Dateien:

Lesenswert?

Aus Zeitgründen gehe ich doch direkt dazu über eine Bibliothek zu 
schreiben. Hier zwei funktionierende "Minicodes".

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.