Hallo! Ich habe den SJA1000 (CAN-Controller) an meinem AVR 8535 angeschlossen. PORTB und PORTD. Irgendwie schaffe ich es einfach nicht den SJA1000 korrekt anzusprechen! Siehe Quellcode Kann mir jemand erklären was ich da falsch mache????
Du must das Timing simulieren, wie es ein 8515 ausgibt, bzw. wie es im SJA1000 Datenblatt steht: Schreiben: Datenbus als Ausgang ALE = 1 Adresse ausgeben ALE = 0 Daten ausgeben WR = 0 WR = 1 Lesen: Datenbus als Ausgang ALE = 1 Adresse ausgeben ALE = 0 Datenbus als Eingang (hochohmig) RD = 0 Daten einlesen RD = 1 Peter
Hallo Peter! Vielen Dank für die schnelle Antwort. Wenn dies hier dann einhalte, dann muss es zu 100% funktionieren??? Hast du meinen Quellcode gesehen???
So habe jetzt die änderungen vorgenommen. Leider funktioniert es noch immer nicht. Ich kann einfach z.B. das Register 4 nicht auslesen. Siehe Quellcode!
Ich habe das DDRB Register auf 0x00 gesetzt. So ein misst es funktioniert noch immer nicht. Ha...was kann da noch tun???
Die Signale ALE, RD und WR (Portpins) müssen IMMER auf Ausgang geschaltet werden. Der Port B muss VOR dem Schreiben auf Ausgang geschaltet werden. Genauso muss er VOR dem Lesen auf Eingang geschaltet werden. Am besten jeweils innerhalb der Routinen lesen() und schreiben(). Stefan
Hallo zusammen! Aufgrund der vielen Nachfragen hier im Forum habe ich mal meine SJA-1000 Funktionen so gut wie möglich versucht zu extrahieren. Leider ist dieser Code noch nicht auf AVRs/MSPs/PICs oder was auch immer getestet (hatte noch keine Zeit), aber falls da jemand interesse hat, kann ich diesen Code gerne zur Verfügung stellen. Ich habe das ganze mit Absicht nicht in die Codesammlung gestellt, da eigentlich noch eine ganze Menge Doku fehlt und der Code, wie gesagt, noch nicht getestet ist. Natürlich stehe ich euch zur Verfügung, wenn ihr das einsetzen wollt! Gruß, Patrick...
Hallo OldBug! Also für den Code würde ich mich interessieren. Kannst du mir diesen Code per Mail zusenden???
Hier habe ich mal einen Ausschnitt aus meinem C Programm gepostet. Kann mir da jemand sagen was ich da falsch gemacht habe, Ich komme nicht weiter! void init(void) { PORTB = 0; DDRB = 0xFF; PORTD = 0; DDRD = 0xFF; ALE = 0; RD = 1; WR = 1; } void schreiben(unsigned char adresse) { init(); ALE = 1; PORTB = adresse; ALE = 0; PORTB = 0x11; WR = 0; WR = 1; } unsigned char lesen(unsigned char adresse) { init(); ALE = 1; PORTB = adresse; ALE = 0; DDRB = 0x00; RD = 0; daten = PORTB; RD = 1; return daten; } void main(void) { schreiben(0x04); sprintf(text," Daten = %3.0u",lesen(0x04)); lcd_gotoxy(0,0); lcd_puts(text); while (1) {}; }
Dem Schreiben sollte man vielleicht auch Daten übergeben ? Und daß Init immer RD und WR auf 0 setzt, dürfte auch gegen den Baum laufen. Peter
Hallo Peter! Ja was meinst du genau? Könntest du mir den Code korrektieren? Ich wäre dir sehr dankbar. Sorry, bin leider kein AVR Experte! Ich bin halt auf hilfe angewiesen
Ok, den Funktionen übergebe ich ja die Parameter! z.B. 0x04
Würde den Controller im extern Ram Modus betreiben und so den CAN Controller ansprechen. Funktioniert besser bezüglich Timing. www.candip.com/candip-avr.htm Josef
"Sorry, bin leider kein AVR Experte!" Das Datenblatt ist Dein Freund und nicht nur dazu da, daß die Hersteller ihren Webspace voll kriegen. "Ich bin halt auf hilfe angewiesen" Und warum beachtest Du dann meine Hilfe nicht ? "Dem Schreiben sollte man vielleicht auch Daten übergeben. Und daß Init immer RD und WR auf 0 setzt, dürfte auch gegen den Baum laufen." Peter
Hallo Peter! Beider schreib-Routine übergebe ich zuerst die Adresse und dann die Daten. Sihe Code --> PORTB = 0x11. Bei der Init-Routine setze ich das RD und WR auf EINS. Das sind Low-aktive eingänge. Oder verstehe ich da jetzt was falsches???
void init(void) { PORTB = 0; DDRB = 0xFF; PORTD = 0; DDRD = 0xFF; ALE = 0; RD = 1; WR = 1; } void schreiben(unsigned char adresse) { init(); ALE = 1; PORTB = adresse; //Hier übergebe ich zuerst die Adresse z.B. 0x04 ALE = 0; PORTB = 0x11; // Hier schreibe ich dann die Daten in das Register WR = 0; WR = 1; } unsigned char lesen(unsigned char adresse) { init(); ALE = 1; PORTB = adresse; //Hier übergebe ich zuerst die Adresse z.B. 0x04 ALE = 0; DDRB = 0x00; RD = 0; daten = PORTB; // Hier lese ich dann die Daten RD = 1; return daten; } void main(void) { schreiben(0x04); sprintf(text," Daten = %3.0u",lesen(0x04)); lcd_gotoxy(0,0); lcd_puts(text); while (1) {}; } Das müsste doch so hinhauen! Aber leider funktioniert es nicht. Vielleicht habe ich noch einen Denkfehler! Hmm...
Oh Gott, Du übergibst ja die Daten nicht als Parameter, sondern schreibst konstant 0x11 rein. Das hat doch nicht den geringsten praktischen Nährwert. Und "PORTD = 0;" setzt gleichzeitig RD und WR auf 0, was den SJA nun völlig durcheinander bringt. Gewöhn Dich besser an die ANSI-C-Syntax, also schreibe: #define WR PORTD0 #define RD PORTD1 PORTD |= 1<<WR^1<<RD; // setzte beide auf 1 PORTD &= ~(1<<WR); // setze WR auf 0 usw. Die Bitbefehle vom Codevision sind nicht portabel und verschleiern Dir aber den Byte-Zugriff. Sie haben Dich daher durcheinander gebracht, anstatt Dir zu nützen. Deshalb benutzen die C-Profis nur die Maskenoperatoren & (AND) und | (OR) und ^ (EXOR). Das ist portabel und wird bei guten Compilern auch optimiert. Peter
So ich habe jetzt das Programm noch einwenig abgeändert. void init(void); void schreiben(unsigned char adresse, unsigned char daten); unsigned char lesen(unsigned char adresse); // Declare your global variables here void init(void) { PORTB = 0; DDRB = 0xFF; PORTD = 0; DDRD = 0xFF; ALE = 0; RD = 1; WR = 1; } void schreiben(unsigned char adresse, unsigned char daten) { ALE = 1; PORTB = adresse; ALE = 0; PORTB = daten; WR = 0; WR = 1; } unsigned char lesen(unsigned char adresse) { unsigned char daten = 0; ALE = 1; PORTB = adresse; ALE = 0; DDRB = 0x00; RD = 0; daten = PINB; RD = 1; return daten; } void main(void) { init(); schreiben(0x04,0x55); sprintf(text," Daten = %3.0u",lesen(0x04)); lcd_gotoxy(0,0); lcd_puts(text); while (1) {}; } Misst läuft immer noch nicht! Hmmmm...
So hab das Programm ein bisschen verändert. #define ALE PORTD.3 #define WR PORTD.6 #define RD PORTD.5 #define HIGH 1; #define LOW 0; void init(void); void schreiben(unsigned char adresse, unsigned char daten); unsigned char lesen(unsigned char adresse); // Declare your global variables here void init(void) { PORTB = 0; DDRB = 0xFF; ALE = 0; RD = 1; WR = 1; } void schreiben(unsigned char adresse, unsigned char daten) { ALE = 1; PORTB = adresse; ALE = 0; PORTB = daten; WR = 0; WR = 1; } unsigned char lesen(unsigned char adresse) { unsigned char daten = 0; ALE = 1; PORTB = adresse; ALE = 0; DDRB = 0x00; RD = 0; daten = PINB; RD = 1; return daten; } void main(void) { init(); schreiben(0x04,0x55); sprintf(text," Daten = %3.0u",lesen(0x04)); lcd_gotoxy(0,0); lcd_puts(text); while (1) {}; }
Hab mal versucht, Deine Konfiguration mit in meine Headerfiles einzubauen. Ich kann diesen Code leider nicht Testen. Wenn irgendwas nicht klappt, dann einfach die Fehlermeldung oder was auch immer hier Posten... Viel Erfolg, Patrick...
Hallo Patrick! Danke für den Code!Trotzdem schaffe ich es einfach nicht, Daten von dem CAN-Controller abzufragen???? So wie ich das Programm geschrieben habe müsste es doch funktionieren. Ich weiss nicht was ich da noch falsch gemacht habe! #define ALE PORTD.3 #define WR PORTD.6 #define RD PORTD.5 #define HIGH 1; #define LOW 0; void init(void); void schreiben(unsigned char adresse, unsigned char daten); unsigned char lesen(unsigned char adresse); // Declare your global variables here void init(void) { PORTB = 0; DDRB = 0xFF; DDRD = 0xFF; ALE = 0; RD = 1; WR = 1; } void schreiben(unsigned char adresse, unsigned char daten) { ALE = 1; PORTB = adresse; ALE = 0; PORTB = daten; WR = 0; WR = 1; } unsigned char lesen(unsigned char adresse) { unsigned char daten = 0; ALE = 1; PORTB = adresse; ALE = 0; RD = 0; daten = PORTB; RD = 1; return daten; } void main(void) { init(); schreiben(0x04,0x55); sprintf(text," Daten = %3.0u",lesen(0x04)); lcd_gotoxy(0,0); lcd_puts(text); while (1) {}; }
Hmm...hab noch bei meinem Programm was vergessen! Siehe Funktion lesen: unsigned char lesen(unsigned char adresse) { unsigned char daten = 0; ALE = 1; PORTB = adresse; ALE = 0; DDRB = 0x00; RD = 0; daten = PORTB; RD = 1; return daten; }
Kann mir jemand dabei Helfen! Ich weiss nicht was ich noch an dem Programm verändern soll. Um Rat wäre ich sehr dankbar! MfG Hennse
Das sieht eigendlich jetzt schon ganz gut aus. Was mir noch aufgefallen ist: die Rückgabe kenne ich nur mit Klammern, also in Deinem Programm: return(daten); Wenn Du nicht weiterkommst, dann leg Deine Schreibroutine mal in eine Endlosschleife und messe die Signale mit dem Oszi nach. Danach dasselbe mit der Leseroutine. Um herauszufinden, ob die Pins auch wirklich Ein- bzw. Ausgang sind: mit einem 10kohm-R nach Masse oder VCC ziehen, nur wenn der Pin Eingang sein soll, darf sich was ändern. Wie gesagt, sonst fällt mir auch nichts auf. Bitte nicht privat mailen, wenn ich eine Idee bzw. Zeit zum Antworten habe, melde ich mich schon, ausserdem sollen ja auch andere an Deinem Problem lernen können. Stefan
Langsam wirds. Hast Du Dir denn wirklich nicht mal das SJA-Timing angesehen ? Nach dem Lesen must Du doch wieder auf Ausgang schalten, sonst geht das nächste Lesen / Schreiben gegen den Baum: unsigned char lesen(unsigned char adresse) { unsigned char daten; ALE = 1; PORTB = adresse; ALE = 0; DDRB = 0x00; RD = 0; daten = PORTB; RD = 1; DDRB = 0xFF; return daten; } Peter
Jetzt hab ich mal mit dem Oszi den Takt überprüft. --> Taktfrequenz nicht vorhanden. Hmmm..dann ist auch klar warum der CAN-Controller nicht arbeitet.
So jetzt hab ich mal noch die Hardware überprüft. takt ist diesesmal vorhanden. Ich habe keinen Fehler entdeckt. Die Software habe ich auch verbessert. Nichts tut sich. Ich weiss jetzt nicht was ich noch tun kann!
Was mir noch einfällt. Den AVR versorge ich mit 8Mhz und den CAN-Controller mit 16Mhz. Macht das was aus wenn die Frequenzen unterschiedlich sind????
So...jetzt glaube ich das der CAN Controller defekt ist. Was anderes kann ich mir nicht vorstellen! Für Hilfe wäre ich sehr sehr dankbar!
Was mir noch einfällt, ist das überhaupt richtig, dass das CS immer auf Ground liegt??? Werden die Adressen erst übernommen wenn das ALE Signal anliegt oder muss ich noch das WR Signal aktivieren?
Mir hat jemand erzählt, dass das CS Signal nicht direkt auf Masse gelegt werden soll! Stimmt dies???
Erwartest Du im Ernst, daß jemand für Dich das Datenblatt lesen soll ??? Wenn Du keinen Oszi hast, um das Timing mit dem im Datenblatte zu vergleichen, dann nimm einen Taster und eine Entprellroutine und "taste" Dich Schritt für Schritt durch (LEDs mit Vorwiderständen an alle Signale). Warte nicht immer, bis Dir jemand den nächsten Schritt vorsagt, treibe mal selber ein bischen Debugaufwand. Prüfe was fehlschlägt, das Lesen oder das Schreiben. Z.B. kannst Du den Takt setzen bzw. abschalten oder die TXD-Pins einschalten. Lese von verschiedenen Adressen, vergleiche, was rauskommt usw. Peter
Warum ich hab mich doch an das Datenblatt gehalten! Ich habe mitbekommen das man das CS Signal nicht auf Masse legen soll, sondern separat über einen Port bedienen soll! Vielleicht liegt es auch daran.
"Ich habe mitbekommen das man das CS Signal nicht auf Masse legen soll, sondern separat über einen Port bedienen soll!" Wo steht das denn im Datenblatt ? Vielleicht stellst Du mal Deine Schaltplan hier rein: - alle VCC und GND angeschlossen ? - Intel-Mode selektiert ? - Reset ordentlich gemacht ? - ist ein Takt am Taktausgang zu sehen ? - keine Lötbrücken, Unterbrechungen ? Versuch doch wirklich mal die einzelnen Schritte zu debuggen, entweder über die UART oder mit Taster und LEDs. Mach ich ja genauso, wenn eine Funktion nicht als Ganzes geht, zerlege ich sie in Einzelschritte, notfalls bis runter zum einzelnen Befehl. Peter
Hallo Peter! 1. alle VCC und GND angeschlossen 2. Intel-Mode aktiviert. 3. zwischen VCC und Reset-Eingang vom AVR habe ich einen 10kOhm Widerstand reingelötet. 4. Takt von 16Mhz vorhanden. 5. keine Lötbrücken bzw. Kurzschlüsse vorhanden. 6. Ich kann sogar die Daten einlesen. (DDRB = 0x00 funktioniert) 7. Steuerleitungen (ALE RD WR) funktionieren. Ich habe mal das veränderte Programm hier gepostet.
Also jetzt habe ich mal Schritt für Schritt alles gecheckt, aber leider ohne Erfolg! Hmmm.... Ich denke es liegt doch an der Software. (Siehe Prog. AVR-CAN.c) Aber wass soll ich da noch verändern. Hab alle möglichen Varianten geprüft.
Ich kann immer nur wiederholen, das Datenblatt ist Dein Freund, lies es gründlich !!! Z.B. steht da drin, daß im Operating Mode von Adresse 0x04 immer 0xFF gelesen wird. Ein Controller ist kein SRAM, d.h. Du kannst nur bestimmte Bits setzen und rücklesen, je nach Mode. Peter
Hallo Peter! Jetzt habe ich es endlich geschaft! Kann Daten lesen und schreiben. Was ich noch vergessen habe ist, das ich in der lese Routine --> daten = PORTB verwendet habe. Da muss nämlich --> daten = PINB stehen. Also ich denke mal das es Funktioniert. Hab z.B. Adresse 0x02 angewählt und einen Wert reingeschrieb(z.B. 0x12). Siehe da, ich konnte das Daten Byte auslesen --> 0x12. Somit müsste das jetzt so stimmen.
Hallo Peter! Endlich habe ich es geschaft. Ich kann Daten lesen und schreiben. In der LESE routine habe ich PORTB statt PINB benutzt. (-->daten = PINB) Z.B. habe ich die Adresse 0x02 angesprochen und den Wert 0x12 reingeschrieben. Siehe da, ich konnte das Datenbyte 0x12 auslesen. Somit müsste das ganze auch funktionieren. MfG Hennse
Hallo Peter! Endlich habe ich es geschaft. Ich kann Daten lesen und schreiben. In der LESE routine habe ich PORTB statt PINB benutzt. (-->daten = PINB) Z.B. habe ich die Adresse 0x02 angesprochen und den Wert 0x12 reingeschrieben. Siehe da, ich konnte das Datenbyte 0x12 auslesen. Somit müsste das ganze auch funktionieren. MfG Hennse
Kann jedem mal passieren. Ich mache viel mit dem 8051 und da gibt es diese Unterscheidung nicht. Deshalb ist es mir bei Deinem Code auch nicht aufgefallen. Vielleicht wäre es mir aufgefallen, wenn Du gesagt hättest, daß Du immer die Adresse zurück liest. Du hast aber immer nur gesagt, es geht nicht. Peter
Vielen Dank Peter! Deine Unterstützung war hilfreich. Ich denke jetzt mal wenn ich Daten auslesen kann wie in diesem Beispiel dann wird dies auch so korrekt sein oder??? Ein Zufallswert kann es ja nicht sein!
Nur noch eine Frage: Wenn ich z.B. das Register 0x02 mit dem Wert 0x12 beschreibe und ich unterbreche die Versorgungsspannung, dann kann ich den Wert von 0x12 nicht mehr auslesen. Hat der SJA nur ein SRAM???
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.