0

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) :

enter image description here

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));
2
  • how would you do it on paper?
    – jsotola
    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

1 Answer 1

0

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).
3
  • yeah i know for the missing parenthesis and semicolon. just made a wrong ctrl+c ctrl+v.
    – gowb0w
    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
    – gowb0w
    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.
    – gowb0w
    Mar 15 at 13:41

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.