Code:
'Mikrocontroller
$regfile = "m32def.dat"
$crystal = 16000000
'Stacks
$hwstack = 200
$swstack = 200
$framesize = 400
'UART konfigurieren
$baud = 19200
'SPI konfigurieren
Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Noss = 1 , Clockrate = 16
Spiinit
'Unterprogramme
Declare Function Read_rx_status As Byte
Declare Function Read_register(byval Adresse As Byte) As Byte
Declare Sub Register
Declare Sub Recieve_can
Declare Sub Mcp2515_init
Declare Sub Interrupt_occur
Declare Sub Config_filter(byval Filter As Byte , Byval Buffer As Byte , Byval Ex_f_enable As Byte)
Declare Sub Send_can(daten As Byte , Byval Tx_identifier As Long , Byval Ex_id_enable As Byte)
Declare Sub Bitmodify(byval Reg_add As Byte , Byval Reg_mask As Byte , Byval Reg_val As Byte)
Declare Sub Send_remote(byval Tx_identifier As Long , Byval Ex_id_enable As Byte)
Declare Sub Write_register(byval Adresse As Byte , Byval Daten As Byte)
'Befehle
Const Spi_read = &H03
Const Spi_write = &H02
Const Spi_reset = &HC0
Const Spi_rts0 = &H81
Const Spi_bitmodify = &H05
Const Spi_rx_status = &HB0
Const Spi_read_rx = &H90
'Registeradressen
'Controlregister
Const Cnf1 = &H2A
Const Cnf2 = &H29
Const Cnf3 = &H28
Const Canctrl = &H0F 'Control Register vom MCP2515
Const Caninte = &H2B 'Interrupt Enable vom MCP2515
Const Canintf = &H2C 'Interrupfflags vom MCP2515
'Transmit Buffer
Const Txb0ctrl = &H30 'Transmit Buffer 0 Control Register
Const Txb0sidh = &H31 'Transmit Buffer 0 Std Identifier High
Const Txb0sidl = &H32 'Transmit Buffer 0 Std Identifier Low
Const Txb0eid8 = &H33 'Transmit Buffer 0 Ext Identifier High
Const Txb0eid0 = &H34 'Transmit Buffer 0 Ext Identifier Low
Const Txb0dlc = &H35 'Transmit Buffer 0 Data Length Code
Const Txb0d0 = &H36 'Transmit Buffer 0 Data Byte 0
Const Txb0d1 = &H37 'Transmit Buffer 0 Data Byte 1
Const Txb0d2 = &H38 'Transmit Buffer 0 Data Byte 2
Const Txb0d3 = &H39 'Transmit Buffer 0 Data Byte 3
Const Txb0d4 = &H3A 'Transmit Buffer 0 Data Byte 4
Const Txb0d5 = &H3B 'Transmit Buffer 0 Data Byte 5
Const Txb0d6 = &H3C 'Transmit Buffer 0 Data Byte 6
Const Txb0d7 = &H3D 'Transmit Buffer 0 Data Byte 7
'Recieve Buffer
Const Rxm0sidh = &H20 'Receive Buffer 0 Std Identifier High
Const Rxm0sidl = &H21 'Receive Buffer 0 Std Identifier Low
Const Rxm0eid8 = &H22 'Receive Buffer 0 Ext Identifier High
Const Rxm0eid0 = &H23 'Receive Buffer 0 Ext Identifier low
Const Rxm1sidh = &H24 'Receive Buffer 1 Std Identifier High
Const Rxm1sidl = &H25 'Receive Buffer 1 Std Identifier Low
Const Rxm1eid8 = &H26 'Receive Buffer 1 Ext Identifier High
Const Rxm1eid0 = &H27 'Receive Buffer 1 Ext Identifier low
Const Rxb0ctrl = &H60 'Recieve Buffer 0 Control Register
Const Rxb1ctrl = &H70 'Recieve Buffer 1 Control Register
Const Rxb0d0 = &H66 'Revieve Buffer 0 Data Byte 0
Const Rxb0d1 = &H67 'Revieve Buffer 0 Data Byte 1
Const Rxb0d2 = &H68 'Revieve Buffer 0 Data Byte 2
Const Rxb0d3 = &H69 'Revieve Buffer 0 Data Byte 3
Const Rxb0d4 = &H60 'Revieve Buffer 0 Data Byte 4
Const Rxb0d5 = &H6A 'Revieve Buffer 0 Data Byte 5
Const Rxb0d6 = &H6B 'Revieve Buffer 0 Data Byte 6
Const Rxb0d7 = &H6C 'Revieve Buffer 0 Data Byte 7
'Error
Const Eflg = &H2D 'Errorflags
Const Tec = &H1C 'Tx Error Counter
Const Rec = &H1D 'Rx Error Counter
'Acceptance Filter
'RXF0
'Standard Identifier
Const Rxf0sidh = &H00
Const Rxf0sidl = &H01
'Extended Identifier
Const Rxf0eidh = &H02
Const Rxf0eidl = &H03
'RXF1
'Standard Identifier
Const Rxf1sidh = &H04
Const Rxf1sidl = &H05
'Extended Identifier
Const Rxf1eidh = &H06
Const Rxf1eidl = &H07
'RXF2
'Standard Identifier
Const Rxf2sidh = &H08
Const Rxf2sidl = &H09
'Extended Identifier
Const Rxf2eidh = &H0A
Const Rxf2eidl = &H0B
'RXF3
'Standard Identifier
Const Rxf3sidh = &H10
Const Rxf3sidl = &H11
'Extended Identifier
Const Rxf3eidh = &H12
Const Rxf3eidl = &H13
'RXF4
'Standard Identifier
Const Rxf4sidh = &H14
Const Rxf4sidl = &H15
'Extended Identifier
Const Rxf4eidh = &H16
Const Rxf4eidl = &H17
'RXF5
'Standard Identifier
Const Rxf5sidh = &H18
Const Rxf5sidl = &H19
'Extended Identifier
Const Rxf5eidh = &H1A
Const Rxf5eidl = &H1B
'I/O Einstellungen
Config Portb.4 = Output
Config Pind.2 = Input
'Namen vergeben
Cs Alias Portb.4
'Globale Variablen
Dim Status As Byte
Dim Interrupt As Byte
Dim Errorcode As Byte
Dim Statusflag As Byte
Dim Input_uart As Long
Dim Can_message(10) As Byte
Dim Can_remote(2) As Integer
Dim Message_id As Long
Dim Identifier As Long
Dim Test(8) As Byte
Dim A As String * 10
Identifier = 200
Test(1) = 2
Test(2) = 4
Test(3) = 9
Test(4) = 16
Test(5) = 25
Test(6) = 36
Test(7) = 49
Test(8) = 64
'Interrupts einstellen
Enable Interrupts 'Interrupts aktivieren '
Config Int0 = Falling 'INT0 auf fallende Flanke einstellen
On Int0 Mcp2515_int 'Sprungmarke für INT0
'On Urxc Uart_recieved
'Enable Urxc
Enable Int0 'INT0 aktivieren
'Chipselect auf High setzen
Set Cs
Wait 1
'MCP2515 initialisieren
Mcp2515_init
'Filter einstellen
'Config_filter 7 , 0 'Filter einstellen (1. Zahl = Filter, 2. Zahl = Buffer)
'Hauptprogramm
Do
Input "Eingabe: " , A
Select Case A
Case "R" : Print "Remote"
Send_remote 7 , 0
Case "D" : Print "Data
Input "Daten: " , Test(1)
Send_can Test(1) , 7 , 0 'Daten senden (1. Zahl = ID , 2. Zahl = Identifiertyp - 0 = Standard, 1 = Extended)
Incr Test(1)
End Select
A = ""
Loop
End
'Unterprogramme
'-------------------------------------------------------------------------------------------------------------------
Function Read_rx_status() As Byte
Reset Cs 'CS auf Low ziehen
Spdr = Spi_rx_status 'Befehl zum auslesen des Rx Status Register ins Datenregister schreiben
Spiout Spdr , 1 'Inhalt des Datenregisters über SPI senden
Waitus 1 'Kurze Zeit warten
Spiin Read_rx_status , 1 'Antwort des MCP2515 unter "Status" speichern
Set Cs
End Function
'-------------------------------------------------------------------------------------------------------------------
Function Read_register(byval Adresse As Byte ) As Byte
Reset Cs 'Chipselect auf Low ziehen
Spdr = Spi_read 'Inhalt von "SPI_Read" im Datenregister speichern
Spiout Spdr , 1
Spiout Adresse , 1
Waitus 1
Spiin Read_register , 1 'Registerinhalt einlesen
Set Cs 'Chipselect auf High ziehen
End Function
'-------------------------------------------------------------------------------------------------------------------
Sub Mcp2515_init
Reset Cs
Spdr = Spi_reset 'MCP2515 reseten
Do
Loop Until Spsr.spif = 1
Set Cs
'Control Register beschreiben
Write_register Canctrl , &H88 'Device in Configuration Mode versetzen, Nachrichten nur 1x versenden
'Interrupts einstellen
Write_register Caninte , &H05 'Transmit und Recieve Buffer 0 Interrupt aktivieren
'Tx-Konfiguration
Bitmodify Txb0ctrl , &H03 , &H03 'Priorität der Nachrichten auf "Highest" stellen
'Bittiming einstellen
Write_register Cnf1 , &H03 'Baudrate einstellen
Write_register Cnf2 , &HA0 'Phasensegmenteinstellungen
Write_register Cnf3 , &H02
'Rx Buffer einstellen
Write_register Rxb0ctrl , &H20 'Standard Identifier erlauben
Write_register Rxb1ctrl , &H60
Bitmodify Canctrl , &HE0 , &H0 'CAN-Controller in den "Normal Mode" versetzen
'Tx Message Identifier einstellen
Write_register Txb0sidh , &H00
Write_register Txb0sidl , &H00
End Sub
'-------------------------------------------------------------------------------------------------------------------
Sub Write_register(byval Adresse As Byte , Byval Daten As Byte)
Reset Cs 'Chipselect auf Low ziehen
Spdr = Spi_write 'Inhalt von "SPI-Write" ins SPI_Data_Register schieben
Do 'Schleife bis SPI Interrupt Flag gesetzt wurde, also bis
Loop Until Spsr.spif = 1 'die Übertragung abgeschlossen ist
Spdr = Adresse
Do
Loop Until Spsr.spif = 1
Spdr = Daten
Do
Loop Until Spsr.spif = 1
Set Cs 'Chipselect auf High ziehen
End Sub
'-------------------------------------------------------------------------------------------------------------------
Sub Bitmodify(reg_add , Reg_mask , Reg_val)
Reset Cs
Spdr = Spi_bitmodify
Do
Loop Until Spsr.spif = 1
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
End Sub
'-------------------------------------------------------------------------------------------------------------------
Sub Interrupt_occur
Local Errorflag As Byte
Local Rx_error As Byte
Interrupt = Read_register(canintf) 'Interruptflags auslesen um zu erfahren welcher Interrupt
'ausgelöst wurde
'Select Case Interrupt
'Case 1 : Recieve_can
'Case 2 : Recieve_can
'Case Else : Print "Error"
'End Select
If Interrupt > 32 Then
Errorflag = Read_register(eflg)
Rx_error = Read_register(rec)
End If
Print "Interruptflag: " ; Interrupt
Print "Error: " ; Errorflag
Print "Errorcounter: " ; Rx_error
End Sub
'-------------------------------------------------------------------------------------------------------------------
Sub Config_filter(byval Filter As Byte , Byval Buffer As Byte , Byval Ex_f_enable As Byte)
Local Filter_low As Integer
Local Filter_high As Integer
Local Id0_high As Byte
Local Id0_low As Byte
Local Id1_high As Byte
Local Id1_low As Byte
Bitmodify Canctrl , &HE0 , &H80, 'CAN-Controller in den "Configuration Mode" versetzen
'Identifier einstellen
Filter_low = Filter 'Speichert den Identifier in zwei Variablen und schiebt
Filter_high = Filter 'den Wert um 5 Stellen nach rechts um die drei
Shift Filter_low , Left , 5 ' niedrigsten Bits zu gewinnen. Dasselbe passiert für
Shift Filter_high , Right , 3 'die acht höchsten Bits. Anschließend werden die Werte
'in die passenden Register geschrieben.
If Buffer = 0 Then
Id0_high = Filter_high
Id0_low = Filter_low
Elseif Buffer = 1 Then
Id1_high = Filter_high
Id1_low = Filter_low
Else
Print "Unbekannter Buffer"
Errorcode = 3
End If
'Maskenbits setzen
Write_register Rxm0sidh , &HFF
Write_register Rxm0sidl , &HFF
Write_register Rxm1sidh , &HFF
Write_register Rxm1sidl , &HFF
'Filter setzen
Write_register Rxf0sidh , Id0_high
Write_register Rxf0sidl , Id0_low
Write_register Rxf1sidh , Id1_high
Write_register Rxf1sidl , Id1_low
Bitmodify Canctrl , &HE0 , &H0 'CAN-Controller in den "Normal Mode" versetzen
End Sub
'-------------------------------------------------------------------------------------------------------------------
Sub Send_remote(byval Tx_identifier As Long , Byval Ex_id_enable As Byte)
Local Tx_low As Integer
Local Tx_high As Integer
Local Id_high As Byte
Local Id_low As Byte
'Prüfen ob die Nachricht mit einem 29-Bit Identifier versendet werden soll oder nicht
If Ex_id_enable = 0 Then
'Prüfen ob der Identifier die richtige Länge hat
If Tx_identifier > 2047 Then
Print "Identifier beträgt " ; Tx_identifier ; " und ist damit zu groß. Maximaler Wert ist 2047!"
Errorcode = 1
Else
'Identifier einstellen
Tx_low = Tx_identifier 'Speichert den Identifier in zwei Variablen und schiebt
Tx_high = Tx_identifier 'den Wert um 5 Stellen nach rechts um die drei
Shift Tx_low , Left , 5 ' niedrigsten Bits zu gewinnen. Dasselbe passiert für
Shift Tx_high , Right , 3 'die acht höchsten Bits. Anschließend werden die Werte
'in die passenden Register geschrieben.
Id_high = Tx_high
Id_low = Tx_low
'ID in die ID-Register schreiben
Write_register Txb0sidh , Id_high
Write_register Txb0sidl , Id_low
'Renotebit setzen
Bitmodify Txb0ctrl , &H08 , &H08
Reset Cs
Spdr = Spi_rts0 'Übertragung auslösen
Do
Loop Until Spsr.spif = 1
Set Cs
End If
Elseif Ex_id_enable = 1 Then
Else
Print "Error. Unbekannter Identifier!"
Errorcode = 2
End If
End Sub
'-------------------------------------------------------------------------------------------------------------------
Sub Send_can(daten(8) As Byte , Byval Tx_identifier As Long , Byval Ex_id_enable As Byte)
Local Tx_low As Integer
Local Tx_high As Integer
Local Id_high As Byte
Local Id_low As Byte
'Prüfen ob die Nachricht mit einem 29-Bit Identifier versendet werden soll oder nicht
If Ex_id_enable = 0 Then
'Prüfen ob der Identifier die richtige Länge hat
If Tx_identifier > 2047 Then
Print "Identifier beträgt " ; Tx_identifier ; " und ist damit zu groß. Maximaler Wert ist 2047!"
Errorcode = 1
Return
Else
'Identifier einstellen
Tx_low = Tx_identifier 'Speichert den Filter in zwei Variablen und schiebt
Tx_high = Tx_identifier 'den Wert um 5 Stellen nach rechts um die drei
Shift Tx_low , Left , 5 ' niedrigsten Bits zu gewinnen. Dasselbe passiert für
Shift Tx_high , Right , 3 'die acht höchsten Bits. Anschließend werden die Werte
'in die passenden Register geschrieben.
Id_high = Tx_high
Id_low = Tx_low
'ID in die ID-Register schreiben
Write_register Txb0sidh , Id_high
Write_register Txb0sidl , Id_low
'Daten in die Datenregister schreiben
Write_register Txb0dlc , 8
Write_register Txb0d0 , Daten(1)
Write_register Txb0d1 , Daten(2)
Write_register Txb0d2 , Daten(3)
Write_register Txb0d3 , Daten(4)
Write_register Txb0d4 , Daten(5)
Write_register Txb0d5 , Daten(6)
Write_register Txb0d6 , Daten(7)
Write_register Txb0d7 , Daten(8)
Reset Cs
Spdr = Spi_rts0 'Übertragung auslösen
Do
Loop Until Spsr.spif = 1
Set Cs
End If
Elseif Ex_id_enable = 1 Then
Else
Print "Error. Unbekannter Identifier!"
Errorcode = 2
Return
End If
End Sub
'-------------------------------------------------------------------------------------------------------------------
Sub Recieve_can
'Variablen für die Empfangsroutine
Local Id_low As Integer 'Buffer für die drei niedrigsten ID-Bits
Local Id_high As Integer 'Buffer für die acht höchsten ID-Bits
Local Laenge As Byte 'Buffer für die vier Längen-Bits
Local Daten As Byte
Local Dummy As Byte
Local Daten_laenge As Byte
Local Zaehler_laenge As Byte
'Variablen löschen
Id_high = 0
Id_low = 0
Laenge = 0
'Status auslesen und analysieren
Status = Read_rx_status()
If Status = 128 Then 'Nachricht in Rx-Buffer 1
Elseif Status = 72 Then 'Standard Remote Anfrage
'Lesen der Buffer auslösen
Reset Cs
Spdr = Spi_read_rx
Spiout Spdr , 1
Waitus 1
'CAN-Nachricht nach und nach empfangen
'ID auslesen
Spiin Id_high , 1
Spiin Id_low , 1
Spiin Dummy , 1 'Beide Bytes des Extended Identifiers einlesen
Spiin Dummy , 1 'und in einem Dummy speichern
'Länge auslesen
Spiin Laenge , 1
'CAN-Nachricht bearbeiten
'Standard Identifier auslesen 'High Identifier erkennen funktioniert!
Shift Id_high , Left , 3 'Verschiebung beim Senden rückgängig machen
Shift Id_low , Right , 5
Can_remote(1) = Id_high 'und Werte logisch miteiander verknüpfen um daraus
Can_remote(1) = Can_remote(1) Or Id_low 'die komplette ID zu gewinnen
Can_remote(2) = Laenge
Elseif Status = 64 Then 'Nachricht in Rx-Buffer 0
'Lesen der Buffer auslösen
Reset Cs
Spdr = Spi_read_rx
Spiout Spdr , 1
Waitus 1
'CAN-Nachricht nach und nach empfangen
'ID auslesen
Spiin Id_high , 1
Spiin Id_low , 1
Spiin Dummy , 1 'Beiden Bytes des Extended Identifiers einlesen
Spiin Dummy , 1
'Länge auslesen
Spiin Laenge , 1
Zaehler_laenge = Laenge + 2
Laenge = Laenge And &H0F
'Daten auslesen
For Daten_laenge = 3 To Zaehler_laenge
Spiin Can_message(daten_laenge) , 1
Next
'CAN-Nachricht bearbeiten
'Standard Identifier auslesen
Shift Id_high , Left , 3 'Verschiebung beim Senden rückgängig machen
Shift Id_low , Right , 5
Laenge = Laenge And &H0F
Can_message(1) = Id_high 'und Werte logisch miteiander verknüpfen um daraus
Can_message(1) = Can_message(1) Or Id_low 'die komplette ID zu gewinnen
Can_message(2) = Laenge
Else
Print "Keine neue Nachricht vorhanden!"
End If
Set Cs
Waitus 1 'Kurz warten
End Sub
'-------------------------------------------------------------------------------------------------------------------
Sub Register
'Terminalausgabe
Print "Registereinstellungen:"
Print "Registerinhalt CNF1: " ; Read_register(cnf1)
Print "Registerinhalt CNF2: " ; Read_register(cnf2)
Print "Registerinhalt CNF3: " ; Read_register(cnf3)
Print "Registerinhalt CAN Control: " ; Read_register(canctrl)
Print "Registerinhalt TXB0 Control: " ; Read_register(txb0ctrl)
Print "Tx Identifier: " ; Identifier
Print "Registerinhalt TXB0 Data Lenght: " ; Read_register(txb0dlc)
Print "Registerinhalt CAN Interrupt Enable: " ; Read_register(caninte)
Print "Registerinhalt CAN Datenregister: " ; Read_register(txb0d0)
Print "----------------------------------------------------------"
End Sub
'ISRs
'-------------------------------------------------------------------------------------------------------------------
'ISR von INT0
Mcp2515_int:
Statusflag = 1 'Interrupt ausgelöst
Return
'-------------------------------------------------------------------------------------------------------------------
'ISR vom UART
'Uart_recieved:
' Input_uart = Udr
'Return
'-------------------------------------------------------------------------------------------------------------------
Lesezeichen