Forum: Mikrocontroller und Digitale Elektronik Prob mit SJA1000 CAN Bus Controller


von LtData (Gast)


Lesenswert?

Hi,

meine seltsamen Probleme wollen nicht abreissen...
Also ich habe hier einen mega32 an dem ein sja1000 hängt.
Ich kann ihn offensichtlich korrekt ansprechen, denn 
Konfigurationsregister des Controllers können von mir beschrieben werden 
und beim auslesen kommt auch wieder das raus, was ich vorher 
reingeschrieben habe.
Nur das message versenden will einfach nicht klappen. Auf der anderen 
Seite hängt auch ein sja1000, der die Message angeblich korrekt 
empfängt. Der empfängt aber nur Kauderwelsch (erkennt aber trotzdem 
keinen Übertragungsfehler).
Jetzt habe ich den sendenden Kontroller mit "self reception request" 
seine message selbst wieder empfangen lassen. Und sogar er selbst 
empfängt nur Kauderwelsch! Aber immerhin bitgenau den selben 
Kauderwelsch, den auch andere Kontroller auf dem Bus empfangen.
Kann mir da wer nen Tipp geben? Timingprobleme bei der Ansteuerung des 
CAN Controllers kann ich ja ausschliessen, wegen der korrekten Funktion 
der Register.
Aber wenn das Ding noch nicht mal seine eigene Message korrekt 
empfängt....

von ERDI - Soft (Gast)


Lesenswert?

Bustreiber benutzt? Bus abgeschlossen? Kannst du mal den Schaltplan 
posten?

von Schmittchen (Gast)


Lesenswert?

Softwarefehler? Timingprobleme!?

von Markus Kaufmann (Gast)


Lesenswert?

Versuch mal Pakete mit lauter 0x00 oder lauter 0xFF zu senden und schau 
ob Du von den Mülldaten irgendwie auf die echten Daten schließen kannst.

von LtData (Gast)


Lesenswert?

Vorneweg: Mir ist es gelungen eine Message korrekt zu senden und zu 
empfangen.

Dennoch: Ich habe offensichtlich ein totales Brett vorm Kopf.

Das Problem liegt in der Software bzw beim Compiler.

folgender Code funktioniert NICHT und liefert immer die selben 
Mülldaten:

int main(void) {

     boot();

     int buffer[12];

// Eine Testmsg in den TX Buffer schreiben.

  sja1k(0x10,write,0x88);    // EFF Frame Information
  sja1k(0x11,write,0x00);    // Identifier
  sja1k(0x12,write,0x00);
  sja1k(0x13,write,0x00);
  sja1k(0x14,write,0x08);
  sja1k(0x15,write,0xFF);    // 8 Data Bytes
  sja1k(0x16,write,0xCD);
  sja1k(0x17,write,0xEF);
  sja1k(0x18,write,0xF0);
  sja1k(0x19,write,0x12);
  sja1k(0x1A,write,0x34);
  sja1k(0x1B,write,0x45);
  sja1k(0x1C,write,0x67);

  sja1k(0x01,write,0x10);    // msg abschicken mit Self reception

  if (sja1k(0x02,read,0)&0x01) { // im Statusregister schauen ob Receive 
Buffer voll, also ob eine Msg empfangen wurde

// Msg in einem Buffer speichern
    buffer[0] = sja1k(0x10,read,0);
    buffer[1] = sja1k(0x11,read,0);
    buffer[2] = sja1k(0x12,read,0);
    buffer[3] = sja1k(0x13,read,0);
    buffer[4] = sja1k(0x14,read,0);
    buffer[5] = sja1k(0x15,read,0);
    buffer[6] = sja1k(0x16,read,0);
    buffer[7] = sja1k(0x17,read,0);
    buffer[8] = sja1k(0x18,read,0);
    buffer[9] = sja1k(0x19,read,0);
    buffer[10] = sja1k(0x1A,read,0);
    buffer[11] = sja1k(0x1B,read,0);
    buffer[12] = sja1k(0x1C,read,0);
    sja1k(0x01,write,0x04);        // release receive buffer

// msg auf dem Display anzeigen

    lcd_command(0x80);
    lcd_hex_digit(buffer[0]);
    lcd_hex_digit(buffer[1]);
    lcd_hex_digit(buffer[2]);
    lcd_hex_digit(buffer[3]);
    lcd_command(0xc0);
    lcd_hex_digit(0xAA);
    lcd_hex_digit(buffer[5]);
    lcd_hex_digit(buffer[6]);
    lcd_hex_digit(buffer[7]);
    lcd_command(0x90);
    lcd_hex_digit(buffer[8]);
    lcd_hex_digit(buffer[9]);
    lcd_hex_digit(buffer[10]);
    lcd_hex_digit(buffer[11]);
//    lcd_hex_digit(buffer[12]);  // Passt nimmer

        }
}

Folgender Code funktioniert und liefert die gesendete Msg auf das 
Display:

int main(void) {

     boot();

//   int buffer[12];

// Eine Testmsg in den TX Buffer schreiben.

  sja1k(0x10,write,0x88);    // EFF Frame Information
  sja1k(0x11,write,0x00);    // Identifier
  sja1k(0x12,write,0x00);
  sja1k(0x13,write,0x00);
  sja1k(0x14,write,0x08);
  sja1k(0x15,write,0xFF);    // 8 Data Bytes
  sja1k(0x16,write,0xCD);
  sja1k(0x17,write,0xEF);
  sja1k(0x18,write,0xF0);
  sja1k(0x19,write,0x12);
  sja1k(0x1A,write,0x34);
  sja1k(0x1B,write,0x45);
  sja1k(0x1C,write,0x67);

  sja1k(0x01,write,0x10);    // msg abschicken mit Self reception

  if (sja1k(0x02,read,0)&0x01) { // im Statusregister schauen ob Receive 
Buffer voll, also ob eine Msg empfangen wurde

    lcd_command(0x80);
    lcd_hex_digit(sja1k(0x10,read,0));
    lcd_hex_digit(sja1k(0x11,read,0));
    lcd_hex_digit(sja1k(0x12,read,0));
    lcd_hex_digit(sja1k(0x13,read,0));
    lcd_command(0xc0);
    lcd_hex_digit(sja1k(0x14,read,0));
    lcd_hex_digit(sja1k(0x15,read,0));
    lcd_hex_digit(sja1k(0x16,read,0));
    lcd_hex_digit(sja1k(0x17,read,0));
    lcd_command(0x90);
    lcd_hex_digit(sja1k(0x18,read,0));
    lcd_hex_digit(sja1k(0x19,read,0));
    lcd_hex_digit(sja1k(0x1A,read,0));
    lcd_hex_digit(sja1k(0x1B,read,0));
//    lcd_hex_digit(buffer[12]);  // Passt nimmer
                sja1k(0x01,write,0x04);    // release receive buffer

        }
}

Ich hatte mir da schon schöne Funktionen geschrieben, die ein Struct 
"CAN_MSG" benutzen usw. Aber die haben auch alle nicht funktioniert, da 
es anscheinend schon daran scheitert, die Daten simpel in Variablen zu 
speichern. Werden die Daten direkt in die Anzeigefunktion übergeben 
funktioniert es also. Aber warum? Speicher sollte genug da sein. 
Immerhin teste ich mit einem Mega32 mit 2kb SRAM (aber es läuft ja auch 
auf einem AT90S4433 genauso gut bzw schlecht).
Gibts in C irgendwas zu beachten, was ich vielleicht nicht weiss? Hatte 
nie derartige Probleme ein Array zu befüllen (unter Visual C++ hats 
zumindest so immer funktioniert). GCC Einstellugen vielleicht? Hat es 
vielleicht mit dem Rückgabewert der Funktion "sja1k" zu tun (der ist vom 
Typ int)?

von Peter D. (peda)


Lesenswert?

Ein Array aus 12 Elementen mit 13 Daten zu füllen muß ja in die Hose 
gehen.


Peter

von LtData (Gast)


Lesenswert?

Du weisst aber, daß man bei "0" beginnt zu zählen? Also ein int 
array[12] initialisiert ein Array mit 13 Elementen, da die 0 das erste 
Element ist.

von Markus Kaufmann (Gast)


Lesenswert?

Nein, ein array[12] ergibt ein Array mit 12 Werten. Und zwar 0 - 11 .

von LtData (Gast)


Lesenswert?

Stimmt. Hab grad nachgeschaut. Entschuldigung Peter.

Trotzdem ist irgendwo der Wurm drin, denn auch wenn ich mein Array mit 
int buffer[13] initialisiere funktioniert es nicht besser.
nehme ich 13 einzelne Int Variablen, dann geht es übrigens jetzt. Es 
darf halt blos kein Array sein... Was mach ich blos falsch.

von Boris H. (Gast)


Lesenswert?

Hi LtData

Hatte schon mal gepostet, aber niemand wollte mir helfen. Vielleicht 
hattest Du ja das gleiche Problem.
Ich hab nen 82c200 (Vorgänger des sja1000) an einem 8515 hängen.
Mein Problem ist, daß der ab und zu mal die gesendeten Daten nicht 
empfängt. Ist allerdings nicht regelmäßig. Ein gleichzeitig am Bus 
hängender 81c90 hat mit den gleichen Daten keine Probleme. Da Timing ist 
bei beiden identisch eingestellt.

Hast Du eine Idee ?

Gruß
Boris

von Peter D. (peda)


Lesenswert?

Wenn das Array die richtige Größe hat, vielleicht liegts am Typ.

Ich weiß ja nicht, wie sja1k() und lcd_hex_digit() definiert  sind, d.h. 
wie und ob eine Typkonvertierung erfolgt.


Versuch doch mal:

unsigned char buffer[13];



Peter

von LtData (Gast)


Lesenswert?

@Boris

ne da kann ich Dir nicht helfen. Ich bin froh, daß sich zumindest jetzt 
die Controller gegenseitig Messages anscheinend korrekt zuschicken 
können. Derartige Probleme wie Du hatte ich bis jetzt noch nicht. Also 
bisher ist noch jede Nachricht irgendwie angekommen. Blos ganz zu 
Anfang, als noch überhaupt nix funktioniert hat, da hats bei mir am 
Timing gelegen. Vielleicht solltest Du mal ein langsameres Timing 
hernehmen.
Oder mal schauen ob der Controller wenigstens etwas erkennt, d.h. etwas 
in seine Fehlerstatusregister geschrieben hat.

@Peter

die Definitionen lauten wie folgt:
int sja1k(int addresse, enum DIRECTION direction, int data)
void lcd_hex_digit(int digit)

Da sollte also eigentlich keine Typumwandlung stattfinden. Ich  habe 
eigentlich immer für alle Variablen "int" genommen, da es sich ja immer 
um ein Byte handelt.

Aber da gibts noch was komisches: Ich hatte mir für eine Can Msg 
folgendes Struct geschrieben:
struct CAN_MSG {
  uint8_t ident;
  uint8_t id0;
  uint8_t id1;
  uint8_t id2;
  uint8_t id3;
  uint8_t data0;
  uint8_t data1;
  uint8_t data2;
  uint8_t data3;
  uint8_t data4;
  uint8_t data5;
  uint8_t data6;
  uint8_t data7;
};

Zugegeben, daß ich da uint8_t genommen habe, aber das erklärt IMHO nicht 
die Reaktion auf mein Struct. Das Programm lässt sich kompilieren und 
läuft auch zunächst.
eine Zeile wie
struct CAN_MSG can_msg;
wird noch ausgeführt. Bei einer Zeile wie
can_msg.ident = 0x88;
stürzt mein Programm auf dem Atmel aber ab und beginnt wieder ganz von 
vorne. Es bleibt nicht hängen. Ich konnte mir das nie erklären und hab 
daher einfach kein struct mehr benutzt.

Ich werde jetzt erstmal mit anderen Datentypen experimentieren. Wenn ihr 
wollt, kann ich auch mal den kompletten Source posten. Der ist aber 
leider nicht mehr so schön durch das ständige verzweifelte ausprobieren.
Ich denke auch mal, wenn es am GCC (GNU GCC 3.3 20030421 (prerelease) - 
das ist der, den man bei avrfreaks bekommt) liegen würde, dann wäre das 
sicher schon anderen aufgefallen. Oder es ist irgendeine GCC 
Einstellungssache, von der ich nix weiss...

von Peter D. (peda)


Lesenswert?

Generell sollte man immer den passenden Typ nehmen.

D.h. "int" auch nur dann, wenn wirklich 16 Bit benötigt werden und 
"unsigned" immer, wenn negative Werte keinen Sinn ergeben. Z.B. bei 
Daten und Adressen sollte alles positiv, also "unsigned" sein.

"int" ohne "unsigned" davor macht eigentlich nur bei echten Meßwerten 
Sinn (negative Temperatur, Spannung usw.).

Bei logischen Daten und Operationen damit kann Dir das Vorzeichen aber 
die komischsten Effekte verursachen.

Auch wenn Du genügend Speicher hast, bringt es absolut nichts ein Byte 
als "int" zu speichern und damit Ressourcen zu verschwenden.
Jede 8-Bit CPU muß "int" erst umständlich durch Kaskadierung von 
mehreren 8-Bit Operationen simulieren.


Es gibt da auf der Atmel AVR-Seite eine schöne Application Note, wie man 
effektiv und übersichtlich unter C programmiert.


Peter

von LtData (Gast)


Lesenswert?

mittlerweile hab ich alles auf uint8_t umgeschrieben und es funktioniert 
hm... besser. Aber immer noch nicht gut.

Mein struct funktioniert jetzt auch halbwegs. Zumindest stürzt der Atmel 
nicht mehr ab, aber es sind immer noch teilweise falsche Daten 
vorhanden, wie beim Array.
Mit ganz normalen Variablen funktioniert es dagegen gut. Aber man muss 
doch auch mit nem Struct und/oder Array hantieren können...
Mein Struct und mein Array bestehen übrigens logischerweise bisher immer 
aus 13 Bytes. Interessant ist, daß offensichtlich die erstsen 4 Bytes 
korrekt sind, dann kommen 2 falsche, dann 1 richtiges, 2 falsche, 2 
richtige, 1 falsches und das letzte kann ich nicht beurteilen, da es 
nicht mehr auf meinem Display angezeigt wird. Ich kann mir das nicht 
erklären. Den falschen Bytes kommt im Programm keine Sonderbehandlung 
zugute.

von ERDI - Soft (Gast)


Lesenswert?

Kannst du vielleicht mal kurz schildern, wie du den SJA1000 
initialisierst?

von LtData (Gast)


Lesenswert?

Wie meinst Du das? Willst Du den Inhalt der Konfigregister haben? Dazu 
bräuchtest Du auch das Datenblatt.
Initialisiert wird er übrigens über die selbe Funktion ("sja1k"), die 
oben verwendet werden.
Na egal ich poste einfach mal meine Initialisierungsbefehle:

  sja1k(0x00,write,0x01);    // RESET MODE aktivieren
  sja1k(0x1f,write,0xC9);    // Peli CAN MODE und andere Einstellungen 
vornehmen
  sja1k(0x06,write,0xC7);    // Register BTR0 schreiben
  sja1k(0x07,write,0xD7);    // Register BTR1 schreiben
  sja1k(0x08,write,0xDA);    // push & pull output
  sja1k(0x04,write,0x00);    // Interrupts erstmal ausschalten
  sja1k(0x00,write,0x00); // zurueck in den Normal Mode: ferig!

Wie gesagt es kann ja eigentlich nicht am SJA liegen, denn mit 13 
einzelnen Variablen gehts ja und mit einem Array mit 13 Elementen gehts 
nicht.
Ob ich wohl einfach mal nen anderen GCC runterladen sollte?

von Leonhardt (Gast)


Lesenswert?

Hallo !

Ich will mit dem AVR 8535 CAN Botschaften senden und empfangen.
Dazu verwende ich einen SJA1000.
Kann mir jemand dazu Infos geben? (Hardwareaufbau und Software)

Ich habe keinen Plan!!!

von Werner (Gast)


Lesenswert?

@Leonhardt:
Es ist auf jeden Fall ganz wichtig, das Du möglichst viele Threads
aufmachst und in ganz vielen Beiträgen mehrfach deine Hilferufe
postest. Dann wird dir bestimmt geholfen.
Andere hätten vielleicht nur gesagt: Wer suchet der findet..

von Boris (Gast)


Lesenswert?

Oder kurz gesagt : http://www.canathome.de/

B.

von Michael (Gast)


Lesenswert?


von Sascha (Gast)


Lesenswert?

Hallo!

@LtData

Bin auch dabei einen SJA1000 mit einem AVR anzusteuern! Könntest Du mir
Deinen Source zukommen lassen? Wäre prima!


Falls natürlich sonst noch jemand mir helfen kann (und will), bin ich
um jede Hilfe verlegen..


Gruß,

Sascha

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.