# Serial com register formula

i am working on a atmega328p, learning to uses its registers instead a coding with common arduino code.

i've found this formula to get the baud rate on the Serial port (using USART protocol) :

how could i type this in C language ? or specifically in the arduino IDE ?

--

i made some researches and discovered that it could write it that way :

``````float _baudrate = (16000000/(16*9600));
``````

then i convert the value to int (because i need an integer value)

``````int _baudrate_int = (int)_baudrate;enter code here
``````

all this for a 9600 baudrate of course.

But when i do this, i don't understand why, the code does not calculate it right. i'm supposed to have 103-104 and i get 710.

it will work if i type (16*9600) product manually. Which is 153600

``````float _baudrate = (16000000/153600);
``````

then i get the right baudrate result. but what if i want the code to calculate everything ? how can i do ?

where's my mistake with this line of code ?

``````float _baudrate = (16000000/(16*9600));
``````
• how would you do it on paper? Mar 14 at 19:11
• Welcome to SE/Arduino! Please take the tour to learn how this site works, and read "How to Ask". Then come back and edit your question to provide the source you have so far. Please add where specifically you are stumbling. BTW, general C questions are better asked on Stack Overflow, especially if they don't have a relation to Arduino. But it is fine here, since you are asking about the Arduino IDE. Are you aware that you are programming C++ if you use the Arduino IDE? C++ and C are different languages. Mar 15 at 6:50

Here:

``````float _baudrate = (16000000/(16*9600)
``````

other than the missing parenthesis and semicolon, you have an integer overflow. The issue is that, on AVR-based Arduinos, an `int` is only 16-bits long. The constants `16` and `9600` being small enough to fit in an `int`, they are implicitly given the `int` type. Then, their multiplication is also done with the `int` type, and the product overflows and wraps modulo 216 to 22528.

You can fix this by giving either or both of these numbers the `L` suffix, which will make them use the `long` data type. Alternatively, if you want a floating point calculation, you can use `.0` as a suffix.

Not that the avr-libc provides a header file with some macros for this calculation, which is then done by the preprocessor: <util/setbaud.h>: Helper macros for baud rate calculations. You can use them as follows:

``````#define BAUD 9600
#include <util/setbaud.h>

void set_baud_rate() {
UBRR0 = UBRR_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~_BV(U2X0);
#endif
}
``````

Edit:

To answer the question in a comment: yes, the `L` suffix creates a `long` constant, and is thus similar to creating a `long` variable (except it is a constant instead of a variable).

I suggest you take a look at the line below from setbaud.h. In the case where U2X0 is not needed, the baud rate register value is computed as:

``````#define UBRR_VALUE (((F_CPU) + 8UL * (BAUD)) / (16UL * (BAUD)) -1UL)
``````

A few things to note:

• It is all computed with integers, no floating point. Actually, the computation is performed by the compiler, at build time, not by the Arduino.
• The suffix `UL` is for `unsigned long`
• Adding 8 before dividing by 16 is a way to round the result to the nearest integer, instead of rounding to zero. Ties are rounded up.
• There is `-1UL` at the end, as this is required by the UART hardware (it is in the formula from the datasheet).
• yeah i know for the missing parenthesis and semicolon. just made a wrong ctrl+c ctrl+v. Mar 15 at 9:43
• I added the L suffix and it worked. impressive, it works ! and i understand what you explained and the fact it will make them use long data type. i have an other little question : is putting the L suffix the same that doing an other variable and make it = (long)variable ? if you see what i mean Mar 15 at 10:06
• yes i understand. the same formula with a 8-addition and giving it long type before rounding it and converting to integer. Mar 15 at 13:41