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

atmega8 - UART przerwania - dioda nie gaśnie po odebraniu danych UART

lukas_gab 22 Kwi 2015 18:13 1620 9
REKLAMA
  • #1 14638178
    lukas_gab
    Poziom 15  
    Witam !

    Dalej walczę z komunikacją uart i dokładam kolejne klocki. Obecnie chciałem nauczyć się korzystać z przerwań. Napisałem następujący program. Do atmegi mówię przez program minicom. Chciałem, żeby przy każdym odebraniu czegoś po uart zapalił diodę, poczekał i ją zgasił. Niestety dioda się tylko zapala i nigdy nie gaśnie ... nie wiem dlaczego - proszę o pomoc - co robię nie tak ?

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Dodano po 55 [minuty]:

    Chyba już wiem co jest ... nie odbierałem danych z rejestru i chyba przerwanie cały czas było wyzwolone i jak gasło to od razu się zapalało ;) Teraz zrobiłem informacje zwrotną i widzę, ze odsyłam na zmianę a i b no i dioda miga, ale muszę czyścić rejestr UDR
  • REKLAMA
  • Pomocny post
    #2 14638404
    BlueDraco
    Specjalista - Mikrokontrolery
    Ta instrukcja nie robi NIC:
    PORTC |= (0<<PC5);
  • REKLAMA
  • Pomocny post
    #3 14639591
    Zaquadnik
    Poziom 27  
    Powinno być
    Kod: text
    Zaloguj się, aby zobaczyć kod
    .
    Linia taka ustawia maskę kod
    Kod: text
    Zaloguj się, aby zobaczyć kod
    . wykonuje operację OR rejestru PORTC z maską 00100000, czyli ustawi bit 6-ty (PC5). Operacja
    Kod: text
    Zaloguj się, aby zobaczyć kod
    . Spowoduje wykonanie operacji AND rejestru PORTC z maską 11011111, czyli wyzeruje ów bit.

    Do tego, na przyszłość, w przerwaniu nie powinieneś wywoływać funkcji zabierających dużo czasu, w tym funkcji delay. Obsługa przerwania powinna być jak najprostsza.
  • Pomocny post
    #4 14639954
    dondu
    Moderator na urlopie...
    oraz jeszcze:

    1. stosujesz stare funkcje obsługi przerwań a nowe wektory - stosuj nowe funkcje ISR(): http://nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
    i wywal nagłówek #include <avr/signal.h>

    2. returny w funkcjach ISR() i main() są zbędne.

    3. Ostatnia uwaga kol Zaquadnik jest baaaardzo istotna.
    Nie dość, że czekasz w funkcji delay to jeszcze dodatkowo czekasz w funkcji USART_Recive takżę wywoływanej w delay - efekt - mikrokontroler kręci się w pętli:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    przy jednocześnie zablokowanych przerwaniach, bo mikrokontroler je zablokował w momencie wejścia w funkcję przerwania.

    Zapoznaj się z tymi artykułami:
    http://mikrokontrolery.blogspot.com/2011/03/rs-232-atmega8-komputer-terminal.html
    http://mikrokontrolery.blogspot.com/2011/04/problemy-c-przerwania.html
  • #5 14644847
    lukas_gab
    Poziom 15  
    Cześć. Dziękuję za wasze odpowiedzi. Udało mi się poprawnie już komunikować i migam diodą sobie. Teraz chciałem przekazać całą instrukcje - tj. adres, po czym rozkaz, ilość parametrów wejściowych, ilość wyjściowych i potem n parametrów wejściowych, czyli pewnie będzie to kilka to kilkunastu bajtów. W odpowiedzi, chciałem dać status czy się udało + ew. odpowiedz - może seria pomiarów z zadanego czasu. Jeżeli nie mam tego robić w przerwaniu to kiedy ? Myślałem, że procesowania przerwania mam zrobić w funkcji przerwania, i podobnie odpowiedź.

    A co sądzicie, żebym w przerwaniu ustawiał jakąś flagę, i jak wrócę z przerwania to jak zakońccze np. pomiary w pętli głównej to przejdę do pobrania rozkazu i potem ew. odpowiedzi??
  • REKLAMA
  • #6 14644986
    dondu
    Moderator na urlopie...
    Musisz opracować własny protokół wymiany danych.

    Jeśli rozkaz wraz z jakimiś dodatkowymi bajtami ma np. 5 bajtów, to warto odbierać je do jakiegoś bufora i dopiero po odebraniu wszystkich rozpoznać jaką paczkę danych odebrano. Z reguły o tym co dana paczka zawiera decyduje co najmniej pierwszy bajt lub kilka jego bitów. Równie dobrze może to być aż 3 bajty i dopiero 2 bajty danych.

    Tak działają popularne komendy AT.

    W ten sposób przerwanie jedynie odbiera dane i co najwyżej rozpoznaje odebranie ostatniego bajtu, jeśli jest to np. zero uznawane za koniec paczki danych. Wtedy też w funkcji przerwania ustawiana zostaje jakaś flaga dl pętli głównej, która zajmie się uruchomieniem funkcji rozpoznającej odebraną paczkę danych.

    To tylko przykład, ale możesz zaprojektować protokół wymiany danych dowolnie inaczej.

    Przykład użycia komend AT do komunikacji mikrokontroler <--> Android znajdziesz tutaj: http://mikrokontrolery.blogspot.com/2011/03/android-bluetooth-LED-MASTER.html
  • #7 14645211
    lukas_gab
    Poziom 15  
    Ok, dzięki za link. Co do sposobu samej transmisji, to już chyba opracowałem sobie protokół - zamierzam w buforze zapisywać odebrane bajty w przerwaniu, a po zakończeniu przesyłania ramki - będę ustawiał flagę i główna pętla będzie procesować komende.

    Wszystko było by super - napisałem nawet prosty program, który odbierał dane i zapisywał w buforze. Jak przesłałem znak 'x' to opróżniał bufor i odsyłał wszystko w kolejności jak odbierał. No super, tylko, że czasami mając takie wejscie

    qwerx

    odpowiadał

    qwerx

    a czasami

    qw<krzaki>x

    Czasami zamiast po x dać odpowiedź musiałem nacisnąć drugi raz x i dopiero wtedy odpowiadał. Jak szybko naciskałem klawiaturę komputera to potrafiłem napisac 3 x 'x' zanim zaczął odpowiadać.

    Idąc dalej postanowiłem to zdebuggować. Napisałem program który odbiera bajty i jak odbierze 'x' to odpowiada zadanym ciągiem znaków.

    W tym przypadku zawsze dostawałem w odpowiedzi zadany ciąg znaków o ile ją dostałem i zawsze było to 'abcde'. Problem w tym, że nie zawsze odpowiadał - czasami należało dwa razy nacisnąć 'x' lub więcej. Nie wiem tak naprawdę skąd to wynika. Przez to, że ciąg odpowiedzi jest stały jestem pewien, że wysyłanie jest ok - gdyż zawsze dostaję dany ciąg znaków nie uszkodzony - problemem jest odbiór prawidłowego bajtu, i sądzę, że to on może być uszkodzony - podobnie w programie wcześniej, pewnie dane były uszkodzone - zapisane do buforu i zwrócone.

    Poniżej przedstawiam program testowy - powiedzcie proszę, dlaczego ten program może mieć problemy z odbiorem poprawnym danych ??

    Jako master używam RaspberryPi i łączę się z atmegami poprzez :

    Kod: Bash
    Zaloguj się, aby zobaczyć kod


    atmegi są podłączone do raspberry pi w magistrale - TX RPi - RX - Atmeg, RX Rpi - TX atmeg - transmitery są wpięte przez diodę, żeby nie było kolizji.

    Do Raspberry pi łączę sie po ssh - obecnie przez dyndns przez internet, ale to chyba nie ma znaczenia - jak łączyłem się po lanie był ten sam problem.

    program:

    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #8 14658119
    lukas_gab
    Poziom 15  
    Problemem był wewnętrzny oscylator 8Mhz. Zastosowałem zwykły zewnętrzny ( nie "uartowy") 12Mhz i działa pięknie. Wynika z tego że wewnętrzne oscylatorki są kiepskie. Niemniej dziękuję za dyskusje - może moje doświadczenie się komuś przyda .
  • REKLAMA
  • #10 14865813
    lukas_gab
    Poziom 15  
    Ostatecznie powiem, żeby zamknąć temat - faktycznie jak ktoś będzie miał problemy z uart - rekomenduje prace na zewn. kwarcy lub na wew. oscylatorze z kalibracją.
REKLAMA