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”.


