1
\$\begingroup\$

I want to establish an USART communication between my Atmega32a chip and my computer but there's something I don't understand. As I read the datasheet the UBRR register is a 12 bit register but is split into two 8 bit registers:UBRRH which cointains the four most significant bits and the UBRRL which contains the eight least significant bits of the USART baud rate; My question is:Why I have to shift BAUD_PRESCALLER with 8 at right? I don't understand how this all works :( The example if BAUD_PRESCALLER is 120,in binary it would be:0b01111000 so 0b01111000>>8 = 0b00000000; => Am I wrong somewhere?

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

I will atach the datasheet for UBRR register: enter image description here

\$\endgroup\$
2
  • \$\begingroup\$ Read the implementation of the begin method: github.com/arduino/Arduino/blob/master/hardware/arduino/avr/…, also if you are using avr-gcc there is no need to address UBRR high and low separately. \$\endgroup\$
    – vicatcu
    Commented Mar 18, 2018 at 20:32
  • \$\begingroup\$ Then it should be UBBRL=(uint8_t)BAUD_PRESCALER and UBBRH=(uint8_t)BAUD_PRESCALER>>4 since UBBRL should take 8 least significant bits, and UBBRH takes 4 most significant bits. \$\endgroup\$
    – Abel Tom
    Commented Mar 18, 2018 at 20:35

1 Answer 1

1
\$\begingroup\$

Assume you want a BAUD_PRESCALER = 1024.

The binary representation of 1024 is: 0b00000100 00000000.

I've put a space after 8 bits so that you can distinguish between the 8 least significant bits (LSBs) from the 8 most significant bits (MSBs). In order to configure the UBRR registers, you have to put the 8 MSBs in the UBRRH register, and the 8LSBs in the UBRRL register. To do this, you can simply typecast BAUD_PRESCALER to a uint8_t to get the LSBs:

UBRRL = (uint8_t)(BAUD_PRESCALLER);

This will assign 0b00000000 to UBRRL, since the 8 MSBs will be discarded due to the typecast. Remember, the typecast to uint8_t will only give you the 8 LSBs of whatever number you give it.

Now, for the UBRRH register, you first need to shift the 8 MSBs into the LSBs in order for the typecast to work correctly. So 0b00000100 00000000 must become 0b00000100, hence the right shift by 8 bits:

UBRRH = (uint8_t)(BAUD_PRESCALLER>>8); //Shifts BAUD_PRESCALLER MSBs into the LSBs
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Ohh wow,I understand now :o Thank you very much for the fast response!! <3 \$\endgroup\$ Commented Mar 18, 2018 at 20:53
  • 1
    \$\begingroup\$ Do you know if it's possible to make all these things in one line?Like: UBRR = 1024? Is this correct? \$\endgroup\$ Commented Mar 18, 2018 at 20:57
  • \$\begingroup\$ Sure, it is. The headers define macros to access 2 consecutive registers. In case you are curious, assuming you are in AVR Studio, you can right click any register name in you code, like UBRR, and click "Goto Implementation" to see how this is done :) \$\endgroup\$
    – Chi
    Commented Mar 18, 2018 at 21:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.