konze
konze

Reputation: 893

AVR UART receives wrong bytes

after a long pause I started to program AVRs again. I was able to setup a UART communication between my Linux computer and an Atmega8. Unfortunately the Atmega8 seems to receive the wrong bytes when I send bytes greater than 0x1f. The UART is running with 9600 BAUD and the data format 8N1.

// clock frequency 1Mhz 
#define F_CPU 1000000UL

// baud rate
#define BAUD 9600
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>


void uart_init (void);
void uart_putc (unsigned char data);
void uart_puts (unsigned char * str, uint8_t size);

// interrupt service routine for UART receiver interupt
ISR(USART_RXC_vect) {

    // get received char
    unsigned char received_char = UDR;

    uart_puts("received=", 9);

    if((received_char & (1<<7)) == (1<<7)) {
        uart_putc('1');
    } else {
        uart_putc('0');
    }

    if((received_char & (1<<6)) == (1<<6)) {
        uart_putc('1');
    } else {
        uart_putc('0');
    }

    if((received_char & (1<<5)) == (1<<5)) {
        uart_putc('1');
    } else {
        uart_putc('0');
    }

    if((received_char & (1<<4)) == (1<<4)) {
        uart_putc('1');
    } else {
        uart_putc('0');
    }

    if((received_char & (1<<3)) == (1<<3)) {
        uart_putc('1');
    } else {
        uart_putc('0');
    }

    if((received_char & (1<<2)) == (1<<2)) {
        uart_putc('1');
    } else {
        uart_putc('0');
    }

    if((received_char & (1<<1)) == (1<<1)) {
        uart_putc('1');
    } else {
        uart_putc('0');
    }

    if((received_char & (1<<0)) == (1<<0)) {
        uart_putc('1');
    } else {
        uart_putc('0');
    }

    uart_puts("\n\r",2);
}


// function to initialize UART
// dataformat 8N1
void uart_init (void) {

    // shift the register right by 8 bits
    UBRRH = (BAUDRATE>>8);

    // set baud rate
    UBRRL = BAUDRATE;            

    // enable receiver, transmitter and receiver interrupt
    UCSRB|= (1<<TXEN)|(1<<RXEN)|(1<<RXCIE);

    // 8bit data format
    UCSRC|= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);   

}

// sends a single char over the UART
void uart_putc (unsigned char data) {

    // wait while register is free
    while (!( UCSRA & (1<<UDRE)));
    // load data in the register
    UDR = data;
}

// sends a string over the UART
void uart_puts (unsigned char * str, uint8_t size) {

    uint8_t i; 

    for(i = 0; i < size; i++) {
        uart_putc(str[i]);
    }
}

// receives a single char over the UART
unsigned char uart_getc (void) {

    // wait while data is being received
    while(!(UCSRA) & (1<<RXC));
    // return 8-bit data
    return UDR;
}


uint8_t main (void) {

    // enable interrupts
    sei();

    // enable uart
    uart_init(); 

    uart_puts("ready\n\r", 7);

    while(1) {
    } 

    return 0; 
}

In GtkTerm I send the following byte sequence: 0x01, 0x02, 0x03, 0x1d, 0x1e, 0x1f, 0x20 and interrupt service routine ISR responds with the following sequence.

enter image description here

However, I should receive received=00100000 for 0x20
Whats wrong?

Upvotes: 1

Views: 1575

Answers (1)

Rev
Rev

Reputation: 6092

From my comment:

Maybe the baud rate is off due to using a slow clock rate / internal RC oszillator? The slower the baud rate, the greater the offset from the "middle" of each bit. This can lead to skipping bits or the controller seeing a bit twice.

Upvotes: 1

Related Questions