logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[STM32] [STM32][C] Jak zapewnić pełną transmisję danych przez USART z DMA i RS485?

grzegorzn 07 Lut 2012 02:15 3614 8
  • #1 10507262
    grzegorzn
    Poziom 13  
    Posty: 128
    Pomógł: 3
    Ocena: 5
    Przesyłam sobie dane przez RS485. Na linii są dwa urządzenia i oba mają mieć możliwość nadawania. W związku z tym, gdy jedno skończy nadawać, powinno wyłączyć układ sterujący linią. Niestety jest problem przy transmisji USARTem przez DMA. Przerwanie transfer complete generowane jest wtedy, gdy DMA skończy swoją pracę, natomiast jeszcze nie wszystko zdążyło się faktycznie wysłać. Gdy w tym przerwaniu wyłączam sterownik RS485, urządzenie odbiorcze nie dostaje dwóch ostatnich bajtów. Jeśli testowo usunę wyłączanie układu od RS485 to wszystko działa poprawnie, bajty się nie gubią, oczywiście z wyjątkiem tego, że drugie urządzenie nie może nadawać.
    Zastanawiam się, jak to rozwiązać. Można by w obsłudze przerwania transfer complete dodać krótkie opóźnienie, ale byłoby to trochę nieeleganckie. Można by też sprawdzać flagę USARTa, z tym, że skoro gubione są dwa ostatnie bajty, to sprawdzanie flagi rozwiązuje problem tylko przedostatniego bajtu, a ostatniego już nie. Można by też po prostu wysyłać o dwa bajty więcej, ale to chyba byłoby jeszcze brzydsze niż opóźnienie. Czy ktoś z Forumowiczów ma jakiś lepszy pomysł?
  • Pomocny post
    #3 10507378
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    W przerwaniu od DMA oczekujesz na ustawienie flagi oznaczającej zakończenie transmisji (TC). Jeśli chcesz super elegancko, ale niekoniecznie lepiej, to w momencie rozpoczęcia transmisji DMA włącz przerwanie od tej flagi w module UART - nadajnik będziesz wyłączał dopiero w tym przerwaniu.

    4\/3!!
  • #4 10510297
    grzegorzn
    Poziom 13  
    Posty: 128
    Pomógł: 3
    Ocena: 5
    Bardzo dziękuję za pomoc, skorzystałem ze sprawdzania flagi od DMA i śmiga. Swoją drogą, to nigdy bym nie pomyślał, że flaga ta ustawia się w innym momencie niż generowane jest przerwanie. A tu się okazuje, że TC to nie TC.
  • #6 10512125
    grzegorzn
    Poziom 13  
    Posty: 128
    Pomógł: 3
    Ocena: 5
    Sprawdzałem flagę od DMA a nie od USARTa. Jak pisałem na początku, przy sprawdzaniu flagi od USARTa gubiło mi ostatni bajt. Teraz jednak przy sprawdzaniu flagi USARTa jest OK. Coś musiałem zmienić, ale nie mogę sobie przypomnieć co. W każdym razie teraz działa.
  • #7 10517191
    grzegorzn
    Poziom 13  
    Posty: 128
    Pomógł: 3
    Ocena: 5
    A jednak nie działa poprawnie i problem nie był w moim roztargnieniu. Sytuacja jest taka, że pierwsza transmisja kończy się przedwcześnie, kolejne są w porządku. W pierwszej ucina się trochę ponad jeden bajt na końcu, tzn. przesyła się fragment przedostatniego i potem już nie.

    Wysyłanie:
    void startUSARTDMATransferTx(uint8_t * buffer) {
    DMA1_Channel4->CCR &= ~DMA_CCR1_EN;
    DMA1_Channel4->CMAR = (uint32_t)buffer;
    DMA1_Channel4->CNDTR = BUFFER_SIZE;
    GPIO_SetBits(GPIOA, GPIO_Pin_8);
    DMA1_Channel4->CCR |= DMA_CCR1_EN;
    }

    handler na koniec wysyłania:
    void DMA1_Channel4_IRQHandler(void)
    {
    //while(DMA_GetFlagStatus(DMA1_FLAG_TC4) == RESET){};
    while(!(USART1->SR & USART_FLAG_TC));
    DMA1->IFCR = DMA1_FLAG_TC4;
    GPIO_ResetBits(GPIOA, GPIO_Pin_8);
    }
  • Pomocny post
    #8 10520185
    Krauser
    Poziom 26  
    Posty: 508
    Pomógł: 124
    Ocena: 12
    Spróbuj tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #9 10522228
    grzegorzn
    Poziom 13  
    Posty: 128
    Pomógł: 3
    Ocena: 5
    Pomogło, dzięki!

Podsumowanie tematu

✨ Użytkownik zmagał się z problemem transmisji danych przez RS485 przy użyciu USART i DMA, gdzie ostatnie bajty były gubione podczas nadawania. Po kilku próbach i sugestiach od innych uczestników forum, użytkownik odkrył, że kluczowe jest sprawdzanie flagi TC (Transfer Complete) USARTa, a nie DMA, co rozwiązało problem. Wskazówki obejmowały użycie przerwania od flagi TC w module UART oraz uruchomienie timera po zakończeniu transferu DMA, co pozwala na bardziej eleganckie zarządzanie stanem linii RS485. Ostatecznie, po wprowadzeniu poprawek, transmisja działała poprawnie.
Wygenerowane przez model językowy.
REKLAMA