Kommunikation mit dem MCP2515

canknotenkomplett_klein
Der CAN-Controller, in diesem Fall ein MCP2515 von Mikrochip, wird mittels SPI-Interface angesprochen und eingestellt.
Die Grundbeschaltung des MCP2515 sieht so aus:

MCP2515 Grundbeschaltung

Dabei wird SCK von MCP2515 mit SCK vom Mega32, SO mit MISO und SI mit MOSI verbunden. Der CS Pin vom MCP2515 kann mit jeden beliebigen I/O vom Mega32 verbunden werden. Ich verwende in meinem Projekt den Pin PB.4.
Das Hauptprogramm besteht aus mehreren Unterprogrammen, welche die Aufgabe haben den Datenverkehr mit dem MCP2515 zu übernehmen z.B. das Auslesen und Beschreiben der verschiedenen Register.
Desweiteren sind die gesamten Registeradressen und ebenso die Befehle für den MCP2515 als Konstanten im Speicher hinterlegt, sodass bequem darauf zugegriffen werden kann.
Die wichtigsten Unterprogramme für die Kommunikation mit dem MCP2515 sind die Unterprogramme „Write_Register“, „Read_Register“ und „Bitmodify“.
Das „Write_Register“ Programm sieht wie folgt aus:

Sub Write_register(byval Adresse As Byte , Byval Daten As Byte)
Reset Cs
Spdr = Spi_write
Do
Loop Until Spsr.spif = 1

Spdr = Adresse
Do
Loop Until Spsr.spif = 1


Spdr = Daten
Do
Loop Until Spsr.spif = 1
Set Cs
Waitus 50 


End Sub

Als allererstes wird der Chipselect auf Low gezogen. Damit weiß der CAN-Controller, dass die nachfolgenden Informationen für ihn bestimmt sind. Anschließend wird der Wert der Konstanten „SPI_Write“ , welche der Befehl für das Schreibkommando ist, in das Datenregister des SPI-Interfaces kopiert.
Mittels

Do

Loop Until Spsr.spif = 1

wird eine Endlosschleife generiert, die solange durchlaufen wird bis das Datenregister vom SPI-Interface leer ist (SPI Interruptbit gesetzt). Dadurch werden Timingprobleme, die auftreten können wenn zu schnell nacheinander Daten auf den Bus gelegt werden, umgangen.
Durch den Schreibbefehl weiß der CAN-Controller nun das ein Register verändert werden soll und er erwartet als nächstes Byte die Adresse des Registers. Diese Adresse wird in die Funktion übergeben und ist variabel.
Nachdem die Adresse abgeschickt wurde erwartet der Controller 1 Byte Daten, welche die neue Konfiguration des Registers beinhalten. Auch diese Daten sind variabel und werden an die Funktion übergeben.
Nachdem diese drei Bytes gesendet wurden wird der Chipselect wieder auf High gelegt und das Unterprogramm ist durchgelaufen.

Das andere Unterprogramm ist das Programm „Read_register“ und es sieht so aus:

Function Read_register(byval Adresse As Byte ) As Byte


Reset Cs
Spdr = Spi_read
Spiout Spdr , 1
Spiout Adresse , 1
Waitus 1
Spiin Read_register , 1
Set Cs              


End Function

Dieses Programm ist dem „Write_register“-Programm sehr ähnlich. Statt einem „Write“-Befehl wird aber diesmal ein „Read“-Befehl gesendet. Danach folgt die Information welches Register gelesen werden soll (auch hier wird dieser Wert in die Funktion übergeben und ist dementsprechend variabel) und anschließend werden die Daten, die der CAN-Controller ausgibt, aus der Funktion zurück in das Hauptprogramm übergeben.

Der letzte wichtige Befehl ist der sogenannte „Bitmodify“ Befehl.
Dieser Befehl sorgt dafür, dass bestimmte Bits in einem kompletten Register geändert werden können. Anders als bei dem „Write“-Befehl wird hierbei nicht der komplette Inhalt des Registers geändert, sondern nur bestimmte Bits welche vorher maskiert wurden.
Bevor ich aber auf das Unterprogramm eingehe, erzähle ich erstmal ein paar Worte zu dem Befehl an sich.
Wie eben schon erwähnt, erlaubt es der Befehl einzelne Bits eines Registers zu ändern.
Dies geschieht folgendermaßen:
Zuerst wird der Bitmodify – Befehl abgeschickt und anschließend folgt die Adresse. Nun weiß der Controller das ein Register geändert werden soll. Um welches Register es sich handelt erfährt er durch die Adresse.
Anschließend folgt 1 Byte Daten, welchesdie Maskierung beinhaltet. Dabei wird ein Bit durch eine „1“ maskiert.
Nach der Maskierung wird der neue Wert der Bits gesendet und schon ist der Registerinhalt geändert.
Hier ein kleines Beispiel:
Das Register X beinhaltet folgendes Bitmuster: 1010 1010
Ich möchte das 1. Bit und das 7. Bit ändern (Bit 0 und 6). Und zwar sollen diese nachher auf „1“ stehen.
Wenn dieses Register nun modifiziert werden soll, sendet man erst die Adresse für das Register X. Anschließend sage ich welche Bits geändert werden sollen. Dazu sende ich dieses Bitmuster: 01000001
Dadurch werden die Bits 0 und 6 markiert. Da ich diese Bits nun auf 1 setzen will, muss ich dieses Bitmuster nochmal als Datenpaket senden. Man kann sich das so vorstellen, dass das Byte, welches die neuen Daten des Registers beinhaltet, auf das alte Bitmuster in dem Register drüber gelegt wird und überall wo in der Maskierung eine „1“ steht wird das Bit mit dem drüber gelegten Bit „ausgetauscht“.
Zusammengefasst sende ich also:

-> Befehl Bitmodify
-> Adresse des Registers
-> Maskierungsbyte 01000001
-> Datenbyte 01000001

Anschließend sieht der Registerinhalt so aus:

1110 1011

Auf diese Weise können natürlich auch einzelne Bits gelöscht werden. Die Maskierung geschieht genau wie oben, nur wird anstelle der „1“ im Datenbyte eine „0“ gesendet.
Das dementsprechende Unterprogramm sieht dann so aus:

Sub Bitmodify(Reg_add , Reg_mask , Reg_val)


Reset Cs
Spdr = Spi_bitmodify
Do
Loop Until Spsr.spif = 1
Waitms 2
Spdr = Reg_add
Do
Loop Until Spsr.spif = 1
Spdr = Reg_mask
Do
Loop Until Spsr.spif = 1
Spdr = Reg_val
Do
Loop Until Spsr.spif = 1
Set Cs
Waitus 50  


End Sub

Wie dem Programmkopf zu entnehmen ist, werden drei Werte in dieses Unterprogramm übergeben. Bei diesen drei Bytes handelt es sich um die Adresse für das Register (Reg_add), das Maskenbyte (Reg_Mask) und das neue Datenbyte (Reg_Val).
Als allererstes wird der Chipselect auf Low gezogen und anschließend wird der Wert der Konstanten für den Befehl „Bitmodify“ gesendet.
Als nächstes wird das Maskenbyte und anschließend das Datenbyte gesendet. Wenn die Übertragung abgeschlossen wurde, wird der Chipselect wieder auf High gezogen.

Mit diesen drei Unterprogrammen wird nachher im Programm (beinahe) die komplette Kommunikation mit dem MCP2515 abgehandelt, was den Aufbau des Programms etwas übersichtlicher macht.

 

-> Zurück zum CAN-Bus

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Time limit is exhausted. Please reload CAPTCHA.