CAN od zera część 1: Jak przesłać dane między CAN1, a CAN2 w STM32 bez użycia transceivera?
W artykule przedstawię implementację protokołu CAN na procesorze STM32G4, uwzględniając i tłumacząc filtry programowe, pokażę jak przesłać informację pomiędzy CAN1 i CAN2 używając jednego procesora, a to wszystko bez użycia transceivera.
Czasem chcemy przetestować działanie magistrali CAN lub filtrów programowych bez konieczności użycia dwóch osobnych płytek lub dodatkowych transceiverów. Taki testowy setup pozwala zweryfikować poprawność konfiguracji CAN w STM32 oraz logikę aplikacji przed wdrożeniem sprzętowym.
Przedstawienie schematu podłączenia:

Połączony układ wygląda następująco:

Rys. 1. Podłączony układ w rzeczywistości
Działanie układu:
Konfiguracja pinów:
CAN1_Tx oraz CAN2_Tx są wyjściami typu push-pull, dlatego potrzebne są diody zabezpieczające.
CAN1_Rx oraz CAN2_Rx skonfigurowane są jako wejścia AF (Alternate Function) bez pull-up oraz bez pull-down.
Zasada działania:
CAN na warstwie fizycznej rozróżnia stan dominujący (logiczne 0) i recesywny (logiczna 1). W normalnej magistrali robi to transceiver różnicowy (CAN_H/CAN_L). Tutaj transceiver jest pominięty, za to uzyskujemy zachowanie podobne do magistrali open-drain:
- Diody separujące zabezpieczają wyjścia przed sytuacją, gdzie na jednym z CAN_Tx byłby stan niski, a na drugim stan wysoki. Taka sytuacja doprowadziłaby do uszkodzenia wyjść CAN_Tx mikrokotrolera.
- Rezystor podciągający ustala pasywnie stan recesywny, poprzez podciągnięcie wspólnej linii do 3.3V.
- Kiedy któryś CAN_Tx chce nadać bit dominujący, jego wyjście ciągnie linię do zera, przez diodę przepływa prąd do masy i wspólny punkt zostaje sprowadzony do niskiego poziomu.
Dlaczego RX odbiera poprawnie?
Peryferium CAN w STM32 oczekuje sygnału z transceivera w postaci jednokanałowego poziomu logicznego: niski – dominujący, wysoki – recesywny. W tym układzie wspólny węzeł daje taki właśnie poziom (podciągnięty = 1, ściągnięty do 0 = 0), więc kanał Rx widzi poprawne stany i dekoduje ramki poprawnie.
Analiza przebiegu:
Na poniższym przebiegu przedstawiłem na kanale 0 sygnał na katodzie diody CAN1_Tx, zaś na kanale 1 przedstawiłem sygnał na liniach Rx. Jak widać na przebiegu sygnał CAN dekodowany jest poprawnie.

Konfiguracja procesora w środowisku CubeIDE:
Na początku zacznę od przedstawienia konfiguracji procesora jakiej użyję we wpisie w środowisku CubeIDE:

Konfiguracja CAN1:

Konfiguracja przerwania CAN1:

Konfiguracja CAN2:

Włączenie przerwania CAN2:

Filtry programowe CAN:
Protokół CAN jest komunikacją rozproszeniową, czyli wszystkie urządzenie podpięte do jednej magistrali otrzymują dane. W takim razie w jaki sposób urządzenia wiedzą, że informacje są przekazywane właśnie do nich? Z pomocą przychodzą filtry programowe zaimplementowane w programie. Peryferium CAN reaguje na ramkę o określonym ID, które to ID jest zgodne z ustawionymi filtrami.
Filtry jakie można wybrać podczas konfiguracji CAN w FilterType:
- RANGE FILTER – czyli ramki z zakresu od ID1 do ID2 będą uwzględniane. Służy do testów lub prostych przypadków,
- MASK FILTER – ID1 to wzorzec ID, ID2 to maska bitowa. Jeśli jest bit 1 w masce, wtedy dany bit jest porównywany, jeśli w masce jest bit 0 wtedy bit jest ignorowany. Przepuszczane są ramki które na konkretnych maski jest 1 logiczna, a ramka przychodząca ma tą samą wartość jak wzorzec ID1. Najlepszy filtr, gdy chcemy odbierać grupy ramek o wspólnym prefiksie ID,
- DUAL FILTER – dla ramek o dwóch ID równych ID1 lub ID2. Najlepszy, gdy chcemy odebrać konkretne dwa ID bez pisania osobnych filtrów,
- RANGE FILTER NO EIDM – działa tak samo jak range filter, lecz ignoruje bit (IDE) określający czy ramka jest standardowej długości czy rozszerzonej. Ten filtr jest przydatny, gdy system pracuje z mieszanymi ramkami: standardowymi i rozszerzonymi, a użytkownik chce filtrować ramki tylko po numerze ID.

Kod:
Callback od CAN1:

Callback od CAN2:

Nagłówek ramki CAN1 oraz CAN2:

Główna pętla programu:

Prezentacja funkcjonowania układu:
CAN1 wysyła informacje na temat częstotliwości i ilości mrugnięć diodą do CAN2 po naciśnięciu przycisku. CAN2 odbiera dane o częstotliwości i ilości mrugnięć diodą. Dalej następują mrugnięcia diodą z określoną częstotliwością i określoną ilością razy.
Uwagi praktyczne:
Na co uważać przy testach bez transceivera?
- Linie CAN_TX i CAN_RX w STM32 są CMOS, więc nie mają odporności na zakłócenia ani zabezpieczeń ESD.
- Działa tylko w krótkim połączeniu (na tej samej płytce).
- W realnym zastosowaniu zawsze wymagany jest transceiver (np. TJA1051, MCP2551, SN65HVD230).
Podsumowanie:
W artykule przedstawiłem prosty, testowy sposób na implementację protokołu CAN, kiedy pod ręką nie mamy transceivera oraz dysponujemy tylko jednym procesorem. W kolejnych pokażę, jak dołączyć zewnętrzny transceiver i komunikować się między dwoma różnymi mikrokontrolerami STM32 po magistrali CAN.
Artykuł powstał jako część wewnętrznych testów i eksperymentów z komunikacją CAN w STM32.
[1] Dostęp w Internecie
Źródło: DMPB

Jak wyglądał ST Ambassadors Event we Włoszech? Mateusz Pluta opisuje swoje wrażenia z wizyty w STMicroelectronics
Dominik Bednarski porównuje STM32MP1 i OpenSTLinux oraz Raspberry Pi 5
Sterownik PWM: Definicja timerów w STM32 do programowych PWM oraz odczyt ADC STM32 



