Obsługa magistrali CAN przez mikrokontrolery PIC
Wstęp
Controller Area Network (CAN) jest szeregową magistralą danych opracowaną w latach osiemdziesiątych w firmie Robert Bosh GmbH dla przemysłu samochodowego. Jej wprowadzenie spowodowało zmniejszenie ilości okablowania łączącego moduły pojazdu oraz umożliwiło wymianę danych między sterownikami.
Zastosowanie
CAN znajduje również zastosowanie:
– w przemysłowych magistralach polowych,
– lotnictwie, CANaerospace oraz implementacja magistrali w Airbus A380 [2],
– pojazdach wojskowych (MilCAN),
– sterowaniu automatyką w budynkach.
Cechy
Najważniejszymi cechami magistrali CAN:
– do 8 bajtów w komunikacie,
– komunikaty są rozpoznawane przez identyfikatory (trafiają do wybranych adresatów),
– automatyczna obsługa dostępu do magistrali,
– możliwość określenia priorytetu komunikatu (im wyższa wartość liczbowa tym komunikat ma niższy priorytet).
Standaryzacja
Standardy magistrali CAN w wersji 2.0 określa specyfikacja firmy BOSH:
– wersja 2.0A posiada 11 bitowy identyfikator,
– wersja 2.0B posiada 29 bitowy identyfikator.
Prędkość transmisji danych
Zgodnie ze standaryzacją Międzynarodowej Organizacji Normalizacyjnej magistrala osiąga następujące przepustowości:
– do 1Mb/s, standard ISO 11898 (High speed CAN bus)
– do 125kb/s, standard ISO 11519 (Low speed CAN bus).
Transmisja danych
Magistrala może pracować w dwóch poziomach logicznych:
– dominującym (ang. “dominant”), na magistralę zapisywane jest logiczne zero,
– recesywny (ang. “recessive”), na magistralę zapisywana jest logiczna jedynka.
Medium transmisyjnym w magistrali CAN jest dwużyłowy kabel typu skrętka. Urządzenia podłączone są do medium w topologii magistrali, która zakończona jest rezystorami terminującymi o wartości 120Ω.
Rys. Topologia magistrali CAN z rezystorami terminującymi.
Każde z urządzeń nazywane jest węzłem (node), którego składowymi są:
– Mikrokontroler (sterujący pracą urządzenia oraz odpowiedzialny za komunikację po magistrali CAN),
– Kontroler CAN, najczęściej wbudowany w mikrokontroler (np. PIC18F25K80). Jego zadaniem jest budowa ramki danych, wykrywanie kolizji itp.
– Transceiver CAN, będący zwykle oddzielnym układem (np. MCP2551). Dostosowuje poziomy napięć pomiędzy magistralą a mikrokontrolerem.
Rys. Elementy węzła – urządzenia podłączonego do magistrali CAN
Układ testowy
Układ testowy został zrealizowany na płytce stykowej. Zastosowano dwa mikrokontrolery PIC18F25K80 do których podłączono transceivery MCP2551.
Układ scalony MCP2551 jest transceiverem CAN pracującym z maksymalną prędkością 1 Mb/s zgodnie ze standardem ISO-11898. Do jednej magistrali może zostać podłączonych do 112 urządzeń wyposażonych w tego typu transceivery.
Rys. Układ testowy
Zadaniem układu testowego jest zrealizowanie komunikacji pomiędzy dwoma urządzeniami połączonymi za pośrednictwem magistrali CAN.
Urządzenie #1 połączone jest z komputerem PC przez przejściówkę (USB-UART), otrzymuje ono znak za pośrednictwem konsoli i wysyła je na magistralę CAN. Następnie przechodzi w stan oczekiwania na odpowiedź i po otrzymaniu ramki danych (zawierającej jeden znak) wysyła go do komputera (wyświetlając go w konsoli).
Urządzenie #2 pełni funkcję “Echo”. Wszelkie adresowane do tego urządzenia dane są odsyłane do nadawcy.
Rys. Schemat ideowy układu testowego.
Program dla mikrokontrolerów
Program dla mikrokontrolerów został napisany w CCS C. Głównymi elementami programu na które należy zwrócić uwagę są:
- Podłączenie biblioteki ca-18f4580.c
#include
- Definicja adresów płytek
#define BOARD1_ID 1 #define BOARD2_ID 2
- Utworzenie zmiennych
struct rx_stat rxstat; int32 rx_id; int32 tx_id; int8 rx_len; unsigned int8 buffer[8];
- Inicjacja CAN
can_init();
- Wysłanie zawartości zmiennej buffer do adresata przez magistralę CAN
can_putd(BOARD2_ID, buffer, sizeof(buffer), 1, 1, 0);
- Wykrycie otrzymanych danych z magistrali CAN
can_kbhit();
- Pobranie danych do zmiennej buffer
can_getd(rx_id, buffer, rx_len, rxstat);
Źródło dla urządzenia #1
#include #fuses INTRC_IO, NOPROTECT, PUT, BROWNOUT, NOWDT,NOMCLR #use delay(clock=8000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) #include #define BOARD1_ID 1 #define BOARD2_ID 2 struct rx_stat rxstat; int32 rx_id; int32 tx_id; int8 rx_len; unsigned int8 buffer[8]; void clear_buffer(){ for(int8 x=0;x<8;x++){ buffer[x]=0; } }void main() { can_init(); delay_ms(500); printf("Uruchomiono, oczekuje na znaki\n"); while(1) { clear_buffer(); buffer[0] = getc(); // oczekiwanie na znak z uart printf("Wysylam %d\n",buffer[0]); // transmisja do modulu 2. can_putd(BOARD2_ID, buffer, sizeof(buffer), 1, 1, 0); clear_buffer(); // wyczyszczenie bufora // oczekiwanie na echo z modulu 2 while(!can_kbhit()); // jesli pobrano wiadomosc if(can_getd(rx_id, buffer, rx_len, rxstat)) { if(rx_id == BOARD1_ID) // wiadomosc dla modulu 1 { printf("Odebralem %d\n", buffer[0]); } } } } |
Źródło dla urządzenia #2
#include #fuses INTRC_IO, NOPROTECT, PUT, BROWNOUT, NOWDT,NOMCLR #use delay(clock=8000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS) #include #define BOARD1_ID 1 #define BOARD2_ID 2 struct rx_stat rxstat; int32 rx_id; int32 tx_id; int8 rx_len; unsigned int8 buffer[8]; void clear_buffer(){ for(int8 x=0;x<8;x++){ buffer[x]=0; } } void main() { can_init(); while(1){ clear_buffer(); // Dostepna wiadomosc z CAN if(can_kbhit()) { // jesli pobrano wiadomosc if(can_getd(rx_id, buffer, rx_len, rxstat)) { if(rx_id == BOARD2_ID) // wiadomosc dla modulu 2 { // odeslanie danych do nadawcy - echo can_putd(BOARD1_ID, buffer, sizeof(buffer), 1, 1, 0); } } } } } |
Odnośniki
Pliki projektu:
Noty katalogowe:
- PIC18F25K80 – mikrokontroler
- MCP2551 – transceiver CAN
Linki:
- [1]http://winntbg.bg.agh.edu.pl/rozprawy/9960/full9960.pdf – Waldemar Mikluszka “Synteza i weryfikacja algorytmów konwersji protokołów komunikacyjnych w polowych magistralach rozgłoszeniowych”. Rozprawa doktorska, AGH 2007r., strona 62.
- [2]http://www.aviationtoday.com/av/issue/feature/can-bus-in-aviation_31468.html – T.V. Rao “CAN Bus in Aviation”.