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

STM32F103RB RS485 - Problem z przesunięciem danych i brakiem echa USART

kornik280 03 Maj 2014 12:35 4860 38
Najlepsze odpowiedzi

Jak poprawnie zrobić echo RS485 na STM32F103RB, aby nie gubić bajtów i nie przesuwać ramek przy przełączaniu nadawania/odbioru?

Problem z przesunięciem bajtów i brakiem echa wynika głównie z tego, że w czasie nadawania wyłączasz odbiornik i przełączasz RS485 zanim transmisja faktycznie się zakończy; trzeba czekać na flagę TC (Transmission Complete), a nie tylko na opróżnienie nadajnika, i dopiero wtedy wrócić na odbiór [#13565141] [#13568992] [#13587063] [#13587491] Nie obsługuj całej komunikacji w samym przerwaniu ani nie blokuj go pętlą oczekującą na TC — przerwanie powinno tylko sygnalizować zdarzenie, a dane lepiej trzymać w buforach cyklicznych Rx/Tx i parsować je w pętli głównej [#13587063] [#13590551] Przy RS485 half-duplex nie wyłączaj samego odbiornika na czas wysyłki, bo wtedy przychodzące znaki są tracone; zamiast tego steruj linią DE/RE i przełączaj tryb po zakończeniu nadawania [#13565141] [#13587491] Jeśli używasz DMA do nadawania na STM32F103, USART1 TX jest przypisany do DMA1 Channel 4, więc konfigurację trzeba ustawić zgodnie z RM0008 [#13595646]
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA
  • #1 13564906
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Chciałbym zralizować transmisje RS485 na stm32f103rb, gdyż mam pod ręką konwerter usb-rs485 oraz max3485.
    Moja ramka składa się z 8 bajtów.Jeśli chodzi o odbieranie to do mojego bufora dane wpadają poprawne czyli prawdopodobnie wszystkie ustawienia fizyczne mam poprawne.
    Niestety po kilku wysłaniach danych z PC z rzędu do arm pojawia się przekłamanie gdyż ostatni bajt wysyłany z PC trafia nie do RxBuf[7] tylko jako pierwszy czyli RxBuf[0] i cała reszte przesuwa się o jeden.

    Drugi problem mam taki ,że arm mi nic nie odsyła gdyż chcę zaraz po odbiorze danych odesłać TxBuf do PC, czyli takie echo.
    Czy możecie mi coś poradzić?
    Kod: text
    Zaloguj się, aby zobaczyć kod



    Oraz przerwanie:
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 13565141
    el2010tmp
    Poziom 25  
    Posty: 713
    Pomógł: 97
    Ocena: 43
    kornik280 napisał:
    volatile uint8_t RxBuf[7];
    volatile uint8_t TxBuf[7];

    Zgodnie z deklaracją te tablice mają po siedem bajtów.

    kornik280 napisał:
    TxBuf[0]=1;
    TxBuf[1]=2;
    TxBuf[2]=3;
    TxBuf[3]=4;
    TxBuf[4]=5;
    TxBuf[5]=6;
    TxBuf[6]=7;
    TxBuf[6]=8;

    Dwie ostatnie linie są "ciekawe".
    A można tak:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    kornik280 napisał:
    USART1->CR1&=~(1<<2);// Odbiornik wylaczony

    W czasie gdy odbiornik jest wyłączony, dane przychodzące nie będą odbierane. :D
  • #3 13565197
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Dzięki , to z tablicami to moja pomyłka pisałem to na szybko.Jak miałem tablice 10 elementowe to było to samo.Co do wartości w TxBuf to nie mają one żadnego znaczenia gdyż chce poprostu wysłać cokolwiek.

    Co się tyczy USART1->CR1&=~(1<<2); to tak ma działać, czyli:
    1. Odbieram dane,
    2.Blokuje odbiór,
    3.Aktywuje wysyłanie,
    4.Wysyłam
    5.Wyłączam wysyłanie
    6.Aktywuje odbiór
  • #4 13565329
    el2010tmp
    Poziom 25  
    Posty: 713
    Pomógł: 97
    Ocena: 43
    Możesz podać logiczne uzasadnienie blokowania odbiornika/nadajnika poza potencjalną możliwością gubienia danych?
    kornik280 napisał:
    Niestety po kilku wysłaniach danych z PC z rzędu do arm pojawia się przekłamanie gdyż ostatni bajt wysyłany z PC trafia nie do RxBuf[7] tylko jako pierwszy czyli RxBuf[0] i cała reszte przesuwa się o jeden.
  • #5 13565515
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Dostaje ramkę analizuje ją i odpowiadam na nią dopiero potem oczekuję następnej ramki

    Chyba, że jestem w błędzie i to robi się inaczej?
  • #6 13566067
    el2010tmp
    Poziom 25  
    Posty: 713
    Pomógł: 97
    Ocena: 43
    kornik280 napisał:
    Dostaje ramkę analizuje ją i odpowiadam na nią dopiero potem oczekuję następnej ramki

    Chyba, że jestem w błędzie i to robi się inaczej?


    Dostajesz dane wtedy kiedy nadchodzą a czy ich wówczas oczekujesz czy nie to już inna sprawa.

    Jak wygląda ramka którą posyłasz z PC?
  • #7 13566187
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Ramka to jest po prostu 8 bajtów na razie, później może jakiś modbus.

    Na początku chce przechwycić 8 bajtów i potem 8 bajtów odesłać,później będę to rozwijał.
  • #8 13566489
    el2010tmp
    Poziom 25  
    Posty: 713
    Pomógł: 97
    Ocena: 43
    kornik280 napisał:
    Ramka to jest po prostu 8 bajtów

    Czyli jak? Osiem bajtów pojedynczo, naraz a może osiem znaków z automatycznie dodanym kodem CR lub CR LF ? Czym to wysyłasz?
  • REKLAMA
  • #9 13566629
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Moja ramka składa się z 8 bajtów (ciągiem) które wysyłam własnej aplikacji napisanej w C#
  • #10 13568455
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Poprawiłem kod:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Teraz nie mam już żadnych problemów z odbieraniem,po odebraniu arm odsyła mi z powrotem ramke, tylko niestety 4 bajty a nie 8 i nie wiem dlaczego
  • #11 13568681
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    1. Najpierw włączasz transmisję UART, a potem programujesz jej parametry - to niezbyt sensowne.

    2. (Nieaktualne, racja, to jest na przerwaniach.)

    3. Jeśli będziesz używał nazw symbolicznych bitów w rejestrach, być może ktoś sprawdzi, czy dobrze ustawiłeś te bity i znajdzie jakiś błąd.

    4. Nie używaj operatorów |= i &= przy początkowym programowaniu peryferiali - to tylko zaciemnia kod. Co innego przy zmianie trybu pracy czy przełączaniu nadawanie/odbiór - tam od biedy może zostać, choć wcale nie musi.

    5. Wyłączasz nadajnik przed zakończeniem transmisji - musisz poczekać na koniec transmisji, a nie na opróżnienie bufora nadawanych danych.
  • REKLAMA
  • #12 13568744
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Dziękuje za uwagi.

    Szczególnie interesująca jest dla mnie uwaga nr. 5 gdyż to może być powód mojego problemu. Jak sprawdzić w przerwaniu że jest koniec transmisji?

    Ad 2 Przecież używam przerwań?
  • #14 13573137
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Dobrze dodałem w przerwaniu oczekiwanie na zakończenie transmisji while(!(USART1->SR & USART_FLAG_TC));

    Kod:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Teraz odsyłam z arm to co do niego wysłałem.

    Teraz sytuacja wygląda tak że dalej nie mam problemów z odbiorem, pojawiła się także odpowiedź ze wszystkimi bajtami- za pierwszym razem gdy coś pośle.
    Za kolejnymi razami gdy coś zmienie w ramce i wysyłam do arm to ta zmiana nie pojawia się w odpowiedzi.
    Dopiero jak kilka razy szybko wyśle tą samą ramkę, to arm odpowiada tą samą ramką (już ze zmianą). Co robię jeszcze nie tak?
  • #15 13573176
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    kornik280 napisał:
    Dobrze dodałem w przerwaniu oczekiwanie na zakończenie transmisji while(!(USART1->SR & USART_FLAG_TC));

    Czyli wybrałeś najgorszą możliwą opcję...

    4\/3!!
  • #16 13573220
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Próbowałem dać w przerwaniu:

    Kod: text
    Zaloguj się, aby zobaczyć kod



    A w konfiguracji USART USART1->CR1|=(1<<6); czyli odblokowanie przerwania od zakonczenia transmisji, ale wtedy wysyłanie wogóle przestało działać leciały jakieś śmieci
  • #17 13585856
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Niestety ciągle sobie nie poradziłem z tym, czy przy wysyłaniu gdy chce wysłać 8 bajtów to mój warunek musi być j>7 czy musze tu uwzględniać bit stopu?
  • #18 13585948
    Tom RealTime
    Poziom 11  
    Posty: 23
    Pomógł: 2
    Ocena: 1
    Kiedy Ci zgłasza przerwanie o nadanym bajcie?
    Wtedy gdy ostatni bajt jest w buforze nadajnika, czy gdy wyjechał z bufora?
    Dokładnie to sprawdź, nim przełączysz się na odbiór.

    Zwróć uwagę na konfigurację. W PC-tach kostki 16550 "ignorują" bity stopu i parity, w procesorach arm, jak liczba bitów stop i parity się nie zgadza, to kicha.
    Jakie kostki transmiterów i receiverów dla 485, jaka długa linia, jaka prędkość transmisji i czy są podpięte terminacje. Ważne szczególnie przy prędkościach powyżej 9600 bd nawet na odcinakach 50 cm.
  • REKLAMA
  • #19 13585987
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Ustawienia 9600 8N1 długość kabla raczej nie ma znaczenia bo wszystko się dzieje u mnie na biurku ponadto nie mam problemów z odbiorem danych które posyłam do ARM.
    Podglądnąłem transmisje w programie serial monitor i problem polega na tym że ARM wysyła mi różne długości ramki czasem casem 8 tyle ile trzeba czasem 1,3 bajty
    Najczęściej odsyła 8 bajtów lub tylko jeden, kolejność bajtów sie zgadza tylko długość ramki
  • #20 13586736
    Tom RealTime
    Poziom 11  
    Posty: 23
    Pomógł: 2
    Ocena: 1
    1. Od czego jest przerwanie uart'a:
    a) transmiter data register empty
    b) transmision complete

    Powinno być od transmision complete wówczas przełączasz się na odbiór.
    Może gdybyś napisał przykład jak wyglądają bajty wysyłane i odebrane po stronie dte i dce
    DEVICE 1 ------> DEVICE 2
    TX RX RX TX
    0x01
    0x01 0x01
    0x05
    0x05 0x05
    0x0A
    0x0A 0x0A
    Przełączenie DE -> DEVICE 2 nadaje echo
    0x01
    0x01
    .....

    Dodano po 4 [minuty]:

    Jeszcze jedno.
    Jak masz ustawione FIFO?
    Czy to jest transmisja asynchroniczna, czy synchroniczna?
  • #21 13586791
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Wysyłam cały czas ramkę składającą sie z bajtów: 1,2,3,4,5,6,7,8
    Na każde posłanie tej ramki dostaję odpowiedź z ARM kolejno:
    01 02 03 04 06 05 07 08

    01 02 03 04 06 05 07 08

    01 02

    01 02 03 04 06 05 07 08

    01

    01

    01 02 03 .

    01 02 03 04 06 05 07 08

    Czyli co jakiś czas dostaję ramkę za krótką .

    Ad1. RS485 jest asynchroniczny
    Ad2. Do czego jest to FIFO gdzie to się ustawia?
  • #22 13587063
    Tom RealTime
    Poziom 11  
    Posty: 23
    Pomógł: 2
    Ocena: 1
    sprawdziłem w dokumentacji. FIFO ustawiane jest w trybie z DMA, którego nie używasz. Więc ten aspekt odpada.
    Dla uporządkowania tematu.
    PC-t wysyła do stm32f1.. ramkę z 8 bajtów z 1 bitem stopu bez parzystości.
    8 bajtów wyjechało i masz je w buforze odbiorczym pc-ta jako echo.
    1. czy arm widzi tylko wybrane bajty ?
    2. czy arm widzi wszystko?
    3. czy odsyła wszystko (8 bytes) i echo w arm potwierdza liczbę i treść nadanych bajtów, jednak PC-t dostaje poszarpaną ramkę?

    Moim zdaniem (nie chcę się tu wpajać swoich teorii), ale pierwszy i najpoważniejszy błąd to błąd metodologiczny. Przerwania służyły i służą tylko i wyłącznie do sygnalizacji zaistniałego zdarzenia a nie obsługi zdarzenia. Obsługa zdarzeń powinna być w osobnym wątku programu.
    Manipulujesz na rejestrze przerwaniowym w przerwaniu, to też nie jest zdrowe podejście i ryzykowne. Aby dokonywać takich manipulacji musisz dobrze poznać architekturę procesora. Procesory STM32 mają tez błedy więc łatwo dostać rykoszetem.
    Przy procesorze typu STM32f103 powinien być zaprzegnięty do tego typu zadania DMA. Sygnalizujesz na przerwaniu tylko koniec transmisji (nadanie ostatniego bajtu, a nie pusty nadajnik, to jest ważne). Dopiero przełączasz się w tryb odbioru. Odbiór też dajesz na przerwanie od odbioru liczby bajtów, lub polingiem sprawdzasz deskryptory.
    STM udostępnił przykłady.
    Pozostając przy obsłudze w przerwaniu powinno wyglądać to tak ALE NIE TESTOWAŁEM:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #23 13587311
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Nie rozumie dlaczego arm mi wysyła czasami tylko 1,2,3 bajty zamiast 8.
    Przecież, przejście w ponowny odbiór jest aktywowane po wysłaniu 8 bajtów, a z odbiorem nie mam żadnych problemów
  • #24 13587330
    Tom RealTime
    Poziom 11  
    Posty: 23
    Pomógł: 2
    Ocena: 1
    Na 100% jest błąd w programie.
    Na jakiej podstawie twierdzisz że wysyła 1, 2, 3 a nie 8 bytes?
    Czy potwierdziłeś to na oscyloskopie?
    Czy twierdzisz na podstawie odebranych bajtów w PC-cie (odbiorniku)?
    Czy twierdzisz na podstawie odebranych bajtów w STM32 (odbiorniku)?
    Może coś nadpisujesz?
  • #25 13587433
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Mam program do analizowania portu szeregowego i widzę co jest wysłane z PC a co przychodzi z ARM.
    Z odbiorem w arm nie mam żadnego problemu gdyż podglądam bufor RxBuf gdy w Keil w debug daje run, każda ramka wysyłana do Arm z PC trafia do RxBuf.

    Problem jest z wysyłaniem, zastanawia mnie to że ARM jest zdolny do ponownego odbioru gdy wyśle 8 bajtów(aktywuje przerwanie od odbierania), czyli gdyby wysłał np 3bajty to nie mógłby ponownie odbierać, a właśnie odbiera kolejne ramki.....
  • #26 13587491
    Tom RealTime
    Poziom 11  
    Posty: 23
    Pomógł: 2
    Ocena: 1
    Odpowiedź jest oczywista. Deaktywujesz (blokujesz) wektor przerwań (to co pisałem wcześniej). Nie deaktywujesz odbiornika. Tu jest Twój błąd. Odbiornik cały czas odbiera znaki. Gdy odblokujesz przerwanie wówczas zgłosi Ci przerwanie od odebranego lub odebranych znaków.
    Nie bardzo wiem, dlaczego tak postępujesz. Jeżeli masz magistralę dwó-przewodową (rs-485 half-duplex), to to co wysyłasz odbierasz i po odbiorze swojego echa, przestawiasz nadajnik na odbiór. Nie rób w przerwaniu operacji na wektorze przerwań. Napisałem Ci przykład. Możesz spróbować tak uruchomić. ów przykład wycina echo.
  • #27 13588361
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Teraz mam:

    Kod: text
    Zaloguj się, aby zobaczyć kod



    Jest już lepiej w 90% przypadków dostaje to co trzeba ,ale czasami ARM wysyła tylko jeden bajt czasami o wartości jeden czyli prawidłowy a czasami 0xff czyli śmieć.Co mogę w tym kodzie poprawić?

    Pojawia się też czasami ramka FF 01 02 03 04 06 05 07 08
    9 bajtów?
  • #28 13589635
    Tom RealTime
    Poziom 11  
    Posty: 23
    Pomógł: 2
    Ocena: 1
    Zastosuj rozwiązanie które wcześniej podesłałem i nie manipuluj nic na odbiorniki i nadajniku a tym bardziej na przerwaniu.
    Teraz wyłączyłeś tylko aktywację odbiornika, a nie odbiornik.
    Dlaczego manipulujesz odbiornikiem i nadajnikiem (zamykanie, otwieranie), jaki to ma sens??
  • #29 13589842
    kornik280
    Poziom 18  
    Posty: 466
    Pomógł: 36
    Ocena: 14
    Jeśli chodzi o nadawanie czy szłoby to zrobić przez DMA bez przerwania TXE i TC (USART).Tzn. uruchamiam DMA i wszystko jest wysłane?
    Bo i tak musze jakoś parsować moją ramkę, a to i tak bedzie sie działo w pętli głównej, czyli takie echo i tak z praktycznego punktu widzenia się nie nadaje
  • #30 13590102
    Tom RealTime
    Poziom 11  
    Posty: 23
    Pomógł: 2
    Ocena: 1
    TAK.
    Gotowe rozwiązanie znajdziesz w bibliotekach dostarczonych przez ST
    Link

Podsumowanie tematu

✨ Użytkownik zmaga się z problemami podczas realizacji transmisji RS485 na mikrokontrolerze STM32F103RB. Główne trudności to przesunięcie danych w buforze odbiorczym oraz brak echa po wysłaniu danych z ARM do PC. Użytkownik zauważa, że ostatni bajt wysyłany z PC trafia do RxBuf[0] zamiast RxBuf[7], co powoduje przesunięcie danych. Dodatkowo, ARM nie odsyła danych do PC po ich odebraniu. W dyskusji poruszane są różne aspekty konfiguracji USART, w tym blokowanie odbioru i nadawania, a także wykorzystanie przerwań. Użytkownicy sugerują poprawki w kodzie, takie jak oczekiwanie na zakończenie transmisji przed przełączeniem na odbiór oraz rozważenie użycia DMA do przesyłania danych. Problemy z długością ramki i nieprawidłowym odsyłaniem danych są również analizowane, a użytkownik jest zachęcany do dokładnego sprawdzenia konfiguracji oraz logiki w kodzie.
Podsumowanie wygenerowane przez AI na podstawie treści dyskusji.
REKLAMA