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?jsotola– jsotola2024年03月14日 19:11:16 +00:00Commented Mar 14, 2024 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.the busybee– the busybee2024年03月15日 06:50:59 +00:00Commented Mar 15, 2024 at 6:50
1 Answer 1
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 forunsigned 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.gowb0w– gowb0w2024年03月15日 09:43:24 +00:00Commented Mar 15, 2024 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 meangowb0w– gowb0w2024年03月15日 10:06:47 +00:00Commented Mar 15, 2024 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– gowb0w2024年03月15日 13:41:40 +00:00Commented Mar 15, 2024 at 13:41