Forum: Mikrocontroller und Digitale Elektronik MCP2515 richtig initialisiert?


von kevin m. (kevinm)


Angehängte Dateien:

Lesenswert?

Guten Abend,

ich versuch schon seit längerem ein Testboard mit einem atmega16 in 
verbindung mit einem MCP 2515 aufzubauen. Leider scheitere ich beim 
initalisieren des MCP. Jetzt habe ich alles soweit das ich zumindest die 
Register werte vom MCP über usart an den PC senden kann. Das Problem ist 
das ich jetzt nicht weiß ob der MCP richtig funktioniert, da ich noch 
kein CAN BUS System an dem ich mein Testboard testen könnte habe.

Jetzt wollte ich fragen ob die Registerwerte die ich beim initalisieren 
übergeben habe soweit in Ordnung sind. Ich möchte auch gernen, wenn der 
MCP eine nachricht vom can bus erhält, das der externe interrupt 
ausgelöst wird. Kann das mit diesem Code (im anhang) funktionieren?

Als Registerwerte erhalte ich am Terminal folgendes:

ATMEGA 16 @ 16 MHZ ext. Takt
USART Initalisiert...
MCP CANCTRL nach Reset: 10000111  (0x87)
MCP CANCTRL Arbeitsmod.: 111  (0x7)
-------- MCP 2515 Register ------

MCP CANCTRL: 111
MCP CANSTAT: 0
MCP CNF1: 111
MCP CNF2: 10010000
MCP CNF3: 10

-------- ----------------- ------

Das heißt der MCP ist im normalen Modus und ist bereit can botschaften 
zu empfangen?

von cskulkw (Gast)


Lesenswert?

Hi,

im Code habe ich gesehen, dass Du das BFPCTRL auf Null gesetzt hast.

Wenn die Empfangsboxen auf ihren dazugehörigen Pin eine Interrupt 
auslösen sollen, dann mußt Du die entsprechend aktivieren. Für RXB0 = 
0x5 und für RXB1 = 0x0C

Viel Erfolg

von kevin m. (kevinm)


Lesenswert?

Danke für deine Antwort. Ich habe eben nochmal im Datenblatt 
nachgelesen. Die Register für RXB0 u RXB1 sind zum einstellen der PINS 
RX0BF u RX1BF bei einem Interrupt richtig? Ich wollte dafür eigentlich 
den PIN INT verwenden.

Also das beschreiben der Register dürfte schonmal funktionieren 
zumindest bekomm ich andere werte zurückgeliefert. Kann ich dann 
schonmal davon ausgehen das bei meiner Hardware alles in Ordnung ist?

von cskulkw (Gast)


Angehängte Dateien:

Lesenswert?

kevin mitn schrieb:
> Ich wollte dafür eigentlich
>
> den PIN INT verwenden.

Ja, viele Wege führen nach ROM. Nur dann mußt Du ggf. noch ständig im 
CANINTF nachschauen, welcher Interrupt ausgelöst hat. Mit der anderen 
Lösung ist das dann klar vorgegeben.

Also, eine Aussage darüber zu treffen, ob Deine Hardware in Ordnung 
wäre, halte ich auf der Faktenlage dieses Forums für Kaffeesatzleserei. 
Ich hoffe, dass Du mir diese Aussage jetzt nicht übel nimmst. Bau Dir 
eine LED an den Int-Pin, dann siehst Du, wenn der Interrupt nach dem 
Auslesen gelöst worden ist.

Ich arbeite mit eine JTAGICE mkII. Wenn ich das zu Fuß hätte debuggen 
müssen, wäre ich bestimmt noch nicht soweit.

Mit was sendest Du, damit der Empfang überhaupt geprüft werden kann?

von kevin m. (kevinm)


Lesenswert?

Hab jetzt leider nicht mehr soviel Zeit gehabt an meinem Projekt weiter 
zumachen. Die letzen Tage hab ich aber wieder getestet und probiert.

@cskulkw: Hab jetzt mal probiert die 2 Pins am MCP2515 erstmal als I/O 
Pins zu schalten und mit LEDs getestet ob ich die überhaupt schalten 
kann. Das funktioniert schonmal. Ich denke auch das die Hardware nicht 
das Problem seit dürfte. Auch die Registerwerte lassen sich problemlos 
schreiben und lesen.

Dann hab ich die Pins als Input Pins für Puffer Voll geschaltet. Wenn 
ich jetzt umstelle auf LoopBack Modus funktioniert das alles schonmal. 
Ich sende eine Nachricht die LED geht aus ich lese die Nachricht lösch 
das interrupt Bit wieder und die LED geht wieder an.

So zurück zum Normal Modus: Als Testsystem mit dem ich Can-Nachrichten 
sende hab ich mir einen Tacho von einem Skoda Octavia besorgt. Ein 
kleinen Bus mit 120 Ohm widerständen an den enden und daran meinen 
mcp2551 der die signale von CANH und CANL umwandelt in eine 0-5V 
Spannung. Das Signal liegt dann am RXD Pin beim MCP2515 an.

Was mir jetzt aufgefallen ist: das Register "REC" = 10000001 und Das 
Register "ERFLG" hat 00001011. Das bedeutet das wenn ich alles 
angeschlossen habe und der mcp im normal Modus läuft die Bits RXEP, 
RXWAR und EWARN auf 1 gesetzt werden. Leider kann ich auch im Datenblatt 
nicht nachlesen warum diese Bits genau gesetzt werden?!?

Warum werden keine Nachrichten von meinem Bus empfangen und stattdessen 
diese ERROR Bits gesetzt?!?

von cskulkw (Gast)


Lesenswert?

Also das bit 7 des EFLG zeigt an, dass die RX1B überschrieben worden 
ist.
Das ist an sich kein drama. Muß jedoch vom Controler gelöscht werden...

Die Bits RXWAR und EWARN zeigen an, dass mehr als 96 Busfehler 
aufgetreten sein. Also, 96 CAN-BOtschaften müßten fehlgeschlagen sein.

Sicherlich kannst Du nicht überprüfen, was auf dem CAN-Bus los ist. Ich 
habe den Verdacht, dass die Bus-Baudraten nicht stimmen.

Versuch doch einmal ein 2. System aufzubauen, dass dann mit der gleichen 
Initialisierung sendet. Wenn das klappt, wäre das ein Indiz für eine 
falsche Baudrate.

Schwingt der µC-Oszillator mit der richtigen Frequenz und vor allen 
Dingen ohne wesentlicher Abweichung?

von Alex A. (Gast)


Lesenswert?

@cskulkw
Hi, du scheinst dich mit diesem Can-Controller ganz gut aus zu kennen.
Kannst du mir verraten, wie ich am besten feststellen kann, wenn der 
TXBx leer ist? Also wann die Nachricht rausgeschickt worden ist und der 
Buffer wieder frei ist.

Habe gesehen, ich kann die Pins so konfigurieren, aber das will ich 
nicht.
Ich möchte lieber per spi abfragen, ob TXB0 frei ist (Nachricht 
erfolgreich übermittelt).

Habe schon probiert TXB0CTRL.TREQ aus zu lesen.
Wenn der Bit 0 ist, dann sollte der Buffer ja leer sein. Aber das klappt 
auf diesem Wege nicht.

Gibt es sonst noch ein Register, das ich auslesen kann, um fest zu 
stellen, dass die Nachricht weggegangen ist und der Buffer wieder leer 
ist?

Mein Problem:
Auf dem Can-Bus ist sehr viel los.
ich muss schon CANCTRL bit3 auf 0 programmieren, damit der One Shot 
Modus deaktiviert ist.

Der MCP braucht desswegen schon etwas Zeit, um die Nachrichten ab zu 
schicken.
Habe jetzt nach dem Senden 50ms Pause, um sicher zu sein, dass die 
Nachricht weggegangen ist.

Das möchte ich aber nicht so, weil das mein programm u.U. langsamer 
macht.

Ich will nach dem Senden nur so lange warten, bis die Nachricht raus 
ist, und nicht pauschal 50ms.

Danke
Gruss Alex S.

von kevin m. (kevinm)


Lesenswert?

Ich habe heute nochmal den Quarz geprüft. Dabei ist mir aufgefallen das 
ich 48p kondensatoren hinter dem Quarz hatte. Hab die beiden gegen 22p 
ausgetauscht, leider ohne erfolg. An den beide Oszillatoren die ich 
verbaut habe (mcp2515 und amtega) kann es nicht liegen.

Zur Baudrate: Der CAN Bus läuft mit 500 kbit/s. Als Baudrate habe ich 
folgendes eingestellt:
CNF1, 0x01
CNF2, 0x90
CNF3, 0x02
Ich habe auch die werte die ich mir mit dem Bit Timing Calculator 
berechnet habe probiert. Leider bekomm ich immer noch Fehler im REC 
Register und kann keine Nachrichten empfangen ...

von Rene S. (gigastulle)


Lesenswert?

cskulkw schrieb:
> kevin mitn schrieb:
>> Ich wollte dafür eigentlich
>>


Cooles Display :) Wie heißt den das Display ?

MFG Rene

von cskulkw (Gast)


Lesenswert?

Alex S. schrieb:
> @cskulkw
>
> Hi, du scheinst dich mit diesem Can-Controller ganz gut aus zu kennen.
>
> Kannst du mir verraten, wie ich am besten feststellen kann, wenn der
>
> TXBx leer ist? Also wann die Nachricht rausgeschickt worden ist und der
>
> Buffer wieder frei ist.

Ich habe das TXREQ-Bit aus dem RXBnTRNL-Register dafür benutzt.

Rene Schir schrieb:
> Cooles Display :) Wie heißt den das Display ?

Das ist das eDIP320 (320 * 240) mit Touchpad von Electronic Assembly. 
Das gibst bei Reichelt für ca. 200 Euro. Dafür kannst Du es mit 
Grafikbefehlen steuern und über RS2323, SPI bzw. TWI an der µC 
anschließen.
Das ist eine Menge Geld. Aber ich hatte einfach keine Lust auf Pixeln...
Vom Günster-geht-immer-Dasein habe ich mit verabschiedet. Vorteile 
kosten eben immer etwas.
Es gibt auch das Display als eDIP240 (240 * 120) für ca. 150 Euro. und 
ein ea43TFT mit 480 X 272 Pixel TFT-Farbdisplay mit 65000 Farben für ca. 
185 Euro.

kevin mitn schrieb:
> Zur Baudrate: Der CAN Bus läuft mit 500 kbit/s. Als Baudrate habe ich
>
> folgendes eingestellt:
>
> CNF1, 0x01
>
> CNF2, 0x90
>
> CNF3, 0x02


Probiers mal mit CNF1 0x0, CNF2 0xB8 , CNF3 0x5

Das habe ich mit Microchip Bittime-Calculator ausgerechnet: 16 mhz, 
500kBaud, Tq 125 ns Number of Time Quanta 16


Ich glaube allerdings nicht, dass es daran liegt. Vielleicht stimmt mit 
Deinem Sender etwas nicht.

Probiers aus.

von Alex A. (Gast)


Lesenswert?

>Ich habe das TXREQ-Bit aus dem RXBnTRNL-Register dafür benutzt.
Du meinst TXBnCTRL, oder?

von cskulkw (Gast)


Lesenswert?

Ups, ja ...

von Alex A. (Gast)


Lesenswert?

Kannst du mir verraten, wie es bei dir funktioniert?
Bei mir ist das aktuell so: (weiss nicht, ob du Basic verstehst, ist 
aber alles selbsterklärend)


'Senden 1 Byte****************************************
 Sub Senden1(byval D0 As Byte )

  Mcp2515_bitmodify2 Txb0ctrl , &B00000011 , &B00000011


  Mcp2515_write_register2 Txb0sidh , Idh
  Mcp2515_write_register2 Txb0sidl , Idl

  Mcp2515_write_register2 Txb0dlc , &H01                    ' Laenge
   'Daten
  Mcp2515_write_register2 Txb0d0 , D0

  'nachricht versenden
  Reset Css2
   Waitus 10
   Mcphilf2 = Spi_rts0
   Spdr = Mcphilf2
   Do
   Loop Until Spsr.spif = 1
   Set Css2

 Do
   Waitus 20
   Reset Css2
  Spdr = &HA0
 Do
 Loop Until Spsr.spif = 1

 Spdr = 0
 Do
 Loop Until Spsr.spif = 1

 Spdr = 0
 Do
 Loop Until Spsr.spif = 1

 Spdr = 0
 Do
 Loop Until Spsr.spif = 1

 Spdr = 0
 Do
 Loop Until Spsr.spif = 1

 Spdr = 0
 Do
 Loop Until Spsr.spif = 1

 Spdr = 0
 Do
 Loop Until Spsr.spif = 1
 Gesendet = Spdr

Set Css2
Loop Until Gesendet = &H0

 End Sub


Nach dem RTS sende ich A0 (laut Datenblatt) und dann noch 6x die 0.
nach dem 6. Mal empfange ich die Daten.
Das Ganze wird wiederholt, bis TXB0CTRL.TREQ = &H0 ist.

Siehst du den Fehler?

Danke
Gruss Alex

von cskulkw (Gast)


Lesenswert?

Naja,

ich lade erste die zu sendenen Daten mit ID in den MOb-Puffer und sende 
das einen RTS für diese Messagebox, damit das Absetzen startet.

Danach frage ich in einer Loop (vereinfacht !) durch wiederholendes 
Einlesen 0x03, 0x30, hier kommt dann der Inhalt von 0x30, in dem das Bit 
4 das TXREQ-Bit ist. Solange es gesetzt ist, ist die Anforderung zum 
Senden noch nicht abgeschlossen.

Die Warteverzögerungen in Deiner Schleife sind danach überflüssig.

Wo wird denn in Deiner Schleife das TXB0CTRL eingelesen? Das 
interessante BIt ist ja noch nicht im Mikrokontroler...

Hilft Dir das?

von Alex A. (Gast)


Lesenswert?

>Das interessante BIt ist ja noch nicht im Mikrokontroler...

Doch, wenn meine Logik stimmt, dann ist das an dieser Stelle eingelesen:
Gesendet = Spdr

Das Heisst, Variable "Gesendet" bekommt den Wert aus SPDR.

Ich kann dir aber leider mit 03h und 30h überhaupt nicht folgen.

Laut Datenblatt, ist der SPI Befehl (Read Status Instruction) 10100000
dann soll ich ja 6 bits schicken, damit der Clock getaktet wird.
ich schicke 6x die 0, und dann lese ich den Bit mit "Gesendet = SPDR" 
aus.

Wenn der bit nicht 0 ist, dann setze ich den CSS kurz auf High, dann 
wieder auf Low, und das Ganze von Vorne, bis der Bit2 auf 0 ist.

Leiter funktioniert das nicht.
Das Programm bleibt irgendwo in diesen Zeilen stehen stehen. 
Wahrscheinlich, weil der Bit nicht 0 wird.

Irgendwo ist ein Fehler drin, aber ich finde diesen nicht.

Gruss Alex S.

von cskulkw (Gast)


Angehängte Dateien:

Lesenswert?

Sorry Alex, habe am Wochenende keine Zeit gehabt, zu posten.

Anbei ein Screenshot.

Du mußt eine Byte 0x03 senden, damit der Controler weiß, dass Du ein 
Register auslesen möchtest.
Dann mußt Du die Adresse der auszulesenden Register senden hier die 0x30

und dann noch einmal ein Byte mit irgend etwas.
Sobald das dann eingelesen ist, solltest Du den Inhalt von TX0CTRL in 
der Variablen haben.

Ist immer ein 3-Byte-Informationsaustausch.

Ich hatte dazu auch mal ein Bus-Trace, der interpretiert war. da sieht 
man das besser als so eine trockene theoretische Beschreibung.

von cskulkw (Gast)


Lesenswert?

Übrigens macht es keinen Sinn nach dem Senderequest noch die 6x die Null 
zu senden. Mann muß vor dem Request die Datenregister laden. Weil sie 
sonst schreibgeschützt sind.

Sorry für den Nachtrag.

von Alex A. (Gast)


Lesenswert?

Danke, hat funktioniert :)

von kevin m. (kevinm)


Lesenswert?

Guten Abende,

so also seit kurzem funktioniert das ganze bei mir und ich kann CAN 
Nachrichten empfangen. Ich kann aber leider nicht genau sagen an was es 
lag. An den Bittimings lag es nicht, die waren anscheinend in Ordnung. 
Ich glaube das es an ein paar kleinen Fehlern an der Hardware lag. Ich 
hab nochmal alles kontrolliert und ausprobiert und irgendwann lief es 
dann auch.

Wie soll es anders sein hab ich jetzt aber das nächste Problem:
Ich betreibe den MCP2515 im interrupt betriebe. Also vom MCP2515 eine 
Leitung zum int2 beim Atmega. Diese zeigt mir an wann der Nachrichten 
Buffer voll ist und lese in dann über die ISR Sequenz aus. Klappt auch 
alles wunderbar.

Mein rießen Problem ist jetzt, dass ständig neue Nachrichten im Buffer 
des MCP2515 liegen. Der Atmega durchläuft ständig die ISR Routine für 
den INT2 pin und lässt keine Zeit für anderes. Ich möchte aber 
zwinschendurch eine CAN Nachricht versenden. Über UART zum Atmega senden 
und über die UART ISR dann die nachricht zum mcp2515 auf den CAN Bus 
schicken. Ich habe gesehen das die Prioritäten für die ISR Routinen fest 
vergeben sind und sich diese anscheinend nicht ändern lässt? Der INT2 
steht fast über allen anderen vectoren und blockiert mir mein ganzes 
programm.

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.