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] Problem z USART-em

Prezes87 28 Lis 2010 14:10 1432 9
REKLAMA
  • #1 8799874
    Prezes87
    Poziom 11  
    Witam!
    Mam problem z USART-em mianowicie nie chce wysyłać tego co chce i wysyła jakieś bzdety.

    
    #define F_CPU            1000000ul
    #include <avr/io.h>
    #include <util/delay.h>   
    #include <avr/signal.h>
    #define FOSC 1000000   
    #define CZYT 50
    #define BAUD 9600
    #define MYUBRR FOSC/16/BAUD-1
    
    
    void USART_Init( unsigned int ubrr){
       /* Set baud rate */
       UBRRH = (unsigned char)(ubrr>>8);
       UBRRL = (unsigned char)ubrr;
       UCSRB|=_BV(RXEN)|_BV(TXEN)|_BV(RXCIE);
       UCSRC|=_BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0);
       //sei();
    }
    
    
    void USART_Transmit( unsigned char data ){
       /* Wait for empty transmit buffer */
       while ( !( UCSRA & (1<<UDRE)) );
       /* Put data into buffer, sends the data */
       UDR=data;
    }
    
    unsigned int USART_Receive( void )
    {
    unsigned char status, resh, resl;
    /* Wait for data to be received */
    while ( !(UCSRA & (1<<RXC)) )
    ;
    return UDR;
    }
       
    
    int main ()
    {
       USART_Init (MYUBRR);
       while(1)
       {
    			USART_Transmit('z');
    	}
       return 0;
    }
    
  • REKLAMA
  • #2 8800013
    tadzik85
    Poziom 38  
    Źle wyliczone UBRR.
  • #3 8800152
    Prezes87
    Poziom 11  
    Dlaczego źle? Mógłbyś rozwinąć swoją odpowiedź?

    Czy może to problem być z Fuse Bitami? Mam ustawione tak jak jest fabrycznie...
  • REKLAMA
  • #4 8800197
    Andrzej__S
    Poziom 28  
    #define MYUBRR FOSC/16/BAUD-1 jest dokładnie przepisane z przykładu w datasheet ATmega16, więc to chyba nie to. Poza tym wyrażenie FOSC/16/BAUD jest chyba równoważne FOSC/(16*BAUD), bo wydaje mi się, że najpierw wykonywane jest działanie FOSC/16, a następnie wynik dzielony jest przez BAUD.
    Moim zdaniem większe znaczenie może mieć fakt, że przy BAUD=9600, U2X=0 i zegarze 1MHz błąd wynosi -7%, więc nawet przy dobrze wyliczonym UBRR synchronizacja może się rozjeżdżać.

    EDIT:
    ...no a jeśli to w dodatku wewnętrzny oscylator?
  • REKLAMA
  • #5 8800199
    tadzik85
    Poziom 38  
    Wpisz twardo wartość z tabelki w datasheet i sprawdź. Sprawdź czy na pewno procesor działa na założonej przez ciebie częstotliwości.
  • #6 8800231
    gaskoin
    Poziom 38  
    Dobrze policzone.

    Po primo - ten baude rate dla 1MHz daje 7% błędów transmisji
    W połączeniu z tak-sobie stabilnym taktowaniem, błąd rośnie :)

    spróbuj z 4800

    Edit: nie ma znacenia czy napiszę 15/3/3/3/3/3 czy 15/(3*3*3*3*3) najpierw wykonywane jest pierwsze dzielenie 15/3 , potem liczba, którą otrzymamy, jest dzielona /3 itd, w drugim przypadku najpierw liczone są wszystkie mnożenia. Nie ma to jednak znaczenia bo liczone to jest na etapie kompilacji (w tym przypadku)
  • #7 8800243
    Prezes87
    Poziom 11  
    Zmieniłem nawet na 1843200 częstotliwośc przy której ma 0% i w dalszym ciągu to samo...

    Jak coś pomoże(a wątpię) to wyrzuca mi "cŘĆţĂ{FF}" zamiast "z"
  • REKLAMA
  • Pomocny post
    #8 8800255
    gaskoin
    Poziom 38  
    Programowo nie da się jej zmienić.......

    Weź chłopie daj wszystko jak było, tylko BAUD daj 4800 i sprawdź, czy przy takiej prędkości działa

    
    #define F_CPU            1000000ul
    #include <avr/io.h>
    #include <util/delay.h>   
    #include <avr/signal.h>
    #define FOSC 1000000   
    #define CZYT 50
    #define BAUD 4800
    #define MYUBRR FOSC/16/BAUD-1
    
    
    void USART_Init( unsigned int ubrr){
       /* Set baud rate */
       UBRRH = (unsigned char)(ubrr>>8);
       UBRRL = (unsigned char)ubrr;
       UCSRB|=_BV(RXEN)|_BV(TXEN)|_BV(RXCIE);
       UCSRC|=_BV(URSEL)|_BV(UCSZ1)|_BV(UCSZ0);
       //sei();
    }
    
    
    void USART_Transmit( unsigned char data ){
       /* Wait for empty transmit buffer */
       while ( !( UCSRA & (1<<UDRE)) );
       /* Put data into buffer, sends the data */
       UDR=data;
    }
    
    unsigned int USART_Receive( void )
    {
    unsigned char status, resh, resl;
    /* Wait for data to be received */
    while ( !(UCSRA & (1<<RXC)) )
    ;
    return UDR;
    }
       
    
    int main ()
    {
       USART_Init (MYUBRR);
       while(1)
       {
    			USART_Transmit('z');
    	}
       return 0;
    }
    
  • #9 8800261
    Prezes87
    Poziom 11  
    Dobra dzięki wielkie już działa. Jedna to 7% to było dużo.
  • #10 8800268
    gaskoin
    Poziom 38  
    Możesz zawsze ustawić bit U2X - wtedy da się 9600 wycisnąć z błędem 0.2%, ale zawsze to lepiej zastosować zewnętrzne źródło taktowania
REKLAMA