Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

STM32 - Obsługa USART Echo

kornik280 03 Maj 2014 12:35 3849 38
  • #1 03 Maj 2014 12:35
    kornik280
    Poziom 18  

    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: cpp
    Zaloguj się, aby zobaczyć kod



    Oraz przerwanie:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0 29
  • #2 03 Maj 2014 13:31
    el2010tmp
    Poziom 25  

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

    0
  • #3 03 Maj 2014 13:47
    kornik280
    Poziom 18  

    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

    0
  • #4 03 Maj 2014 14:11
    el2010tmp
    Poziom 25  

    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.

    0
  • #5 03 Maj 2014 14:52
    kornik280
    Poziom 18  

    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?

    0
  • #6 03 Maj 2014 17:24
    el2010tmp
    Poziom 25  

    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?

    0
  • #7 03 Maj 2014 18:01
    kornik280
    Poziom 18  

    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ł.

    0
  • #8 03 Maj 2014 19:11
    el2010tmp
    Poziom 25  

    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?

    0
  • #9 03 Maj 2014 19:50
    kornik280
    Poziom 18  

    Moja ramka składa się z 8 bajtów (ciągiem) które wysyłam własnej aplikacji napisanej w C#

    0
  • #10 04 Maj 2014 12:38
    kornik280
    Poziom 18  

    Poprawiłem kod:

    Kod: cpp
    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

    0
  • #11 04 Maj 2014 13:37
    BlueDraco
    Specjalista - Mikrokontrolery

    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.

    0
  • #12 04 Maj 2014 13:56
    kornik280
    Poziom 18  

    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ń?

    0
  • #13 04 Maj 2014 15:05
    Freddie Chopin
    Specjalista - Mikrokontrolery

    kornik280 napisał:
    Jak sprawdzić w przerwaniu że jest koniec transmisji?

    Pewnie użyć przerwania od końca transmisji...

    4\/3!!

    0
  • #14 05 Maj 2014 20:47
    kornik280
    Poziom 18  

    Dobrze dodałem w przerwaniu oczekiwanie na zakończenie transmisji while(!(USART1->SR & USART_FLAG_TC));

    Kod:

    Kod: cpp
    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?

    0
  • #15 05 Maj 2014 20:53
    Freddie Chopin
    Specjalista - Mikrokontrolery

    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!!

    0
  • #16 05 Maj 2014 21:03
    kornik280
    Poziom 18  

    Próbowałem dać w przerwaniu:

    Kod: cpp
    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

    0
  • #17 09 Maj 2014 21:21
    kornik280
    Poziom 18  

    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?

    0
  • #18 09 Maj 2014 21:45
    Tom RealTime
    Poziom 10  

    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.

    0
  • #19 09 Maj 2014 21:59
    kornik280
    Poziom 18  

    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

    0
  • #20 10 Maj 2014 10:08
    Tom RealTime
    Poziom 10  

    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?

    0
  • #21 10 Maj 2014 10:30
    kornik280
    Poziom 18  

    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?

    0
  • #22 10 Maj 2014 12:21
    Tom RealTime
    Poziom 10  

    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
    Zaloguj się, aby zobaczyć kod

    0
  • #23 10 Maj 2014 13:41
    kornik280
    Poziom 18  

    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

    0
  • #24 10 Maj 2014 13:46
    Tom RealTime
    Poziom 10  

    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?

    0
  • #25 10 Maj 2014 14:10
    kornik280
    Poziom 18  

    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.....

    0
  • #26 10 Maj 2014 14:28
    Tom RealTime
    Poziom 10  

    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.

    0
  • #27 10 Maj 2014 19:46
    kornik280
    Poziom 18  

    Teraz mam:

    Kod: cpp
    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?

    0
  • #28 11 Maj 2014 10:47
    Tom RealTime
    Poziom 10  

    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??

    0
  • #29 11 Maj 2014 11:50
    kornik280
    Poziom 18  

    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

    0
  • #30 11 Maj 2014 13:03
    Tom RealTime
    Poziom 10  

    TAK.
    Gotowe rozwiązanie znajdziesz w bibliotekach dostarczonych przez ST
    Link

    0