Jak przesłać dane między CAN1, a CAN2 w STM32 bez użycia transceivera?

Na rozgrzewkę:

We wpisie 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:

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:

  • 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:

We wpisie 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 wpisach pokażę, jak dołączyć zewnętrzny transceiver i komunikować się między dwoma różnymi mikrokontrolerami STM32 po magistrali CAN.
Ten wpis powstał jako część naszych wewnętrznych testów i eksperymentów z komunikacją CAN w STM32.

Potrzebujesz pomocy przy projektowaniu elektroniki, programowaniu mikrokontrolerów? Skontaktuj się z nami.


[1] Dostęp w Internecie: https://www.keil.com/appnotes/files/apnt_236_v2.9.pdf


Podobne wpisy

Dodaj komentarz