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.

[ATmega32][C/LabView] - Obsługa dwukierunkowa RS232

oObi89 14 Sie 2012 11:23 7236 53
  • #1 14 Sie 2012 11:23
    oObi89
    Poziom 9  

    Witam,
    Mam problem, z którym od dłuższej chwili nie mogę sobie poradzić..
    Zrobilem program do transmisji po RS 232 dwukierunkowo. Generalnie działa, ale problem pojawia się kiedy w każdej pętli chce wysyłać stringa składającego się z kilku bajtów.
    Po stronie atmegi napisałem program, w którym część obsługi RSa znajduje się w przerwaniu, co 10ms dana z LabView jest zapisywana w tablicy na atmedze po czym jest odsyłana do komputera, taki schemat działania sprawdza się do momentu kiedy z komputera wysyłane są od 1 do 4 bajtów danych, w przypadku 5 bajtów do komputera wracają bity 1szy, 2gi, 3ci, oraz 5ty (4ty tak jakby był pomijany), trochę już nad tym siedziałem, może ktoś ze świeżym spojrzeniem coś zauważy, no chyba, że podchodzę do tego zupełnie źle..

    Kod: C
    Zaloguj się, aby zobaczyć kod
    [ATmega32][C/LabView] - Obsługa dwukierunkowa RS232


    byłbym bardzo wdzięczny za jakąkolwiek pomoc.
    Pozdrawiam
    Poprawiłem temat na zgodny z regulaminem p. 3.1.15.
    Proszę na przyszłość używać tagu [syntax=C] do wklejania kodu...[/syntax].
    Poprawiłem, LordBlick

    0 29
  • Pomocny post
    #2 14 Sie 2012 12:42
    tmf
    Moderator Mikrokontrolery Projektowanie

    Od strony AVR napisz to od nowa. Napisz asynchroniczną obsługę wysyłania danych po RS, bo tak jak masz być nie może - blokujesz przerwania na długi czas potrzebny na wysłanie danych przez wolny interfejs szeregowy. Kolejna rzecz - jak ten program działa? Na losową pozycję bufora zapisuje odebrany bajt z PC (w dodatku blokując cały MCU do czasu jego odebrania!), po czym od właściwie losowej pozycji jest transmitowany bufor?

    0
  • #3 14 Sie 2012 13:01
    stanleysts
    Poziom 27  

    bufor cykliczny się tu prosi...

    0
  • #4 14 Sie 2012 13:22
    oObi89
    Poziom 9  

    -nie rozumiem co masz na myśli przez "Napisz asynchroniczną obsługę wysyłania danych po RS"?
    -blokowanie przerwania następuje tylko w momencie kiedy pętla while czeka na zwolnienie bufora, czy się myle?
    -Co do działania programu to nie do końca jest tak.. To co wyśle z PC jest zapisywane jako kolejne elementy tablicy (czyli dokładnie tak jak potrzebuje, gdyz konkretne dane będa mi potrzebne w dalszej części programu), kiedy testowałem wysyłanie z atmegi pojedyńczych komórek to wszystko znajdowało się dokładnie tam gdzie powinno.. w sensie, że do danej komórki w kolejnych przebiegach pętli były zapisywane dokładnie te same dane.
    -co do bufora cyklinego to jego zasada działania z tego co czytałem polega na tym, że dane zmieniają swoją pozycje, w związku z tym nie będę mógł później wykorzystać w programie konkretnej, akurat mi potrzebnej danej, chyba że tym razem również nie mam racji??

    0
  • Pomocny post
    #5 14 Sie 2012 13:27
    stanleysts
    Poziom 27  

    Cytat:
    -blokowanie przerwania następuje tylko w momencie kiedy pętla while czeka na zwolnienie bufora, czy się myle?


    Przerwań nie blokuje się w żaden sposób, żadnym while-m.

    Cytat:
    co do bufora cyklinego to jego zasada działania z tego co czytałem polega na tym, że dane zmieniają swoją pozycje, w związku z tym nie będę mógł później wykorzystać w programie konkretnej, akurat mi potrzebnej danej, chyba że tym razem również nie mam racji??


    Nie, chodzi o to abyś w przerwaniu tylko odczytywał do bufora cyklicznego dane a potem sobie w petli glownej cos z tymi danymi robil. Bufor cykliczny jest po to, że zajmuje mały obszar pamięci a nie zapisuje ciągle następnych komórek pamięci w nieskończoność. Należy uważać żeby dane były pobierane z bufora szybciej niż są do niego wrzucane.

    0
  • Pomocny post
    #6 14 Sie 2012 13:59
    LordBlick
    VIP Zasłużony dla elektroda

    Po co kombinujesz z tym while ? Skoro korzystasz z mechanizmu przerwań, to użyj kolejnego :

    Kod: C
    Zaloguj się, aby zobaczyć kod
    Sam mikrokontroler sprawdzi tą flagę sobie sam bez dodatkowego narzutu i wywoła tą procedurę w odpowiednim czasie...

    0
  • #7 15 Sie 2012 16:17
    oObi89
    Poziom 9  

    wstawiłem odbiór i wysyłanie do przerwania od RXC i faktycznie teraz działa to dużo lepiej, mam jednak pytanie jak to będzie wyglądało w przypadku kiedy przerwanie z timera też będzie aktywne ? chodzi mi o to, że w przerwaniu od timera będzie jeszcze odczyt ADC co 1, 10 lub 100ms i czy przerwanie od usarta RXC jakoś na to nie wpłynie? czy któryś odczyt nie zostanie pominięty w przypadku kiedy np. akurat bedą wysyłane lub odbierane dane w przerwaniu USARTa??

    poniżej kod mojego przerwania od RXC:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    dodatkowo mam jeszcze jedno pytanie:
    potrzebuje zadawać z poziomu labview liczby które będą miały część po przecinku. Chciałbym to zrealizować w taki sposób, że liczbę w Labview będę mnożył przez 10 lub 100 tak aby przesunąć przecinek i aby poswstała liczba całkowita, następnie podziele ją na 2 lub 4 bajty, prześle do mikrokontrolera, połącze wszystkie bajty i znowu przesune przecinek aby uzyskać liczbe po przecinku.. Czy takie rozwiązanie będzie działać? czy można to zrealizować w lepszy sposób??

    0
  • Pomocny post
    #8 15 Sie 2012 16:23
    stanleysts
    Poziom 27  

    Cytat:
    Czy takie rozwiązanie będzie działać? czy można to zrealizować w lepszy sposób??
    Będzie dobre, wiele rzeczy się tak robi, żeby uniknąć działania na float'ach.

    Kod: c
    Zaloguj się, aby zobaczyć kod
    Co to robi w przerwaniu? Przecież jak Ci się już wywołało przerwanie to nic nie trzeba sprawdzać.

    Co robi ta linijka?
    Kod: c
    Zaloguj się, aby zobaczyć kod
    Wysyłanie lepiej zrobić gdzie indziej.

    Ogólnie to powinno iść tak:

    Masz bufor kołowy do którego zapisujesz dane, wiesz więc (jakies znaczniki head/tail) czy jest cos wogole w buforze), teraz za pomoca zwyklego odpytywania sprawdzasz czy masz cos do wyslania i jak masz to wysylasz:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #9 15 Sie 2012 16:29
    oObi89
    Poziom 9  

    faktycznie nie pomyślałem, że skoro to jest przerwanie od RXC to już ten while nie potrzebny,

    a co do wysyłania to tutaj sprawdzałem po prostu czy wszystko się dobrze pozapisywało, w dalszej częsci przerzuce to gdzie indziej.

    dzięki za pomoc, w takim razie próbuje dalej :)




    edit. bym zapomniał, co do tego przerwania od timera, to na pewno nie będzie się to gryzło z niczym od usartu, zaden pomiar adc nie zostanie pominięty?

    0
  • #10 15 Sie 2012 19:48
    tmf
    Moderator Mikrokontrolery Projektowanie

    Nie będzie się gryzło, dopóki obsługa przerwań będzie trwała krótko. Oczywiście inne przerwanie i czas jego obsługi wprowadzi pewien jitter do obsługi dugiego przerwania, w efekcie pomiary ADC nie będą co ściśle określony czas w każdym przypadku, a jedynie statystycznie. Jeśli to przeszkadza można zastosować nieblokującą obsługę przerwań (ISR_NOBLOCK), wtedy jitter nie będzie większy niż kilka taktów CPU. Oczywiście obsługa przerwań w takim przypadku musi być krótka, tak, aby nie dochodziło do ich kumulacji co grozi przepełnieniem stosu.

    0
  • #12 15 Sie 2012 20:57
    ppawel12
    Poziom 16  

    Hej,

    Po stronie LV działa wszystko czy też masz problemy ? Od AVR koledzy pomagają już.

    wWidzę, że dałeś w LV do pętli while a w niej strukturę sekwencyjną wraz z "próbą" synchronizacji. Działasz na komunikacji synchronicznej ?
    Komunikacja z LV może sobie wisieć w powietrzu, dopiero jak coś wpiszesz do bloczka VISA WRITE to poleci po kablach tak samo jest z odbiorem.
    Na twoim miejscy bym zrobił bez tej "synchronizacji" (struktury sekwencyjnej). Po prostu wysyłasz 5 bajtów i równocześnie odbierasz 5 bajtów.

    Nie wiem czy dobrze rozumiem Twoja idee.

    0
  • #13 15 Sie 2012 20:58
    tmf
    Moderator Mikrokontrolery Projektowanie

    Ale to już niekoniecznie. Skoro pomiar ADC będzie najczęściej co 1 ms, to spokojnie w przerwaniu timera można odczytywać ADC i rozpoczynać kolejną konwersję, której wynik odczyta się w następnym przerwaniu timera i tak w kółko.

    0
  • #14 15 Sie 2012 23:23
    oObi89
    Poziom 9  

    co do LV chyba faktycznie tą sekwencje musze wywalić, bo te opóźnienia chyba jakoś dziwnie wpływają na cały proces..

    a co do programu ma to generalnie być PID z zadawanymi kilkoma rzeczami z LV, wszystko ma sobie wyliczać i parę rzeczy przedstawiać na komputerze, ADC chyba musi być w timerze, bo mam konkretne czasy próbkowania (1,10,100ms), a przerwaniem od ADC chyba tego nie uzyskam. Myślałem sobie, żeby zrobić odbiór danych w jednym przerwaniu, wysyłanie w drugim przerwaniu(lub tez w przerwaniu od timera co określony czas), odczyt adc + pwm w przerwaniu od timera, a w pętli głównej funkcja PIDa, czy dobrze myśle i czy coś takiego ma prawo zadziałać?

    0
  • #15 15 Sie 2012 23:50
    LordBlick
    VIP Zasłużony dla elektroda

    oObi89 napisał:
    ADC chyba musi być w timerze, bo mam konkretne czasy próbkowania (1,10,100ms), a przerwaniem od ADC chyba tego nie uzyskam.
    Start konwersji ADC jak najbardziej w przerwaniu timera, ale odczyt w przerwaniu ADC będzie natychmiast po jej zakończeniu.

    0
  • #16 16 Sie 2012 19:50
    ppawel12
    Poziom 16  

    Co do procka to LordBlick ma racje.

    W LV wywal tą strukturę sekwencyjną i te "prymitywną synchronizację". Daj lepiej w zwykłej pętli while odczyt i zapis. Jak wejdziesz w przerwanie ustaw flagę informującą procke o wysłaniu danych po wyjściu z przerwania. Procek wychodzi z przerwania i wysyła info do LV. Jak coś wpiszesz do rejestru to wyślesz, LV odbierze i zapisze do np. tablicy, vektora i potem to obsłużysz. Ja bym dał obsługę przycisku -> wprowadzasz dane do LV klikasz przycisk i dane zostają wysłane do procka. Co najwyżej odbieranie danych w przerwaniu plus opóźnienie w LV przy wysyłaniu by nie nadpisać danych w rejestrach (dużo danych chcesz wysyłać). Należało by to przetestować.

    0
  • #17 17 Sie 2012 12:54
    oObi89
    Poziom 9  

    teraz pojawił się kolejny problem, w przerwaniu od RXC odbieram i wysyłam po 13 bajtów danych, z tego co widać na obrazach poniżej to wg. mnie wartości są odsyłane prawidłowo (4 ostatnie bajty w arrayu 'odebrany string' jest to wartość odczytów adc, a wcześniejsze bajty są na razie po prostu odsyłane z powrotem).
    Problem pojawia się, kiedy odesłaną liczbę 16bitową chce z powrotem przedstawić w formie liczby 16bitowej, ( odebrane części hi i lo są identyczne jak te wysłane, ale z jakiegoś powodu nie są one poprawnie przedstawiane). Dodatkowo do kontrolek ADC0 i ADC1 są podpięte wyniki z tego samego pomiaru, a jedna kontrolka pokazuje wartość 10 bitową a druga 8bitową. Wydaje mi się, że jest to jakiś problem po stronie LabView, ale mogę się mylić, może jakiś bardziej doświadczony kolega jest mi w stanie pomóc?

    pętla główna:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    przerwanie od RXC:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    w przerwaniu od timera znajduje się na razie tylko miganie diodą co sekunde, żeby być pewnym, że przerwanie działa, ale później przeniose do niego odczyt ADC jak będzie już dobrze wszystko działało i jak dodam przełączanie kanałów.
    Co do wysyłania danych zdecydowałem się zostawić je w przerwaniu od RXC jako, że będę wysyłał i odbierał tablice o takim samym rozmiarze i takie rozwiązanie jest chyba najprostsze czy takie rozwiązanie jest prawidłowe, bo póki co działa ok? [ATmega32][C/LabView] - Obsługa dwukierunkowa RS232 [ATmega32][C/LabView] - Obsługa dwukierunkowa RS232

    0
  • #18 17 Sie 2012 18:14
    ppawel12
    Poziom 16  

    Teoretycznie w przerwaniu możesz wysyłać, ale z drugiej strony w przerwaniu powinno się tylko ustawiać flagi by szybko powracać z przerwania. Jak prosta aplikacja to przejdzie ale jak będzie bardzo rozbudowana to postanie dłuższy czas w przerwaniu może być problemem.

    Rozumiem, że masz problem z LV.

    Cytat:
    Problem pojawia się, kiedy odesłaną liczbę 16bitową chce z powrotem przedstawić w formie liczby 16bitowej, ( odebrane części hi i lo są identyczne jak te wysłane, ale z jakiegoś powodu nie są one poprawnie przedstawiane).


    daj jakiś przykład co wysyłasz. Masz liczbę16 bitową czyli dwa bajty podaj je i podaj to co odebrałeś również w postaci 2 bajty i cała liczba 16 bitowa. Podejrzewam problem z rzutowaniem (konwersja).

    Cytat:
    Dodatkowo do kontrolek ADC0 i ADC1 są podpięte wyniki z tego samego pomiaru, a jedna kontrolka pokazuje wartość 10 bitową a druga 8bitową. Wydaje mi się, że jest to jakiś problem po stronie LabView, ale mogę się mylić, może jakiś bardziej doświadczony kolega jest mi w stanie pomóc?


    Chodzi o tą liczę 134 i 902 ? powinny być te same wyniki ? Po stronie LV nie masz żadnych operacji matematycznych, jedynie to co odbierasz od razu wyrzucasz na ekran.
    sumując te wartości w "odebranym string" te 2 bajty ostatnie są identyczne czyi jest ok, ale coś w tej kontrolce ADC0 jest przekładaniem :/ z jakiegoś powodu wrzuca ostatnią wartość odebraną:/ weź może w LV ręcznie wygeneruj tablicę do odebrania i patrz na debugerze jak idzie przesyłanie danych. Być może jakieś przesunięcie się wkradło :/

    0
  • #19 18 Sie 2012 12:19
    oObi89
    Poziom 9  

    hm, w jakim sensie ustawiam tylko flage? chodzi o coś takiego ??

    Kod: c
    Zaloguj się, aby zobaczyć kod


    i teraz w pętli głównej coś takiego??

    Kod: c
    Zaloguj się, aby zobaczyć kod


    bo to niestety nie działa, ale gdyby dało się zrobić coś działającego na takiej zasadzie to byłoby nawet lepiej. W tym momencie do PC nie jest odsyłane nic, aż wkońcu wyskakuje error z timeoutem.

    Co do wysyłania liczb o którym pisałem wcześniej to wychodzi na to, że mieszają się starsze bity z tych liczb, dlatego pokazuje złe wyniki, a co do kontrolki ADC to powinny być wyświetlane identyczne wartości bo jest wysyłane dokładnie to samo, a znowu jest wyświetlany tylko jeden bajt.

    0
  • Pomocny post
    #20 18 Sie 2012 16:06
    ppawel12
    Poziom 16  

    O coś takiego mi chodziło. Teraz jest wywoływane przerwanie i procesor tylko je wykonuje ustawia flagę i ucieka do obsługi całego kodu.
    rxFlag i txFlag - musi być tylu volatile (int/char itp.) by była możliwość zmieniania ich wartości w przerwaniu. Masz tak ?? Sprawdzałeś w symulatorze jak program skacze po funkcjach ??

    Zrób tak. skopiuj to wszystko do nowego VI i wywal bloczki READ and WRITE. Stwórz prostą tablicę tego co wysyłasz i podłącz na czysto. Będzie to prosta symulacji komunikacji. Wtedy włącz coś takiego jak highlight (chyba tak to się nazywa taka żarówka w LV na górze) i obserwuj jak podążają dane i gdzie może nastąpić przekłamanie/zgubienie bajtu.

    0
  • #21 19 Sie 2012 22:21
    oObi89
    Poziom 9  

    flagi rx i tx oczywiście próbowałem ustawić jako volatile, niestety efekt ten sam - nie działa. Na razie odbieram i wysyłam w przerwaniu RXC i to działa, ale jeśli da się to zrobić lepiej to chętnie poprawie.


    Co do LabView okazało się, że popełniłem błąd w indexowaniu bloczka 'index array', w helpie jest podane, że funkcja wybiera elementy arraya do n-1, a nie do n tak jak ja to zrobiłem, więc ten element też już działa :)

    0
  • #22 20 Sie 2012 17:26
    ppawel12
    Poziom 16  

    Powinno zadziałać, czemu nie nie działa to pytanie do bardziej zaawansowanych użytkowników AVR ja programuje PIC

    spoko z LV już wszystko śmiga ?

    0
  • #23 20 Sie 2012 19:18
    oObi89
    Poziom 9  

    tak, LV działa dobrze, wszystko jest jak powinno być, teraz tylko pytanie co z tą transmisją, a póki co walczę z PIDem.

    0
  • #24 20 Sie 2012 21:54
    ppawel12
    Poziom 16  

    a próbowałeś ten kod ruszyć w symulatorze ? program wchodzi do przerwania ustawia flage i co dalej się dzieje ?

    0
  • #25 20 Sie 2012 23:10
    stanleysts
    Poziom 27  

    nie wiem ale dla mnie ten kod jest średni, bo załóżmy że odbierasz dane i ok wyskakuje przerwanie- flaga jest ustawiona, zapisujesz dane do tablicy i jest ok, ale potem czekasz jakis czas, bufor jest pusty i co - wysylasz dane z tablicy zwiększasz licznik i znów bufor jest pusty to znow dane się wysylają (no bo występuje przerwanie od pustego bufora nadawczego)- ale jakie dane - przecież tam już nic wartościowego nie ma? jak do tej pory mniej odebrałeś niż chcesz wyslać. Zresztą wyślesz dane i znów się przerwanie wykona bo bufor danych wysłanych jest pusty - licznik się szybko przekręci itd. Wg mnie powinno być jakieś kontrolowane blokowanie przerwań

    0
  • #26 21 Sie 2012 18:27
    ppawel12
    Poziom 16  

    Nie wiem jak jest w AVR ale w PIC nie wyślesz pustego bufora przerwanie się wykona jeśli jakieś dane są w buforze. Tak samo z odbieraniem.
    Można dodać licznik by kontrolować wysyłanie i odbieranie.

    0
  • #27 21 Sie 2012 19:13
    stanleysts
    Poziom 27  

    może coś źle rozumiem i się trochę źle wysłowiłem, nie wysyłam przecież "pustego bufora" ale to co znajduje się w tablicy (bufor_wysylu[licznik1]) bo to jest do UDR wpisywane, a tam coś zawsze jest, nie ważne, że śmieci ale coś jest, to dlaczego to się ma nie wysłać?

    0
  • #28 21 Sie 2012 22:06
    oObi89
    Poziom 9  

    nie wiem czy was dobrze rozumiem, ale przecież tak jak jest zrobione teraz to moje bufory (odbioru i wysyłu) mają stałą wartość i stały rozmiar, dane są cały czas wpisywane te same i dokładnie w te same miejsca tablicy lub są aktualizowane, musze odbierać/wysyłać stale to samo bo ma to służyć do kontroli pewnych funkcji z komputera, więc chyba żadne inne śmieci nie mają prawa się wysłać.

    a co do tego co polecałeś wcześniej, to jak przetestować coś takiego w symulatorze? bo przecież żeby mi weszło do przerwania od RXC to musiałoby coś zostać wysłane z komputera, czy da się to zrobić jakoś inaczej?

    0
  • #29 21 Sie 2012 22:28
    stanleysts
    Poziom 27  

    Cytat:
    nie wiem czy was dobrze rozumiem, ale przecież tak jak jest zrobione teraz to moje bufory (odbioru i wysyłu) mają stałą wartość i stały rozmiar, dane są cały czas wpisywane te same i dokładnie w te same miejsca tablicy

    Ale z jakimi częstotliwościami są wpisywane/wypisywane...

    0
  • #30 21 Sie 2012 22:32
    oObi89
    Poziom 9  

    no tak.. tego dokładnie nie wiem, jest to robione z każdym kolejnym przebiegiem nieskończonej pętli while, więc wydaje mi się, że i tak jest to robione szybcięj niż są wywoływane przerwania od RXC, a do tego jeszcze przed pierwszym przebiegiem pętli while oba bufory są zainicjowane wartością 0 we wszystkich komórkach, więc wydaje mi się, że jest ok.

    0