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

[atmega16][c][rs232] Problem z kodowaniem (?) znaków

kormikez 29 Maj 2009 10:34 1320 5
REKLAMA
  • #1 6589118
    kormikez
    Poziom 10  
    Witam forumowiczów Elektrody :)

    Trudno mi powiedzieć, czy prawidłowo zdefiniowałem w temacie problem (raczej nie), bo w gruncie rzeczy nie wiem, dlaczego mój program zachowuje się w taki sposób. A oto jak się zachowuje.

    Opis działania programu:

    Odebrany z interfejsu UART pojedynczy znak odbij natychmiast z powrotem. Czyli takie echo "nielokalne".

    Efekt:
    Niektóre ze znaków wracają prawidłowo, inne zamieniają się w krzaki bądź zupełnie inne znaki, np.:

    w -> w     e -> g     r -> r 
    t -> v     u -> w     i -> o 
    o -> o     p -> ~     s -> s 
    d -> f     f -> f 

    ...itd. Sądzę, że dalej wymieniać nie ma potrzeby :)

    Do odbioru znaku wykorzystywane jest przerwanie UART, tak jak to widać w kodzie poniżej:

    SIGNAL (SIG_UART_RECV){ 
            unsigned char c;
            c = UDR;
            rsSend(c);
    }
    
    void rsSend(unsigned char data){
            while( !(UCSRA & (1<<UDRE)));
            UDR = data;
    }


    Jako terminala używałem programów minicom i HyperTerminal. Na obu efekt identyczny.

    Dodam, że tematyka AVR to dla mnie trochę nowość, zajmuję się tym od około 2 miesięcy i na pewno wielu rzeczy nie wiem. Jeżeli problem, który tu poruszam jest w jakiś sposób banalny to proszę o wyrozumiałość :)

    Aha, no i mam nadzieję, że nie powieliłem tematu na forum, ale naprawdę trudno było mi zdefiniować problem, stąd nie sposób znaleźć odpowiedź.


    I jeszcze może jedna rzecz, być może będzie to jakaś wskazówka. Gdy w obsłudze przerwania miałem taki ciąg instrukcji:

    SIGNAL (SIG_UART_RECV){ 
            LEDY_ON();
            unsigned char c;
            c = UDR;
            rsSend(c);
            _delay_ms(100);
            LEDY_OFF();
    }

    wówczas zamiast znaków wracały tylko i wyłącznie krzaki (i wszystkie takie same). Zbyt długa obsługa przerwania? :|

    Będę niezmiernie wdzięczny za wszelkie wskazówki. Słowa krytyki również wskazane :)

    Pozdrawiam.
  • REKLAMA
  • #2 6589198
    Jerzy_W
    Poziom 14  
    Witam!
    Ten kod powinien działać!
    Czym taktujesz ATMega?. Ja zawsze tam gdzie jest transmisja na UART daję kwarc. Wewnętrzny oscylator jest mało dokładny i mało stabilny termicznie.
  • REKLAMA
  • #3 6589292
    kormikez
    Poziom 10  
    W układzie jest zewnętrzny kwarc. Problem sprzętowy raczej bym wykluczył, posiadam dwa egzemplarze, z którymi nie było zresztą dotąd problemów (np. obsługa modułów RF), a które zachowują się identycznie. Oba zostały złożone przez osobę się na tym znającą (czyli nie przeze mnie ;).

    Przy okazji, dzięki użyciu diody zauważyłem jeszcze jedno: wpisanie w terminalu znaków 'q' oraz 'a', czy też (spacja) generuje dwa znaki.
  • REKLAMA
  • REKLAMA
  • #5 6589778
    wilk125
    Poziom 23  
    jaka wartośc ma zewnetrzny kwarc?
  • #6 6589780
    kormikez
    Poziom 10  
    dawid512: Twoje rozwiązanie daje ten sam efekt, co mnie odrobinę zaskakuje.

    Inicjalizacja oczywiście jest, wygląda to dokładnie tak:
    void rsConf(){
            // set baud rate
            UBRRH = (uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_OSC)>>8);
            UBRRL = (uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_OSC);
    
            // Enable receiver and transmitter; enable RX interrupt
            UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
    
            //asynchronous 8N1
            UCSRC = (1 << URSEL) | (3 << UCSZ0);
    
    }


    gdzie:
    #define F_OSC 4000000
    #define UART_BAUDRATE 9600
    #define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUDRATE)*16l)-1)



    EDIT
    No i mam rozwiązanie problemu. Na rozwiązanie naprowadziła mnie uwaga wilka125, ale wszystkim Wam dziękuję za zaangażowanie.
    Problem polegał na tym, że mam kwarc 16Mhz, podczas gdy F_OSC był jak widać powyżej. Zmiana na 16MHz rozwiązała całą kwestię.

    Jeszcze raz serdeczne dzięki!
REKLAMA