Electronic – How set the baud rate for serial communication in ATmega32u4

atmegabaudratemicrocontrollerteensyuart

I have a teensy 2.0 board and am trying to use it to control this LCD through serial TTL.

I got it to work fine with my Arduino uno and some sample Arduino code, but I want to do it with the teensy and the C language.

The teensy uses the ATmega32u4 and here is the datasheet for that chip.

In the datasheet, starting on page 186, is the section on USART. On page 192 is some sample C language code on how to initialize the USART. I am confused on a couple of lines and could use some help.

void USART_Init( unsigned int baud )
{
  /* Set baud rate */
  UBRRHn = (unsigned char)(baud>>8);
  UBRRLn = (unsigned char)baud;

  /*rest of code here*/
}

First, I am not clear on what the baud rate number should be. My LCD is calling for 9600 baud with 1 start bit, 1 stop bit, no parity bit, and 8 bits of data. On page 189 of the ATmega32u4's datasheet I did the calculation on what the baud rate should be which in the case of the teensy and LCD combination should be 103 because the chip frequency is 16mhz and the baud rate is 9600. This also matches the number in the chart on page 213 of the ATmega32u4's datasheet. So, is this the correct number that would be passed into the USART_Init function for the variable baud?

I am also confused on the two lines that set the baud rate. I understand that, as per page 209 of the ATmega32u4's datasheet the baud rate registers are broken into a low and high register but only bits 8:10 on the high register are used making it a combined 12-bit register. So, going back to the code, I don't understand some things:

  1. Why is it being typecast to an unsigned char because I am assuming that UBRRHn should be in binary notation.
  2. I also do not understand the (baud>>8) part because if you fill in 103 for baud then you get (103>>8) and that ain't right. Can someone explain this line for me? Thanks.
UBRRHn = (unsigned char)(baud>>8);<br/>
UBRRLn = (unsigned char)baud;
  1. Should baud be the 12 bit binary version of 103 which is 00001100111? If so, then how would the code be written?

Also, I found some sample code(http://www.pjrc.com/teensy/uart.html) on the teensy website that sets up the UART and it sets up the baud rate like this:

void uart_init(uint32_t baud)
{
    cli();
    UBRR1 = (F_CPU / 4 / baud - 1) / 2;

    /*rest of code here*/
}

If I plug in the numbers it would look like this:

UBRR1 = (16000000 / 4 / 9600 - 1) / 2; /* Which would equal 208 */
  1. The number 208 is different than 103 so I don't understand where they are getting the equation to calculate it.
  2. UBRRn is only mentioned in ATmega32u4's datasheet on pages 188 and 189. It looks like that holds the value of both UBRRHn and UBRRLn. The above code seems to be trying to set both at the same time but as an int. I am so confused, doesn't that need to be in binary notation?

Well, I am looking forward to getting over this hump and moving on to making my LCD dance. 🙂

Best Answer

To understand all of this stuff, take a look at "Table 18-1. Equations for Calculating Baud Rate Register Setting" from the datasheet on page 189. The equation you suggested you found in some example code

UBRR1 = (F_CPU / 4 / baud - 1) / 2;

... is kind of close to the equation for Asynchronous Double Speed mode (U2Xn = 1)... but not exactly.

If you know the baud rate and crystal speed you intend to operate at, I would just pull the register settings out of "Table 18-9. Examples of UBRRn Settings for Commonly Used Oscillator Frequencies" on datasheet page 210 and call it a day. The only reason to use any of those equations is if you want to be able to change the settings dynamically at run-time for some reason (or if you want to do thins "elegantly" in software, I prefer compile time certainty for something like this to remove doubt).

For the settings you outlined in your question, that would be:

UCSR1A = 0;                         // importantly U2X1 = 0
UCSR1B = 0;                         // interrupts enabled in here if you like
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); // no parity, 8 data bits, 1 stop bit
UCSR1D = 0;                         // no cts, no rts
UBRR1  = 103;                       // 9600 baud @ 16MHz XTAL with U2X1 = 0    

As a side note, while the hardware does store the baud rate register (UBBRn) as two 8-bit registers, in software there is no need to treat it as such. You can access the High and Low registers (e.g. UBRR1H and UBRR1L respectively) but you can also just assign to (or read from) the named "combined" register as though it was a 16-bit register.

UBRR1 = 0x0343; is functionally equivalent to UBRR1H = 0x03; UBRR1L = 0x43;

Related Topic