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!
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 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
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
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...
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
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, 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?
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???