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

atmega8+uart+przerwanie+dioda+LED+C

28 Lut 2011 17:04 2648 25
  • Poziom 12  
    napisałem program który powinien sprawdzić czy wysłany znak z klawiatury przez hyperterninal odpowiada znakowi, który ustawiłem programowo w tablicy. Do tego użyłem przerwania reagującego na terminator. Jeśli znak z klawiatury będzie zgodny ze znakiem w tablicy to powinna się zaświecić dioda. Program sie kompiluje lecz nie reaguje na moje próby. Od niedawna jestem hobbystą avr' ków dlatego mam pytanie odnośnie przerwań czy mogę ustawić tak flagę jak mam poniżej w programie?
    Kod: c
    Zaloguj się, aby zobaczyć kod
    Darmowe szkolenie: Ethernet w przemyśle dziś i jutro. Zarejestruj się za darmo.
  • Pomocny post
    Moderator Mikrokontrolery Projektowanie
    Odczyt rejestru UDR powoduje utratę jego zawartości - stąd jeśli do jego poprzedniej wartości chcesz się ponownie odwołać, musisz jego stan przechowywać w jakiejś tymczasowej zmiennej.
  • Pomocny post
    Poziom 27  
    NIe możesz tak manewrować ciągle rejestrem UDR.
    Skopij UDR w przerwaniu raz do jakiejś zmiennej , a potem używaj już tylko tej zmiennej.
  • Pomocny post
    Poziom 23  
    Moja propozycja jest taka, w celu sprawdzenia połączenia, najpierw w przerwaniu odsyłaj echo do terminala, wykluczy to błędy sprzętowe.

    Druga sprawa jest taka, że nie powinieneś odczytywać UDR w pętli, a tylko w przerwaniu. Żebym gafy nie strzelił, ale wydaje mi się, że w momencie odczytania z UDR rejestr ten się zeruje.
    W zasadzie to właśnie w przerwaniu powinieneś dodawać odczytany znak do tablicy a lepiej bufora okrężnego i sprawdzać czy był to np 0x0D.
    Jeśli był to analizujesz te kilka znaków przed nim.
    -------------------------------
    Dwóch mnie ubiegło.... aj, ten refleks
  • Poziom 12  
    czyli mogę zrobić po prostu tak? czy po takiej zmianie licznik nie będzie mi się inkrementował?
    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    Poziom 23  
    Nie możesz tak zrobić. Napisaliśmy Ci w miarę wyraźnie, nie możesz dwa razy użyć UDR. Napisz sobie na początku przerwania
    Kod: c
    Zaloguj się, aby zobaczyć kod
    a potem tego x używaj sobie ile razy chcesz.
    Przeanalizuj sobie ten program jeszcze krok po kroku, może rozrysuj, jak nie pójdzie, któś podsunie Ci działający kod.
  • Poziom 12  
    Kod: c
    Zaloguj się, aby zobaczyć kod

    nie chciałbym korzystać z gotowych kodów bo chce sam trochę pogłówkować, ale czasami jest jakaś blokada i ani rusz dalej, a tablice sprawiają mi sporo problemów
  • Pomocny post
    Poziom 23  
    Kolego
    Kod: c
    Zaloguj się, aby zobaczyć kod
    to nie to samo co
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Już na wstępie pozbawiasz się informacji o tym co przyszło do procesora.
    Pisząc UDR=cośtam, każesz procesorowi coś wysłać, bo UDR to rejestr taki dwukierunkowy. Np:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    spowoduje, że to co odbierzesz przypiszesz do zmiennej x, a za chwile tego samego x wyślesz spowrotem jako ech. Aczkolwiek trzeba jeszcze dbać o to, żeby bufor nadawczo odbiorczy był czysty w momencie wysyłania / odbierania.
  • Poziom 12  
    Racja to nie to samo, teraz będę o tym pamiętał. A jeśli chodzi o to żeby bufor był czysty w momencie odbierania to w którym miejscu najlepiej użyć funkcji,
    Kod: c
    Zaloguj się, aby zobaczyć kod

    bo chyba o nią Ci chodzi?
  • Poziom 23  
    Nie kolego, wykorzystując przerwania nie stosujesz takiego kodu.
    Ten działa w taki sposób, że do momentu pojawienia się czegoś w buforze UARTa jest zapętlowny w while.

    Raczej chodziło o to, że wkładając dane do UART, kiedy nadajesz dane, musisz sprawdzać czy bufor jest czysty i dopiero dawać znak do transmisji.
  • Poziom 12  
    a w jaki sposób sprawdzać czy bufor jest czysty, bo teraz widzę, że trochę poplątałem myśląc że jak wyzeruje licznik w tablicy to będę miał czysty bufor.
  • Poziom 12  
    poszperałem w necie i znalazłem coś takiego

    Kod: c
    Zaloguj się, aby zobaczyć kod


    I teraz pytanie. Czy można zrobić dwa przerwania powiązane ze sobą?
  • VIP Zasłużony dla elektroda
    mianiek13 napisał:
    poszperałem w necie i znalazłem coś takiego
    Kod: c
    Zaloguj się, aby zobaczyć kod
    I teraz pytanie. Czy można zrobić dwa przerwania powiązane ze sobą?
    To przerwanie jest od wysyłania danych, a nie od odbioru.
  • Poziom 12  
    a chciałbym zapytać jeszcze o jedną rzecz, mianowicie znalazłem taki opis przerwań:

    Cytat:
    Avr-gcc posiada dwa typy handlerów przerwań : SIGNAL() - utrzymujący sprzętowe wyłączenie przerwania ( wszelkie pozostałe przerwania są zablokowane do momentu zakończenia obsługi bieżącego ); oraz INTERRUPT() - wyposażony w prologu w odblokowanie /sei()/ przerwań. Zasadniczym błędem jest użycie INTERRUPT w przypadku przerwań wyzwalanych warunkiem. Klasyczny przykład to np. obsługa usart - przerwanie jest aktywne zawsze po odebraniu bajtu, aż do jego odczytania. Jednak sei() w prologu nie daje nam szansy odczytu rejestru odbiornika - wcześniej zawsze wystąpi ponowne wywołanie handlera - i tak kolejno aż do przepełnienia stosu i wywrócenia się programu.


    czyli z tego mam rozumieć, że w moim przypadku nie powinienem stosować przerwania INTERRUPT()??
  • Poziom 12  
    po wielu próbach odstawiłem przerwania na bok bo możliwe, że problem mam z komunikacją uarta. Napisałem kod który zaświeca diodę jeśli otrzyma znak z klawiatury:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    I mama pytanie, dlaczego jak zmienie zero oraz negacje w if (i!=0) na np. if (i=='5') to dioda po wciśnięciu piątki na klawiaturze się już nie zaświeci? Czy można w ogóle tak robić bez dekodowania na hex? Albo mam jakiś inny problem
  • Poziom 23  
    Zapewne problem polega na tym, że
    Kod: c
    Zaloguj się, aby zobaczyć kod
    wykonujesz tylko w jednym przypadku. Powinieneś wywołać tą linię przed pętlą
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Sam zapis
    Kod: c
    Zaloguj się, aby zobaczyć kod

    jest jak najbardziej ok;
  • Poziom 12  
    Niestety ten zabieg nie spowodował zmian, tak jakby uart rozpoznawał dwa stany: jest sygnał i nie ma sygnału, bez odczytywania tego czym jest sygnał:/
    Nie wie Pan co może być przyczyną?
  • Pomocny post
    Poziom 23  
    No to ja tu widzę jeszcze taki dinks:
    W kodzie masz napisane, że prędkość transmisji to 9600.
    Zakładam, że mimo wszystko zostałeś przy zegarze procka 1MHz.
    Z tego zaś wynika, że jeśli do UBRRL wstawiasz 12, to twoja prędkość to nie 9600 a 4800.
    Drugą opcją jest to, że musisz załączyć bit U2X w rejestrze UCSRA (wtedy będzie 9600).
  • Poziom 12  
    Mad Bekon miałeś racje trzeba było dodać U2X do UCSRA:D serdeczne dzięki za pomoc w końcu widzę że ten USART działa. Teraz zabieram się za walke z tablicami i przerwaniem, wiec pewnie jeszcze bede miał kilka pytań i problemów:D
  • Poziom 12  
    Wiec po przeczytaniu i przejrzeniu sporej ilości stron w internecie i na elektrodzie, posiłkując się kilkoma podobnymi tematami stworzyłem taki kod
    Kod: c
    Zaloguj się, aby zobaczyć kod


    I chciałbym jakoś przebrnąć przez tego uarta wykorzystując tablice i przerwania, a następnie sprawdzić poprawność wysyłanych bajtów w terminalu. Jednak coś jest nie tak bo kod nie działa poprawnie( brak efektu na podanie w trzecim miejscu tablicy liczby pięć):/
  • Poziom 12  
    A jak w whil'u zmienię na to czy po prostu bufor jest gotowy jeśli tak to zaświeć diodę:
    Code:
       while(1){
    
           if(uart_rx_complete)
          {
             PORTB&=~(1<<PB1);//świecenie diody jesli czwarty znak jest dziewiatka
             _delay_ms(100);
             }
             else
             {
             PORTB|=(1<<PB1);// nie świecenie
             }   
             uart_rx_len = 0;// zwolnienie buforu
             uart_rx_complete = 0;
          }
       }


    lecz przez wysłania z terminala znaków reaguje na losową ich ilość. Tylko dlaczego tak losowo a nie chociażby na sam enter?
  • Pomocny post
    Poziom 10  
    1. powinieneś zamiast SIGNAL(SIG_UART_RECV) zastosować makro ISR( _vect)
    2. przerwanie to nie zwykła funkcja którą od tak sobie można przerwać prze break albo return
    3.uart_rx_buffer[uart_rx_len] = 0; tu powinien być NULL('\0'), a nie zero
    4.nie rozumiem Twojego sposobu wykorzystania flag spróbuj uart_rx_complete = 1; i uart_rx_complete = 0;
  • Moderator Mikrokontrolery Projektowanie
    bullyman napisał:
    1. powinieneś zamiast SIGNAL(SIG_UART_RECV) zastosować makro ISR( _vect)

    ... i tutaj znajdziesz, co trzeba: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
    Stosujesz stare nazwy wektorów: Old vector name
    a powinieneś te z pierwszej kolumny + ISR() tak jak napisał bullyman.
  • Poziom 12  
    dzięki za konkretną pomoc, po dodaniu jeszcze vilatile do char uart_rx_buffer[UART_MAXBUFF]; wszystko działa tak jak powinno. Temat uważam za zakończony.