Electronic – USART and ATmega RX Problem

atmegarxduart

I'm trying to understand how USART of ATmega works. I read some pages and I've picked information about it. To test functionality I've written this code:

#define F_CPU 16000000
#define BAUD_RATE_115200_BPS  8

#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>

void Transmit(void);

unsigned char data[] = "Data transmitted...";

int main()
{
    unsigned int ubrr = BAUD_RATE_115200_BPS;

    UBRR0H = (uint8_t)(ubrr >> 8);
    UBRR0L = (uint8_t)(ubrr);
    UCSR0B = (1 << RXEN0) | (1 << TXEN0);
    UCSR0C = (1 << USBS0) | (3 << UCSZ00);

    DDRB = 0b11111111;

    Transmit();

    while(1)
    {
        while (!(UCSR0A & (1 << RXC0)));

        //data[0] = UDR0;
        //data[1] = 0;

        sprintf(data, "%d", UDR0);

        Transmit();

        switch(UDR0)
        {
            case 'A':
                Transmit();
                PORTB = 0b11111111;
                _delay_ms(2000);
                PORTB = 0b00000000;
                break;

            case 'B':   
                PORTB = 0b11111111;
                _delay_ms(500);
                PORTB = 0b00000000;
                break;          

            default  :
                break;

        }
    }
}


void Transmit(void)
{
    int i = 0;

    while(data[i] != 0)
    {
        while (!(UCSR0A & (1 << UDRE0)));
        UDR0 = data[i]; 
        i++;
    }

    _delay_ms(100);
}

I can send data without problem, but I can't receive correct data. If I send "A", I receive ASCII code 161 or 225 and with "B", 162 or 226. I don't understand where the problem is.

For tests I'm using Arduino Uno (ATmega328P 16MHz).

Best Answer

The baud rate is on the edge of accepted tolerance, so change to 38400 BPS. Try different terminal program which can send capital and non-capital letters properly.