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....
Bustreiber benutzt? Bus abgeschlossen? Kannst du mal den Schaltplan posten?
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.
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)?
Ein Array aus 12 Elementen mit 13 Daten zu füllen muß ja in die Hose gehen. Peter
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.
Nein, ein array[12] ergibt ein Array mit 12 Werten. Und zwar 0 - 11 .
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.
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
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
@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...
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
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.
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?
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!!!
@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..
Vielleicht liegts am BitTiming?! (siehe http://www.elektroniknet.de/topics/automatisieren/fachthemen/artikel/1997/ek9722b_1.htm) Gruss Michael
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.