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

[stm32][rs485] Brak transmisji

polimorf 19 Gru 2011 10:29 8744 16
  • #1 10278510
    polimorf
    Poziom 13  
    Posty: 136
    Pomógł: 3
    Ocena: 1
    Witam.

    Posiadam płytkę własnego projektu, posiadającą interfejs rs485 na us ST485CDR. Pomiędzy usart1 STM'a a st485 są wstawione 3 konwertery napięć 3.3V - 5.0V.
    Dodatkowo do przetestowania komunikacji kupiłem moduł AVTMOD-03 (usb-rs485).

    Problem jest taki że nie mogę nic odebrać z usart1, nadawanie nieraz działa (jak debuguje po kroku lub jeśli debuger jest odłączony).

    Aby sprawdzić usart stm'a i konwertery napięć wylutowałem st485 i w to miejsce podpiąłem moduł z MAX232 (5V) - komunikacja działała obustronnie - czyli konwertery napięć działają.

    W programie mam też 3 ms opóźnienia pomiędzy sterowaniem połączonymi pinami re i de st485 pomiędzy nadawaniem a odbiorem.

    Wie ktoś co może być przyczyną takiego stanu rzeczy?
  • #2 10278963
    Krotki
    Poziom 14  
    Posty: 93
    Pomógł: 6
    Ocena: 1
    Jeśli uważasz że błąd tkwi w elektronice prześlij schemat, jeśli w programie pokaż kod. Gdybając ciężko będzie zgadnąć co jest nie tak :)
  • #3 10279307
    polimorf
    Poziom 13  
    Posty: 136
    Pomógł: 3
    Ocena: 1
    schemat jest następujący - standard:
    [stm32][rs485] Brak transmisji
    te 4 elementy 3 rezystory i kondensator są niezamontowane - jest to polecane przez ST obwód zamiast rezystora 120R (mniej prądożerny).

    kod z maina:
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
      GPIO_Conf.GPIO_Pin = GPIO_Pin_10;
      GPIO_Conf.GPIO_Mode = GPIO_Mode_Out_PP;
      GPIO_Conf.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(GPIOB, &GPIO_Conf);
      GPIO_SetBits(GPIOB, GPIO_Pin_10);
    
    USART_Config_Default();
    
    volatile uint32_t tmp;
    while(1) {
    GPIO_ResetBits(GPIOB, GPIO_Pin_10);
    	  for(tmp=0;tmp<20000;tmp++);
    	  /* Wait the byte is entirely received by USARTy */
    	  while(USART_GetFlagStatus(EVAL_COM1, USART_FLAG_RXNE) == RESET);
    	  volatile uint8_t znak = USART_ReceiveData(EVAL_COM1);
    
    GPIO_SetBits(GPIOB, GPIO_Pin_10);
    	  for(tmp=0;tmp<20000;tmp++);
    	  USART_SendData(EVAL_COM1, znak);
    	  while(USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TXE) == RESET);
    }
    

    pojedyńcza pętla 20000 trwa około 3 ms - sprawdziłem na analizatorze logicznym.

    Funkcje konfigurujące usart:
    void USART_Config_Default(void)
    {
      /* EVAL_COM1 default configuration */
      /* EVAL_COM1 configured as follow:
            - BaudRate = 9600 baud
            - Word Length = 8 Bits
            - One Stop Bit
            - Parity Odd
            - Hardware flow control disabled
            - Receive and transmit enabled
      */
      USART_InitStructure.USART_BaudRate = 19200;//460800;//115200;//19200;//460800;//9600;
      USART_InitStructure.USART_WordLength = USART_WordLength_8b;
      USART_InitStructure.USART_StopBits = USART_StopBits_1;
      USART_InitStructure.USART_Parity = USART_Parity_No;//USART_Parity_Odd;
      USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
      USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    
      /* Configure and enable the USART */
      STM_EVAL_COMInit(COM1, &USART_InitStructure);
    
      /* Enable the USART Receive interrupt */
      //USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    }
    
    void STM_EVAL_COMInit(COM_TypeDef COM, USART_InitTypeDef* USART_InitStruct)
    {
      GPIO_InitTypeDef GPIO_InitStructure;
    
      /* Enable GPIO clock */
      RCC_APB2PeriphClockCmd(COM_TX_PORT_CLK[COM] | COM_RX_PORT_CLK[COM] | RCC_APB2Periph_AFIO, ENABLE);
    
      if (COM == COM1)
      {
        RCC_APB2PeriphClockCmd(COM_USART_CLK[COM], ENABLE);
      }
      else
      {
        /* Enable the USART2 Pins Software Remapping */
        GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
        RCC_APB1PeriphClockCmd(COM_USART_CLK[COM], ENABLE);
      }
    
      /* Configure USART Tx as alternate function push-pull */
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
      GPIO_InitStructure.GPIO_Pin = COM_TX_PIN[COM];
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_Init(COM_TX_PORT[COM], &GPIO_InitStructure);
    
    
      /* Configure USART Rx as input floating */
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
      GPIO_InitStructure.GPIO_Pin = COM_RX_PIN[COM];
      GPIO_Init(COM_RX_PORT[COM], &GPIO_InitStructure);
    
      /* USART configuration */
      USART_Init(COM_USART[COM], USART_InitStruct);
    
      /* Enable USART */
      USART_Cmd(COM_USART[COM], ENABLE);
    }


    Konfiguracja usarta została sprawdzona przy okazji testowania połączenia rs232 - działa.
    Pod analizatorem logicznym wpiętym pomiędzy st485 a translatory napięcia brak jest komunikacji na linii RO - utrzymuje się tam poziom wysoki.
  • #4 10279416
    Krotki
    Poziom 14  
    Posty: 93
    Pomógł: 6
    Ocena: 1
    Na linii rs485 musisz mieć wymuszony stan poprzez rezystory plus terminatory (tu R20 + kondensator) na końcach szyny. Ten pomysł z kondensatorem jest dość fajny, ale nie wiem, czy nie ogranicza on prędkości transmisji.

    Generalnie ja używam 3 rezystorów: R18 i R19 -> 560 Om i R20 -> 120 Om.

    Dodatkowo warto też połączyć masy - specyfikacja rs485 mówi o max. 7v różnicy potencjałów odbiornik/nadajnik.

    Co do programu to się nie wypowiem bo sam zaczynam z stm32 :P
  • #5 10280765
    polimorf
    Poziom 13  
    Posty: 136
    Pomógł: 3
    Ocena: 1
    Możliwe że mam uszkodzony konwerter usb-rs485 - zamówiłem 2.
    Wymieniłem us st485 na nowy i jest ta sama sytuacja - brak komunikacji.
  • #6 10280820
    Krotki
    Poziom 14  
    Posty: 93
    Pomógł: 6
    Ocena: 1
    Masz jakąś instrukcje do tego konwertera ? Wg specyfikacji rs485 A to wyjście odwracające, B to wyjście nieodwracające. Twój konwerter ma na odwrót tak jak większość producentów tego typu sprzętu. Popróbuj po przełączać przewody np A z B :)

    Oczywiście zakładając że podłączyłeś rezystory :D
  • #7 10282474
    polimorf
    Poziom 13  
    Posty: 136
    Pomógł: 3
    Ocena: 1
    Podłączyłem rezystory, przekładałem przewody, dodałem wspólną masę, wymieniłem max485 z modułu avt na ST485 i też nic. Nie działa.

    Poczekam aż przyjdzie mi nowy moduł usb-rs485 - to wtedy przetestuje czy ten działa.

    Dzięki za pomoc.
  • #8 10282742
    Krotki
    Poziom 14  
    Posty: 93
    Pomógł: 6
    Ocena: 1
    Jeśli posiadasz oscyloskop to mogę polecić debugowanie rs485 w obrazkach: Link

    Powodzenia !
  • #9 10282859
    polimorf
    Poziom 13  
    Posty: 136
    Pomógł: 3
    Ocena: 1
    Dzięki - ciekawy dokument, może skorzystam.

    Teraz nawet nie mogę odebrać nic z urządzenia, czasami zaczyna mrugać dioda od odbierania - rzadko (ale na terminalu nadal pusto).
    Poczekam na przejściówkę.
  • #10 10323629
    polimorf
    Poziom 13  
    Posty: 136
    Pomógł: 3
    Ocena: 1
    Mam już nową przejściówkę.

    Teraj po podłączeniu przewodów tak jak wcześniej (przejściówka jest inna niż wcześniej) odbieram dane za każdym razem.
    Niestety przy wysyłaniu działa to tylko gdy debuguję i przechodzę krokowo przez USART_SendData (dlatego zakładam że elektronika jest w porządku). Przy normalnej pacy lub debugowaniu bez zatrzymywania nic nie przychodzi na terminal - nie pomaga nawet wstawianie przed wysyłaniem sekundowej przerwy.

    Jakieś pomysły?

    [edit]
    Poprawka tylko pojedyńcze wysyłanie danych 1 bajtowych nie powoduje zmian na terminalu.
    W trybie burst :) gdy wysyłam dane wpętli przychodzi dużo danych jednak nie wiem czy wszystkie.

    [edit]
    jak wysyłam dane w szeregu 10 bajtów to odbieram od 5 do 9 bajtów. A Jak wysyłam dane pojedyńcze to muszę wysłać 2 bajty aby 1 doszedł i to nieraz nie pomaga.
    Przelutowanie elementów i wypróbowanie innych kombinacji nic nie dało - utrzymywał się tan sam błąd.
    Sprawdzałem 3 kombinacje:
    1. bez rezystora 120R pomiędzy przewodami A i B.
    2. z rezystorem i kondensatorem pomiędzy A i B - tak jak na schemacie.
    3. z rezystorem 120R pomiędzy A i B.
  • #11 10324130
    Krotki
    Poziom 14  
    Posty: 93
    Pomógł: 6
    Ocena: 1
    Zakomentuj obie linijki opóźnienia:
    for(tmp=0;tmp<20000;tmp++);

    I wtedy zobacz co się stanie :D
  • #12 10324182
    polimorf
    Poziom 13  
    Posty: 136
    Pomógł: 3
    Ocena: 1
    Niestety to samo po wprowadzeniu poprawki.
    Jak wysyłam po 2 takie same bajty to prawie zawsze przychodzi jeden (przy prędkości 1200).

    [Edit]
    Co dziwne przy prędkości 115200 jest to samo - tyle że co któryś znak pojawia się dodatkowy krzak.
  • #13 10324715
    Krotki
    Poziom 14  
    Posty: 93
    Pomógł: 6
    Ocena: 1
    Winą są zależności czasowe ... powinieneś zbudować bufor najlepiej rotacyjny gdzie w przerwaniu dodajesz znak przychodzący, a wysyłając pobierasz z początku. Dodatkowo musisz pamiętać że masz tryb half-duplex (wspólną szynę), czyli jak rozpoczynasz transmisje wielu znaków do mikrokontrolera musisz go poinformować kiedy on ma odpowiedzieć (np znak końca transmisji, stały rozmiar komend, zwalnianie linii na określony czas pomiędzy znakami) - kwestia odpowiedniego protokołu.

    Teraz masz tak że obierasz znak i od razu próbujesz go wysłać pomimo ze linia jest zajęta poprzez transmisje z komputera. Żeby odpowiedział mikrokontroler musisz mu dać na to czas pomiędzy znakami lub buforować i odsyłać z opóźnieniem.

    Nieco chaotyczna wypowiedź ale mam nadzieje ze coś udało mi się wytłumaczyć :)
  • #14 10324926
    polimorf
    Poziom 13  
    Posty: 136
    Pomógł: 3
    Ocena: 1
    Krotki napisał:
    Winą są zależności czasowe ... powinieneś zbudować bufor najlepiej rotacyjny gdzie w przerwaniu dodajesz znak przychodzący, a wysyłając pobierasz z początku.

    Wysyłam po kilka razy ten sam znak który otrzymałem z mastera.

    Krotki napisał:
    Dodatkowo musisz pamiętać że masz tryb half-duplex (wspólną szynę), czyli jak rozpoczynasz transmisje wielu znaków do mikrokontrolera musisz go poinformować kiedy on ma odpowiedzieć (np znak końca transmisji, stały rozmiar komend, zwalnianie linii na określony czas pomiędzy znakami) - kwestia odpowiedniego protokołu.

    Teraz po każdym odebranym znaku z mastera slave wysyła po 2 znaki

    Cytat:

    Teraz masz tak że obierasz znak i od razu próbujesz go wysłać pomimo ze linia jest zajęta poprzez transmisje z komputera. Żeby odpowiedział mikrokontroler musisz mu dać na to czas pomiędzy znakami lub buforować i odsyłać z opóźnieniem.

    Dawałem mu nawet 10s przerwę - jest to samo.

    Patrzyłem przebiegi na oscyloskopie i wszystko wygląda dobrze - porównując z tym dokumentem którego link mi podałeś.
  • Pomocny post
    #15 10325112
    Krotki
    Poziom 14  
    Posty: 93
    Pomógł: 6
    Ocena: 1
    To ja się już pogubiłem.

    Czyli jak z termminala PC naciskasz 1 znak przychodzą Ci 2 takie same na terminal ?

    Nie masz zaznaczonej opcji automatycznego echo ?
  • #16 10325195
    polimorf
    Poziom 13  
    Posty: 136
    Pomógł: 3
    Ocena: 1
    Cytat:
    Czyli jak z termminala PC naciskasz 1 znak przychodzą Ci 2 takie same na terminal ?

    Właśnie przychodzi mi na terminal tylko jeden znak - chociaż wysyłam 2 - tylko tak to działa.
    Jak z procka wyślę 1 znak - to na terminal nie przychodzi mi żaden.

    Nie mam włączonego automatycznego echo.

    [Edit]
    [stm32][rs485] Brak transmisji
    kanał 0 i 1 to RS485
    kanał 2 to tx uartu

    Dobra wszystko jasne - dopiero dzisiaj się temu przyjrzałem.
    Dzięki za pomoc.
  • #17 10327391
    HumunD
    Poziom 11  
    Posty: 19
    Ocena: 1
    Proponuje zapoznać się z dokumentacją ST jak poprawnie wykonać obsługę RS485 dla stm32 W proponowanym rozwiązaniu ST wykorzystuje flagę TC transmit complete. Czyli po prawidłowym wysłaniu bajtu wywoływane jest przerwanie, po ostatnim bajcie przełączasz RS485 w tryb odbioru, bez obliczania późnień itp. :D

Podsumowanie tematu

✨ Użytkownik ma problem z komunikacją RS485 na własnej płytce z interfejsem ST485CDR. Po podłączeniu konwertera USB-RS485 AVTMOD-03, nie może odebrać danych z USART1, mimo że nadawanie czasami działa. Po wymianie ST485 na nowy i przetestowaniu z MAX232, komunikacja działała. Użytkownik dodał rezystory terminacyjne, ale problem nadal występuje. Wskazówki dotyczące poprawy obejmują użycie bufora, odpowiedniego protokołu komunikacji oraz sprawdzenie ustawień konwertera. Po wymianie przejściówki na nową, użytkownik zaczął odbierać dane, ale nadal występują problemy z wysyłaniem. Sugerowane jest zapoznanie się z dokumentacją ST w celu poprawnej obsługi RS485.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA