Liste der Anhänge anzeigen (Anzahl: 1)
Funktionierendes CAN Bus Projekt entwickeln unter Bascom
Hallo zusammen,
ich möchte gemeinsam mit mehreren (und Euch) enlich mal das Problem des CAN Busses unter Bascom lösen.
Ich habe mich zu der Version mit dem MCP 2115 Controller und einem Mega 8 entschieden. Der MCP 2515 ist ein CAN Bustreiber auf SPI Basis, somit kann man sinnvoll die Programmierports nutzen.
Ich weiß, diese Kombination gibt es schon in diesem Forum - und das auch noch funktionstätig - jedoch nur unter C!
ich habe viel im Netz gesucht und bin leider immer nur unter C fündig geworden und ein nicht vollendetes Bascomprogramm.
Ich denke das kann man auch unter Bascom lösen, vielleicht gemeinsam.
Ich habe mal in einem Forum einen Quelltext unter Bascom gefunden, der schafft auch irgendeine Kommunikation mit dem Chip, aber senden tut das Ding nix. Man muss nur zwischen den SPI Befehlen einen 21ms wait Befehl einfügen.
Zum Verständniss des Chips MCP 2515 und die Funktion um senden zu können:
1. Slave Select auf Masse und das Manuel
2. Register 1 anwählen und mit Daten beschreiben
3. Register 2 anwählen und mit Daten beschreiben
4. Register 3 anwählen und mit Daten beschreiben
5. Slave Select wieder manuell auf Potential
...... und die Kiste müsste senden.
Kann mir das jemand bestätigen? Mal abgesehen das vorher ein Reset und der Takt eingestellt werden müssen.
Besten Dank
Liste der Anhänge anzeigen (Anzahl: 1)
CAN Bus für alle
Hallo zusammen,
ich möchte mal auf den Grundgedanken von Michael_avr zurück kommen.
Ein gewöhlicher AVR Chip mit MCP 2515 auf der einen und ein paar Ein- und Ausgängen auf der anderen Seite sowie ggf ein LCD Display.
Das alles für einen verträglichen Preis mit dem auch ein Hobbyelektroniker ein paar Chrashs wegstecken kann.
Ich sitze jetzt schon eine lange Zeit an diesem Thema und gebe immer wieder vor Verzweiflung auf. Ich denke nach den unzähligen Forenbeiträgen über dieses Thema, dass es bisher keinem gelungen ist, ein solches Projekt in Bascom in die Praxis umzusetzen.
Fangen wir doch einmal einfach an.
Über den CAN Bus soll eine LED mit einem Taster ein und aus geschaltet werden. Wie kann man das machen?
Wie sieht die Hardware und die Software aus?
Es wäre schön wenn sich an dieser Stelle viele beteiligen würden, so dass wir in kleinen Schritten zu einem Ergebnis kommen können.
Tobias
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo,
ich habe vor einiger Zeit eine Schaltung gefunden mit der ein Atmega8 am Can Bus zu betreiben ist. Leider war dort keine Bascom sondern nur C-Software vorhanden. http://www.kreatives-chaos.com/artikel/can-testboard
Kann jemand sagen ob der hier beschriebene Schaltungsaufbau auch mit Bascom funktioniert?
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Vitis,
ich habe jetzt eine Schaltung, analog zu der des CanTestBoard aufgebaut.
Die dort genutzten Pins musste ich etwas anpassen.
Den Code habe ich wie folgt angepasst:
Code:
$regfile = "m8def.dat" ' ATMega8
$crystal = 7372800 ' Baudratenquarz der AVR (MCP2515 mit 16MHz)
$hwstack = 40 ' default use 32 for the hardware stack
$swstack = 80 ' default use 10 for the SW stack
$framesize = 90
Declare Sub Can_init()
Declare Sub Mcp2515_write(byval Reg_add As Byte , Byval Reg_val As Byte)
Declare Sub Mcp2515_bitmodify(byval Reg_add As Byte , Byval Reg_mask As Byte , Byval Reg_val As Byte)
Declare Function Mcp2515_read(byval Reg_add As Byte) As Byte
Mcp2515cs Alias Portb.4 'MISO
Config Mcp2515cs = Output
Const Cmd_read = &H03 ' Read Command
Const Cmd_write = &H02 ' Write Command
Const Cmd_bitmodify = &H05 ' Bit-modify Command
Const Cmd_readstatus = &HA0 ' Read Status Command (poll)
Const Cmd_read_rx_status = &HB0
Const Cmd_reset = &HC0 ' Reset Command
Const Cmd_rts0 = &H81
Const Cmd_rts1 = &H82
Const Caninte = &H2B
Const Canctrl = &H0F
Const Canstat = &H0E ' Statusregister
Const Eflg = &H2D ' Error Flag Register
Const Cnf3 = &H28 ' Configuration Register 3
Const Cnf2 = &H29 ' Configuration Register 2
Const Cnf1 = &H2A ' Configuration Register 1
Const Txb0ctrl = &B00110000 ' Transmit Buffer 0 Control Register
Const Txb0sidh = &B00110001 ' Transmit Buffer 0 Std Identifier High
Const Txb0sidl = &B00110010 ' Transmit Buffer 0 Std Identifier Low
Const Txb0eid8 = &B00110011 ' Transmit Buffer 0 Ext Identifier High
Const Txb0eid0 = &B00110100 ' Transmit Buffer 0 Ext Identifier Low
Const Txb0dlc = &B00110101 ' Transmit Buffer 0 Data Length Code
Const Txb0d0 = &B00110110 ' Transmit Buffer 0 Data Byte 0
Const Txb0d1 = &B00110111 ' Transmit Buffer 0 Data Byte 1
Const Txb0d2 = &B00111000 ' Transmit Buffer 0 Data Byte 2
Const Txb0d3 = &B00111001 ' Transmit Buffer 0 Data Byte 3
Const Txb0d4 = &B00111010 ' Transmit Buffer 0 Data Byte 4
Const Txb0d5 = &B00111011 ' Transmit Buffer 0 Data Byte 5
Const Txb0d6 = &B00111100 ' Transmit Buffer 0 Data Byte 6
Const Txb0d7 = &B00111101 ' Transmit Buffer 0 Data Byte 7
Const Rxm0sidh = &B00100000 ' Receive Buffer 0 Std Identifier High
Const Rxm0sidl = &B00100001 ' Receive Buffer 0 Std Identifier Low
Const Rxm0eid8 = &B00100010 ' Receive Buffer 0 Ext Identifier High
Const Rxm0eid0 = &B00100011 ' Receive Buffer 0 Ext Identifier low
Const Rxm1sidh = &B00100100 ' Receive Buffer 1 Std Identifier High
Const Rxm1sidl = &B00100101 ' Receive Buffer 1 Std Identifier Low
Const Rxm1eid8 = &B00100110 ' Receive Buffer 1 Ext Identifier High
Const Rxm1eid0 = &B00100111 ' Receive Buffer 1 Ext Identifier low
Const Rxb0ctrl = &H60
Const Rxb1ctrl = &H70
' Hardware SPI-Schnittstelle konfigurieren
'Config Portb.6 = Input 'Vitis
'Config Portb.5 = Output 'Vitis
'Config Portb.7 = Output 'Vitis
Config Portb.4 = Input
Config Portb.3 = Output
Config Portb.5 = Output
Spcr = &B01010010
'Config Pind.2 = Input 'Vitis
Config Pind.3 = Input
Config Int0 = Falling
On Int0 Int_canint
Enable Int0
Enable Interrupts
Call Can_init()
Do
' Zu übertragende Daten setzen:
Mcp2515_bitmodify Txb0ctrl , &B00000011 , &B00000011 ' TX-Konfiguration
Mcp2515_write Txb0sidh , &B01010101 ' Empfängeradresse setzen
Mcp2515_write Txb0sidl , &B01010101 ' Empfängeradresse setzen
Mcp2515_write Txb0dlc , &H04 ' Paketlänge festlegen
Mcp2515_write Txb0d0 , &B01010101 ' Zu übertragende Daten setzen
Mcp2515_write Txb0d1 , &B01010101 ' Zu übertragende Daten setzen
' Übertragung auslösen
Reset Mcp2515cs
Waitus 10
Spdr = Cmd_rts0
Do
Loop Until Spsr.spif = 1
Waitus 10
Set Mcp2515cs
Loop
Sub Can_init()
Local Can_tmp As Byte
Reset Mcp2515cs
' Reset MCP2515
Can_tmp = Cmd_reset
Spdr = Can_tmp
Do
Loop Until Spsr.spif = 1
Set Mcp2515cs
Waitms 2000
Mcp2515_write Canctrl , &B10001000 ' low nibble: 3=OSM 2=CLK-Pin 1-0=CLK Divider
Print "speed change done"
' F MCP2515 = 16MHz
Can_tmp = Eram_param_baudrate
Select Case Can_tmp
Case 0:
' CAN 31,25 KHz
Mcp2515_write Cnf1 , &B00001111
Case 1:
' CAN 62,5 KHz
Mcp2515_write Cnf1 , &B00000111
Case 2:
' CAN 125 KHz
Mcp2515_write Cnf1 , &B00000011
Case 3:
' CAN 250 KHz
Mcp2515_write Cnf1 , &B00000001
Case 4:
' CAN 500 KHz
Mcp2515_write Cnf1 , &B00000000
Case Else :
Mcp2515_write Cnf1 , &B00001111
End Select
Mcp2515_write Cnf2 , &B10010000 ' Cnf2 = &H29
Mcp2515_write Cnf3 , &B00000010 ' Cnf3 = &H28
Mcp2515_write Caninte , &B00000011
Mcp2515_write Rxb0ctrl , &B01100000
Mcp2515_write Rxb1ctrl , &B01100000
Mcp2515_write Rxm0sidh , 0 ' Empfängeradressen auf 0, Filter aus
Mcp2515_write Rxm0sidl , 0
Mcp2515_write Rxm0eid8 , 0
Mcp2515_write Rxm0eid0 , 0
Mcp2515_write Rxm1sidh , 0
Mcp2515_write Rxm1sidl , 0
Mcp2515_write Rxm1eid8 , 0
Mcp2515_write Rxm1eid0 , 0
Mcp2515_bitmodify Canctrl , &B11100000 , &B00000000
'Mcp2515_write Canctrl , &B00000000 ' low nibble: 3=OSM 2=CLK-Pin 1-0=CLK Divider
'Mcp2515_write Canctrl , &HE0
End Sub
Sub Mcp2515_bitmodify(reg_add , Reg_mask , Reg_val)
Local Can_tmp2 As Byte
Mcp2515cs = 0
Can_tmp2 = Cmd_bitmodify
Spdr = Can_tmp2
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
Mcp2515cs = 1
End Sub
Sub Mcp2515_write(reg_add , Reg_val)
Local Can_tmp2 As Byte
Mcp2515cs = 0
Can_tmp2 = Cmd_write
Spdr = Can_tmp2
Do
Loop Until Spsr.spif = 1
Waitms 2
Spdr = Reg_add
Do
Loop Until Spsr.spif = 1
Spdr = Reg_val
Do
Loop Until Spsr.spif = 1
Mcp2515cs = 1
End Sub
Function Mcp2515_read(reg_add)
Local Can_tmp2 As Byte
Mcp2515cs = 0
Can_tmp2 = Cmd_read
Spdr = Can_tmp2
Do
Loop Until Spsr.spif = 1
Spdr = Reg_add
Do
Loop Until Spsr.spif = 1
Spdr = 0
Do
Loop Until Spsr.spif = 1
Mcp2515_read = Spdr
Mcp2515cs = 1
End Function
Und jetzt gleich ein paar Fragen:
1. Die Adressierung der einzelnen Knoten spielt eine wichtige Rolle.
Wo ist die Adresse dieses Konoten festgelegt?
2. Verstehe ich es richtig dass der Empfängerknoten unter &B01010101 zu erreichen ist
3. Woraus leitest du die Peketlänge "&H04" ab?
Tobias
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
ich habe mich zwischenzeitlich mal an die Hardware gemacht und das hier beschriebene CAN-MEGA8 Modul nach dem Entwurf aus "kreatives-chaos.com" nachgebaut.
Nach regem Kontakt mit Vitis habe ich das folgende Programm in so weit angepasst dass es zumindes möglich sein sollte, eine Nachricht (welcher Taster gedückt wurde) über den CAN Bus zu senden.
Code:
'Testprogramm CAN Sender und Empfänger
$regfile = "m8def.dat" ' ATMega8
$crystal = 7372800 ' Baudratenquarz der AVR (MCP2515 mit 16MHz)
$hwstack = 40 ' default use 32 for the hardware stack
$swstack = 80 ' default use 10 for the SW stack
$framesize = 90
$baud = 9600
' Allgemeine Config ************************************************************
Const Keys = 5 '5 angeschlossene Taster
Config Pinc.0 = Input 'Eingang 1 bis 5
Config Pinc.1 = Input
Config Pinc.2 = Input
Config Pinc.3 = Input
Config Pinc.4 = Input
Config Pinc.5 = Input
Config Portb.0 = Output 'Relaisausgang 1 bis 5
Config Portb.1 = Output
Config Portb.2 = Output
Config Portd.7 = Output
Config Portd.6 = Output
Dim I As Byte
Dim Key As Byte
Dim T1 As Bit 'Variable für Tasterzustand
Dim T2 As Bit
Dim T3 As Bit
Dim T4 As Bit
Dim T5 As Bit
Dim Taster As Byte
Portb.0 = 0 'Grunsstellung fixieren
Portb.1 = 0
Portb.2 = 0
Portd.7 = 0
Portd.6 = 0
'CAN relevante Config **********************************************************
Declare Sub Mcp2515_write(byval Reg_add As Byte , Byval Reg_val As Byte)
Declare Sub Mcp2515_bitmodify(byval Reg_add As Byte , Byval Reg_mask As Byte , Byval Reg_val As Byte)
Declare Function Mcp2515_read(byval Reg_add As Byte) As Byte
Mcp2515cs Alias Portd.4 'CS am 2515
Config Mcp2515cs = Output
Const Cmd_read = &H03 ' Read Command
Const Cmd_write = &H02 ' Write Command
Const Cmd_bitmodify = &H05 ' Bit-modify Command
Const Cmd_readstatus = &HA0 ' Read Status Command (poll)
Const Cmd_read_rx_status = &HB0
Const Cmd_reset = &HC0 ' Reset Command
Const Cmd_rts0 = &H81
Const Cmd_rts1 = &H82
Const Caninte = &H2B
Const Canctrl = &H0F
Const Canstat = &H0E ' Statusregister
Const Eflg = &H2D ' Error Flag Register
Const Cnf3 = &H28 ' Configuration Register 3
Const Cnf2 = &H29 ' Configuration Register 2
Const Cnf1 = &H2A ' Configuration Register 1
Const Txb0ctrl = &B00110000 ' Transmit Buffer 0 Control Register
Const Txb0sidh = &B00110001 ' Transmit Buffer 0 Std Identifier High
Const Txb0sidl = &B00110010 ' Transmit Buffer 0 Std Identifier Low
Const Txb0eid8 = &B00110011 ' Transmit Buffer 0 Ext Identifier High
Const Txb0eid0 = &B00110100 ' Transmit Buffer 0 Ext Identifier Low
Const Txb0dlc = &B00110101 ' Transmit Buffer 0 Data Length Code
Const Txb0d0 = &B00110110 ' Transmit Buffer 0 Data Byte 0
Const Txb0d1 = &B00110111 ' Transmit Buffer 0 Data Byte 1
Const Txb0d2 = &B00111000 ' Transmit Buffer 0 Data Byte 2
Const Txb0d3 = &B00111001 ' Transmit Buffer 0 Data Byte 3
Const Txb0d4 = &B00111010 ' Transmit Buffer 0 Data Byte 4
Const Txb0d5 = &B00111011 ' Transmit Buffer 0 Data Byte 5
Const Txb0d6 = &B00111100 ' Transmit Buffer 0 Data Byte 6
Const Txb0d7 = &B00111101 ' Transmit Buffer 0 Data Byte 7
Const Rxm0sidh = &B00100000 ' Receive Buffer 0 Std Identifier High
Const Rxm0sidl = &B00100001 ' Receive Buffer 0 Std Identifier Low
Const Rxm0eid8 = &B00100010 ' Receive Buffer 0 Ext Identifier High
Const Rxm0eid0 = &B00100011 ' Receive Buffer 0 Ext Identifier low
Const Rxm1sidh = &B00100100 ' Receive Buffer 1 Std Identifier High
Const Rxm1sidl = &B00100101 ' Receive Buffer 1 Std Identifier Low
Const Rxm1eid8 = &B00100110 ' Receive Buffer 1 Ext Identifier High
Const Rxm1eid0 = &B00100111 ' Receive Buffer 1 Ext Identifier low
Const Rxb0ctrl = &H60
Const Rxb1ctrl = &H70
' Hardware SPI-Schnittstelle konfigurieren
Config Portb.4 = Input 'MISO von 2515
Config Portb.3 = Output 'MOSI von 2515
Config Portb.5 = Output 'SCK
Spcr = &B01010001 'Bit7=0:IntAus, Bit6=1:SPIAn, Bit5=0:MSBfirst,
'Bit4=1:Masterfunktion, Bit3=0:SCK=0wennIdle,
'Bit2=0:L-H-Flanke, Bit1+0=01:AVRClock/16
'Config Pind.3 = Input 'INT1 am AVR und MCP2515
Config Int1 = Falling
On Int1 Int_canint 'Interrupt zum empfangen
Enable Int1
Enable Interrupts
'Programm Start*****************************************************************
Print "Start Programm"
Gosub Can_init
Do
For I = 1 To Keys
Key = I
Select Case Key
Case 1 : Debounce Pinc.0 , 0 , Key_o1 , Sub 'Port 1.
Case 2 : Debounce Pinc.1 , 0 , Key_o2 , Sub 'Port 2
Case 3 : Debounce Pinc.2 , 0 , Key_o3 , Sub 'Port 3
Case 4 : Debounce Pinc.3 , 0 , Key_o4 , Sub 'Port 4
Case 5 : Debounce Pinc.4 , 0 , Key_o5 , Sub 'Port 5
End Select
Next
Loop
' Zustandsänderung Ausgänge
Key_o1:
Toggle Portb.0
Print "Portb.0" 'Buchse 1
If T2 = 0 Then
T2 = 1
Else
T2 = 0
End If
Gosub Data_send 'Statusänderung per CAN übertragen
Return
Key_o2:
Toggle Portb.1
Print "Portb.1" 'Buchse 2
If T5 = 0 Then
T5 = 1
Else
T5 = 0
End If
Gosub Data_send 'Statusänderung per CAN übertragen
Return
Key_o3:
Toggle Portb.2 'Buchse 3
Print "Portb.2"
If T3 = 0 Then
T3 = 1
Else
T3 = 0
End If
Gosub Data_send 'Statusänderung per CAN übertragen
Return
Key_o5:
Toggle Portd.6 'Buchse 4
Print "Portd.6"
If T1 = 0 Then
T1 = 1
Else
T1 = 0
End If
Gosub Data_send 'Statusänderung per CAN übertragen
Return
Key_o4:
Toggle Portd.7 'Buchse 5
Print "Portd.7"
If T4 = 0 Then
T4 = 1
Else
T4 = 0
End If
Gosub Data_send 'Statusänderung per CAN übertragen
Return
End
'CAN Initialisieren *****************************
Can_init:
Reset Mcp2515cs ' Reset MCP2515
Spdr = &HC0
Do
Loop Until Spsr.spif = 1
Set Mcp2515cs
Waitms 2000
'Mcp2515_write Canctrl , &B10001000 ' low nibble: 3=OSM 2=CLK-Pin 1-0=CLK Divider &B10001000
Print "speed change done"
' CAN 31,25 KHz
Mcp2515_write Cnf1 , &B00001111
Mcp2515_write Cnf2 , &B10010000 ' Cnf2 = &H29
Mcp2515_write Cnf3 , &B00000010 ' Cnf3 = &H28
Mcp2515_write Caninte , &B00000011
Mcp2515_write Rxb0ctrl , &B01100000
Mcp2515_write Rxb1ctrl , &B01100000
Mcp2515_write Rxm0sidh , 0 ' Eigene Empfängeradressen auf 00000000 setzen, kein Filter
Mcp2515_write Rxm0sidl , 0
Mcp2515_write Rxm0eid8 , 0
Mcp2515_write Rxm0eid0 , 0
Mcp2515_write Rxm1sidh , 0
Mcp2515_write Rxm1sidl , 0
Mcp2515_write Rxm1eid8 , 0
Mcp2515_write Rxm1eid0 , 0
Mcp2515_bitmodify Canctrl , &B11100000 , &B00000000
Mcp2515_write Canctrl , &B00000000 ' low nibble: 3=OSM 2=CLK-Pin 1-0=CLK Divider
Mcp2515_write Canctrl , &HE0
Return
'Daten übertargen ****************************
Data_send:
Mcp2515_bitmodify Txb0ctrl , &B00000011 , &B00000011 ' TX-Konfiguration
Mcp2515_write Txb0sidh , &B01010101 ' Empfängeradresse setzen
Mcp2515_write Txb0sidl , &B01010101 ' Empfängeradresse setzen
Mcp2515_write Txb0dlc , &H01 ' Paketlänge festlegen für ein Byte
'Hier soll der Status abgefragt werden: T1, T2, T3, T4, T5
Taster = Pinc
Taster = Taster And &B00011111
Mcp2515_write Txb0d0 , Taster ' Zu übertragende Daten setzen
' Übertragung auslösen
Print "Datenuebertragung"
Reset Mcp2515cs
Waitus 20
Spdr = Cmd_rts0
Do
Loop Until Spsr.spif = 1
Waitus 20
Set Mcp2515cs
Print "Datenuebertragung end"
Return
Int_canint:
Print "Datenempfang - Prüfung"
'Prüfung der ankommenden Daten
Print "Daten:"
Return
Sub Mcp2515_bitmodify(reg_add , Reg_mask , Reg_val)
Local Can_tmp2 As Byte
Mcp2515cs = 0
Can_tmp2 = Cmd_bitmodify
Spdr = Can_tmp2
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
Mcp2515cs = 1
End Sub
Sub Mcp2515_write(reg_add , Reg_val)
Local Can_tmp2 As Byte
Mcp2515cs = 0
Can_tmp2 = Cmd_write
Spdr = Can_tmp2
Do
Loop Until Spsr.spif = 1
Waitms 2
Spdr = Reg_add
Do
Loop Until Spsr.spif = 1
Spdr = Reg_val
Do
Loop Until Spsr.spif = 1
Mcp2515cs = 1
End Sub
Function Mcp2515_read(reg_add)
Local Can_tmp2 As Byte
Mcp2515cs = 0
Can_tmp2 = Cmd_read
Spdr = Can_tmp2
Do
Loop Until Spsr.spif = 1
Spdr = Reg_add
Do
Loop Until Spsr.spif = 1
Spdr = 0
Do
Loop Until Spsr.spif = 1
Mcp2515_read = Spdr
Mcp2515cs = 1
End Function
Beim Empfänger der 1:1 in der Hardware ist, sollte zumindest ein Interrupt ausgelöst werden und dies per Print Befehl ausgeben.
Leider funktioniert dies bei mir noch nicht. Den Fehler konnte ich bisher nicht feststellen.
Aber ich denke dass dies schon mal ein Anfang ist um vielleicht gemeinsam etwas weiter zu kommen.
Mein Vorschlag wäre, dass ihr euch die Schaltung anseht und vielleicht auch nachbaut. Irgent wo hat sich ein (Hardware-)Fehler eingeschlichen. Ich kann ihn einfach nicht finden. Vermutlich sehe ich den Wald vor lauter Bäumen nichtmehr.
Wer macht mit?
Tobias