cbit-manipulationuart

UART communication on ATmega32A with PC


I'm a beginner in programming AVR microcontrollers, and I get a lot of headaches sometimes from reading the datasheets.

I'm trying to make a communication between my AVR and PC just to send some characters and receive it on my computer.

There are two lines I don't understand from the whole program and that is:

void USART_init(void)
{
    UBRRH = (uint8_t)(BAUD_PRESCALLER>>8); <---- this one!
    UBRRL = (uint8_t)(BAUD_PRESCALLER); <--- and this one
    UCSRB = (1<<RXEN)|(1<<TXEN);
    UCSRC = (1<<UCSZ0)|(1<<UCSZ1)|(1<<URSEL);
}

Datasheet

Why do I have to shift BAUD_PRESCALLER with 8? If BAUD_PRESCALLER is a number and shifting that number with 8 doesn't mean the result will be zero? (Because we are shifting it too many times)

From the datasheet, I understand that UBRRH contains the four most significant bits and the UBRRL contains the eight least significant bits of the USART baud rate. (Note: UBBR is a 12-bit register)

So how can we actually put all the required numbers in the UBBR register?


Solution

  • You have to shift it right 8 bits, because the result of BAUD_PRESCALLER is larger than 8 bits. Shifting it right 8 bits gives you the most significant byte of a 16-bit value.

    For example, if the value of BAUD_PRESCALAR is 0x123, then 0x1 would be assigned to UBRRH and 0x23 would be assigned to UBRRL.

    If the library was smart, it could also perform sanity checking on the BAUD_PRESCALAR to make sure it fits in 16 bits. If it can't, that means you cannot achieve the baud rate you want given the clock you are using. If you're UBRRx is truly 12 bits, the sanity check would look something like this:

    #if BAUD_PRESCALAR > 0xFFF
    #error Invalid prescaler
    #endif