Atmega128 i MCP2515 - problem.

To forum jest dla wszystkich pasjonatów mikrokontrolerów AVR Atmela. Wymiana doświadczeń i pomoc dla początkujących w pisaniu programów zarówno w C, Asemblerze jak i BASCOM. Zapraszam znawców tematu, aby pomogli wszystkim początkującym!
ODPOWIEDZ
Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Atmega128 i MCP2515 - problem.

Post autor: M@ciej » 02 gru 2009, 12:06

Witam.

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
Z założenia program ma odliczać co sekundę od 1 do 10 i te liczby wysyłać przez CAN. Płytka odbiornika ma pokazywać binarnie te wartości na 8 diodach LED. Problem w tym, że niestety komunikacja nie następuje i nic się nie dzieje?

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.
Załączniki
CAN.jpg

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 02 gru 2009, 18:28

Tu coś masz po polsku: (nie wiem na ile ci się przyda ?)
http://www.pelek.org/Publikacje/SCR06_01.pdf
Tu masz PDFa z kartą katalogową.
http://ww1.microchip.com/downloads/en/D ... 21801d.pdf
Ciekawy temat na elektrodzie z sporą ilością linków :
http://www.elektroda.pl/rtvforum/topic641670.html

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 02 gru 2009, 19:41

Dzięki za odp. Nie wiedziałem,ze w ogóle ktoś odpisze. Pierwszy link mi trochę pomógł, bo chociaż jest tam opis bibliotek do C, to kilka informacji o MPC2515 tam znalazłem. Notkę katalogową mam (nie robiłbym na układzie, którego notki nie widziałem).

Problem w tym, że ten MCP2515 ma wiele różnych rejestrów, które trzeba wypełnić odpowiednimi danymi konfiguracyjnymi i w tym chyba tkwi problem.

Dużo szukałem na necie gotowców pod Bascom. Jest kilka z nich na niemieckich stronach poświęconych robotyce, ale żaden z nich (po przystosowaniu do pinologii Atmega128) nie działał, dlatego się tu zwróciłem.

alaris
Użytkownik
Posty: 530
Rejestracja: 21 lut 2006, 14:56
Lokalizacja: Gorzow/Poznan

Post autor: alaris » 02 gru 2009, 20:23

Sprawdz, czy w tym MCP nie ma czegos takiego jak zapetlenie (tryb LOOP BACK czy jakos tak). Jest to uzyteczna rzecz, bo masz w tym trybie niejako polaczony nadajnik z odbiornikiem. To co wyslesz zaraz trafi do rejestrow odbiorczych MCP i bedziesz mogl latwo zweryfikowac czy scalak w ogole dziala.

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 04 gru 2009, 13:06

Znalazłem kilka błędów na płytkach oraz w programie (chciałem odczytywać dane z bufora transmisyjnego, zamiast odbiorczego). Po poprawieniu błędów fizycznych i przestawieniu adresów na właściwe niestety nadal nie działa :( Spróbuję wpisać coś do buforów a potem odczytać na razie w obrębie tego samego scalaka.

Inna sprawa, że we wszystkich przykładach komenda do wysyłania jest zdefiniowana pod &H02 a do odbioru pod &H03, tymczasem w PDFie do MCP2515 pod tymi adresami są jakieś filtry i nie rozumiem tego właśnie.

Zależy mi na jak najprostszym przesyłaniu danych pomiędzy dwoma MCP.

[ Dodano: 2009-12-04, 14:28 ]
Próba zapisu i odczytu kilku rejestrów wykazała, że cokolwiek wpiszę do rejestru transmisyjnego, dostaję zawsze wartość 255(dec). Wniosek z tego, że zawodzi komunikacja po SPI. Jak się okazuje, układ MPC2515 jest niewybrany i na jego wejściu /CS panuje zawsze stan wysoki. Sygnał /CS układu mam połączony z /SS i każda próba wyzerowania tego bitu (w Atmega128 jest to Portb.0) kończy się niepowodzeniem i nie wiem dlaczego?

Awatar użytkownika
kayron
Użytkownik
Posty: 2088
Rejestracja: 21 wrz 2008, 12:53
Lokalizacja: Poland
Kontakt:

Post autor: kayron » 04 gru 2009, 16:37

W takim razie możesz mieć źle skonfigurowany SPI. W nowych Megach ma aż 4 tryby pracy. ustawia sie tam zbocze, sygnały itd. (szczegóły w helpie bascoma), ale można tam też odciąć linię /SS. I ja bym tak zrobił na początek, odciął linię /SS i sterował sobie nią sam programowo. Być może właśnie dla tego próby sterowania /SS ci nie wychodzą, bo jest przypisana do sprzętowego SPI i nie można wtedy nią sterować dowolnie. Ogólnie przestudiuj sobie dobrze HELP z BASCOMA na temat SPI. Ostatecznie popróbuj z różnymi konfiguracjami tego portu. Nie musisz zmieniać szybkości transmisji.

Awatar użytkownika
M@ciej
Użytkownik
Posty: 736
Rejestracja: 13 sie 2005, 21:38
Lokalizacja: Szczecin

Post autor: M@ciej » 04 gru 2009, 18:19

Waśnie dałem parametr "Noss=1", czyli wyłączyłem, ale nadal nie przesyła i dostaję 255 z buforów. Pozostaje kombinacja trybów pracy SPI. jak Kolega wyżej zauważył. Przyjrzę się tej sprawie.

[ Dodano: 2009-12-05, 13:17 ]
Kombinowałem z ustawieniami SPI i nadal nic. Moje wątpliwości budzą adresy komend zapisu/odczytu jako 03 i 02. W PDFie do MPC2515 nie znalazłem takich adresów, za to pod tymi adresami są jakieś filtry.

[ Dodano: 2009-12-05, 13:44 ]
No, udało się zapisywać i odczytywać z rejestrów. Nie wiem dlaczego, ale przy każdej operacji na SPI muszę uaktywniać (zerować) /CS i ustawiać go z powrotem, niemniej to jest furtka do dalszych działań :)

ODPOWIEDZ