Chciałem zrobić prostą komunikację po sieci CAN. Do tego celu użyłem (zrobiłem) dwa identyczne układy jak na Rys. poniżej. Oba układy połączone są skrętką dwóch przewodów a w jednym z nich zapięty jest S1 (rezystor 120R). Program pisałem w Bascomie i jego listing wygląda tak:
Kod: Zaznacz cały
$regfile = "m128def.dat"
$crystal = 8000000
$hwstack = 32 'domyślnie 32 dla stosu sprzętowego
$swstack = 8 'domyślnie 10 dla stosu SW
$framesize = 24 'domyślnie 40 dla ramek
Rem ########## konfiguracja kilku portów ######################################
Config Porta = Input
Porta = &B11111111
Config Portc = Output
Portc = &B00000011
Config Portb.4 = Output
Config Portb.5 = Output
Config Portb.6 = Output
Config Portd.7 = Input : Portd.7 = 1 ' pin master/slave
Master_slave Alias Pind.7
Declare Sub Mcpinit()
Declare Sub Canwrite(byval Reg_add As Byte , Byval Reg_val As Byte)
Declare Sub Canmod(byval Reg_add As Byte , Byval Reg_mask As Byte , Byval Reg_val As Byte)
Declare Function Canread(byval Reg_add As Byte ) As Byte
'##### Konfiguracja wstępna SPI
Config Portb.0 = Output 'MCP_CS
Mcp_cs Alias Portb.0
Set Mcp_cs 'aktywny stan niski
Config Pind.0 = Input 'MCP Interrupt MCP2515 /INT
'##### Deklaracja stałych adresowych ###########################################
Const Cmd_read = &H03 'Read Command
Const Cmd_write = &H02 'Write Command
Const Cmd_bitmodify = &H05 'Bit-modify Command
Const Cmd_reset = &HC0 'Reset Command
Const Canctrl = &H0F 'Control Register
Const Txb0d0 = &B00110110 ' Bufor transmisyjny, Bajt danych 0
Const Rxm0sidh = &B00100000 ' Bufor odbiorczy 0, Std Identifier High
Dim Data_tmp As Byte 'Tymczasowy bit danych
Dim Canstatus As Byte 'Status
Dim Spi_write_buff(3) As Byte 'Bufor wysyłania
Dim Spi_mod_buff(4) As Byte 'Modbufor
Dim Spi_read_buff(2) As Byte 'Bufor odbioru
Config Int0 = Falling 'Przerwanie na INT0 od MPC2515
On Int0 Can_int Nosave 'przerwanie na odbiór CAN (tryb SLAVE)
Enable Interrupts 'uruchomienie przerwań
'##### Właściwa konfiguracja SPI ###############################################
'SPI
Config Portb.2 = Output 'MOSI
Config Portb.3 = Input 'MISO
Config Portb.1 = Output 'SCK
Config Portb.0 = Output '/SS - /CS
Config Spi = Hard , Data Order = Msb , Master = Yes , Noss = 0 , Clockrate = 4
Spiinit
'*******************************************************************************
Call Mcpinit()
Data_tmp = Canread(canctrl)
'##### Obsługa Master/Slave ####################################################
Dim Do_wyswietlenia As Byte
Dim Licznik As Byte
If Master_slave = 0 Then 'gdy jumper zdjety, tryb SLAVE
Enable Int0
Do
Portc = Do_wyswietlenia
Waitms 250
Loop
Else ' Gdy jumper założony, tryb BASTER
Do
Incr Licznik
Reset Mcp_cs
Waitus 1
Call Canwrite(txb0d0 , Licznik)
Waitus 1
Set Mcp_cs
If Licznik > 10 Then Licznik = 0
Waitms 1000
Loop
End If
End
Can_int:
Reset Mcp_cs
Waitus 1 'tutaj odczytanie danych z CAN
Do_wyswietlenia = Canread(txb0d0) 'odczytujemy daną z Txb0d0, czyli pierwszy adres z brzegu
Waitus 1
Set Mcp_cs
Return
Sub Mcpinit()
Local Can_tmp As Byte 'Lokale Variable
Can_tmp = Cmd_reset
Reset Mcp_cs
Waitus 1
Spiout Data_tmp , 1
Waitus 1
Set Mcp_cs
Waitus 20 'Warten bis Reset erledigt, evtl. Abfrage MCP einbauen ?
Print "done!"
Rem change prescaler...
Spi_write_buff(1) = Cmd_write
Spi_write_buff(2) = Canctrl
Spi_write_buff(3) = &B00000100 'Prescaler auf Takt/1
Reset Mcp_cs
Waitus 1
Spiout Spi_write_buff(1) , 3
Waitus 1
Set Mcp_cs
End Sub
Sub Canwrite(reg_add , Reg_val) 'Subroutine "schreiben"
Spi_write_buff(1) = Cmd_write
Spi_write_buff(2) = Reg_add
Spi_write_buff(3) = Reg_val
Spiout Spi_write_buff(1) , 3
End Sub
Sub Canmod(reg_add , Reg_mask , Reg_val)
Spi_mod_buff(1) = Cmd_bitmodify
Spi_mod_buff(2) = Reg_add
Spi_mod_buff(3) = Reg_mask
Spi_mod_buff(4) = Reg_val
Spiout Spi_mod_buff(1) , 4
End Sub
Function Canread(reg_add)
Spi_read_buff(1) = Cmd_read
Spi_read_buff(2) = Reg_add
Spiout Spi_read_buff(1) , 2
Spiin Canread , 1
End Function
To mój pierwszy układ z CANem i mogę kilku rzeczy nie wiedzieć. Program wziąłem z jakiejś niemieckiej strony i zaadoptowałem do swoich warunków, ale i tak nie chodzi. Nie wiem gdzie może być błąd, bo gdzieś jest, skoro nie działa?
Procek taktowany jest wewnętrznym zegarem 8MHz.