Zamienione linie danych UART na PCB? Jak uratować projekt z STM32

Udostępnij

W większości nowszych rodzin mikrokontrolerów STM32 linie RX i TX interfejsu UART można zamienić bez konieczności modyfikacji fizycznych połączeń na PCB. Takie proste rozwiązanie programowe może w niektórych przypadkach uratować błędny projekt płytki drukowanej.

Dwie pułapki w oznaczeniach linii RX i TX

Standardowy system oznaczeń, przyjęty w znakomitej większości schematów ideowych i blokowych, z którymi mamy do czynienia na co dzień, definiuje linie interfejsu asynchronicznego UART następująco:

TX - wyjście danych

RX - wejście danych

Pierwszy problem to niejednoznaczność konwencji przyjmowanych w dokumentacjach przez projektantów. O ile w przypadku interfejsów takich jak I2C wszystkie linie zegarowe lub danych o tej samej nazwie są łączone ze sobą (np. linię SCL mikrokontrolera podłączamy do SCL czujnika, a SDA procesora – do SDA sensora), to już w interfejsie UART linie są skrosowane: wyjście danych jednego układu łączymy z wejściem drugiego i na odwrót. W zależności od tego, jaką nomenklaturę przyjmiemy na schemacie, będzie ona niejako „prawidłowa” tylko dla jednego z układów – a zatem nietrudno o pomyłkę na etapie rysowania dokumentacji. Przykładowo na poniższym schemacie oznaczenia nadano „z punktu widzenia” mikrokontrolera.

Przykład schematu ideowego z oznaczeniami linii UART zdefiniowanymi z punktu widzenia mikrokontrolera: linia PA9 to wyjście danych (TXD) mikrokontrolera, podczas gdy PA10 to wejście – RXD (rys. HardwareDesigner.pl)

Oczywiście można ów problem rozwiązać na poziomie samego nazewnictwa, wyraźnie identyfikując przeznaczenie danej sieci (np. MCU_RX, MCU_TX), ale z różnych względów nie zawsze takie rozwiązanie będzie użyteczne lub pożądane.

Kolejne źródło niejednoznaczności wynika z różnic w sposobie opisywania linii UART-u w dokumentacjach niektórych układów scalonych oraz modułów. Poniżej pokazano zrzut ekranu z tabeli wyprowadzeń zamieszczonej w nocie katalogowej modułu u-blox SARA-N3. Wprawdzie kierunek linii jest wyraźnie opisany i to na trzy sposoby (literowo, opisowo oraz numerycznie, w odniesieniu do standardu ITU-T V.24), ale… istnieje spore ryzyko, że z przyzwyczajenia zwrócimy uwagę tylko na same nazwy TXD/RXD, nie zagłębiając się w dalsze szczegóły dokumentacji.

Fragment dokumentacji modułu u-blox SARA-N3 z liniami interfejsu UART oznaczonymi zgodnie ze standardem ITU-T V.24, czyli… przeciwnie do powszechnie przyjętej konwencji, tj.: TXD – wejście danych modułu, RXD – wyjście danych z modułu; kierunki zostały zatem zapisane z punktu widzenia układu nadrzędnego, np. zewnętrznego mikrokontrolera, a nie samego modułu (źródło: datasheet)

Inny przykład pułapki nazewniczej ma miejsce w przypadku niektórych układów scalonych, w tym nadajników/odbiorników linii RS-485. Tutaj z kolei linia oznaczona literą R to wyjście odbiornika, a nie wejście nadajnika – trzeba ją zatem podłączyć do linii RXD mikrokontrolera.

Rysunek blokowy układów SN65HVD53, SN65HVD54 i SN65HVD55 (źródło: datasheet)

Błędne połączenie linii spowodowałoby potencjalne zwarcie dwóch wyjść na jednej ścieżce (w momencie, w którym próbowałyby wymusić przeciwne stany logiczne) i pozostawienie drugiej ścieżki (wejście-wejście) bez aktywnego źródła sygnału. W przypadku mikrokontrolerów STM32, o ile oczywiście linie należą do tej samej instancji interfejsu USART, błąd można łatwo skorygować przez ustawienie bitu SWAP, co spowoduje następującą zmianę:

  • fizyczny pin USARTx_TX (np. PA9 w przypadku USART1) zacznie odbierać dane z wyjścia układu/modułu zewnętrznego,
  • fizyczny pin USARTx_RX (np. PA10 w przypadku USART1) zacznie nadawać dane do wejścia układu/modułu zewnętrznego.

Implementacja funkcji SWAP w różnych rodzinach STM32

Bit odpowiedzialny za włączenie funkcji zamiany wyprowadzeń danych interfejsu U(S)ART lub LPUART jest elementem struktury rejestru konfiguracyjnego CR2 w zdecydowanej większości nowszych rodzin STM32. Jako przykład podamy tutaj fragment dokumentacji układów z serii STM32C5.

Struktura rejestru CR2 interfejsu UART w mikrokontrolerach STM32 nowszych generacji (źródło: ST)

Trzeba jednak pamiętać, że bitu SWAP – podobnie jak pola bitowego ADD[7:0], funkcji inwersji danych DATAINV oraz wyprowadzeń (TXINV, RXINV) czy ustawienia kolejności bitów (MSBFIRST) – nie znajdziemy w starszej implementacji bloku peryferyjnego U(S)ART, która była stosowana w następujących rodzinach mikrokontrolerów:

  • STM32F1,
  • STM32F2,
  • STM32F4,
  • STM32L1.
Struktura rejestru CR2 interfejsu UART w mikrokontrolerach STM32F1 (źródło: RM0008)

Konfiguracja bitu na 4 sposoby

Inicjalizacja z użyciem CubeMX

Najprostsza metoda konfiguracji to rzecz jasna zaznaczenie odpowiedniego pola w konfiguratorze graficznym CubeMX. Należy przy tym zwrócić uwagę, że w widoku obudowy mikrokontrolera linie pozostaną niezmienione, zatem w dalszym ciągu wyświetlane będą domyślne kierunki danych zdefiniowane w nocie katalogowej, w tabeli funkcji alternatywnych GPIO. Widać to doskonale na poniższym zrzucie ekranu – linia PA10 wciąż jest podpisana jako USART1_RX, pomimo ustawienia funkcji TX and RX Pins Swapping na wartość Enable, zaś PC4 wciąż figuruje jako USART1_TX.

Widok okna programu CubeMX z blokiem USART1 skonfigurowanym w trybie zamiany znaczenia linii TXD i RXD (fot. HardwareDesigner.pl)

Inicjalizacja ręczna z użyciem STM32 HAL1

Jeżeli konfigurację mikrokontrolera wykonujemy ręcznie z użyciem biblioteki STM32 HAL1, musimy pamiętać, by funkcję zamiany linii włączyć przed wywołaniem HAL_UART_Init(). Najpierw zapisujemy wartość makra UART_ADVFEATURE_SWAP_INIT do pola AdvancedInit.AdvFeatureInit struktury konfiguracyjnej, sygnalizując chęć użycia zaawansowanych funkcji konfiguracji UART-u. Dopiero potem do pola AdvancedInit.Swap wpisujemy wartość UART_ADVFEATURE_SWAP_ENABLE , by program mógł docelowo ustawić bit SWAP w rejestrze CR2. Poniżej pokazano przykład funkcji konfigurującej interfejs USART1.

UART_HandleTypeDef huart1;

static void MX_USART1_UART_Init(void)
{
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200;
    huart1.Init.WordLength = UART_WORDLENGTH_8B;
    huart1.Init.StopBits = UART_STOPBITS_1;
    huart1.Init.Parity = UART_PARITY_NONE;
    huart1.Init.Mode = UART_MODE_TX_RX;
    huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart1.Init.OverSampling = UART_OVERSAMPLING_16;

    huart1.AdvancedInit.AdvFeatureInit =
        UART_ADVFEATURE_SWAP_INIT;

    huart1.AdvancedInit.Swap =
        UART_ADVFEATURE_SWAP_ENABLE;

    if (HAL_UART_Init(&huart1) != HAL_OK)
    {
        Error_Handler();
    }
}

Konfiguracja z użyciem biblioteki LL

Według dokumentacji STM32 bit SWAP jest jednym z tych ustawień, które należy wykonywać tylko i wyłącznie przy wyłączonym bloku UART:

This bitfield can only be written when the USART is disabled (UE = 0).

W poniższym kodzie zaznaczono explicite ten fakt poprzez wywołanie funkcji LL_USART_Disable() przed ustawieniem bitu SWAP, a następnie funkcji LL_USART_Enable() dopiero po tej operacji.

LL_USART_Disable(USART1);

LL_USART_SetTXRXSwap(
    USART1,
    LL_USART_TXRX_SWAPPED
);

LL_USART_Enable(USART1);

Bezpośrednia konfiguracja rejestru

Jeżeli pracujemy bezpośrednio na definicjach rejestrów, kod odpowiadający powyższemu przykładowi będzie jeszcze prostszy:

USART1->CR1 &= ~USART_CR1_UE;
USART1->CR2 |= USART_CR2_SWAP;
USART1->CR1 |= USART_CR1_UE;

Podsumowanie

Bit SWAP w rejestrze USART_CR2 pozwala programowo zamienić role fizycznych pinów RX i TX. Funkcja ta, dostępna w większości nowszych rodzin STM32, może pomóc „uratować” projekt PCB, w którym przez przypadek zastosowano błędne połączenie wyjścia z wyjściem i wejścia z wejściem. W niektórych przypadkach można w ten sposób także uprościć layout PCB, jeżeli standardowe przypisanie linii danych UART wymagałoby nieco bardziej złożonego prowadzenia ścieżek. Warto jednak pamiętać, że opisana funkcja nie występuje w starszych seriach STM32, czyli w rodzinach STM32F1, F2, F4 oraz L1.

Mateusz
Mateusz
Redaktor technologiczny portalu HardwareDesigner.pl. Doświadczony konstruktor urządzeń elektronicznych i programista mikrokontrolerów, w szczególności STM32 i ESP32.

Czytaj więcej

Wybrane dla Ciebie