2018-01-16 09:27 AM
Why do we need to calculate the baudrate using this formula,
baud = fCK / (16*USARTDIV)
I mean, why can't we write 9600 or any other desired baudrate value directly in USART_BRR register? Why do we need to perform this calculation first. What are we calculating here anyway?
This might be a dumb question to ask, but I am really confused here. Please help.
Thanks in advance!
#uart #uart-ft-serial-communications #stm32f103rb #usart2018-01-16 09:38 AM
You want the register to be simple and the logic in silicon to be uncomplicated.
A counter is simple, you count clock pulses and you create a divider.
Doing immediate division with logic is complicated, the ALU already has logic to do this, and the synchronous design uses clocks, these clocks may be different from implementation to implementation. ie you might run the CPU at 72 MHz, others may need it to run at 64 MHz, or slow down to 8 MHz
The design will therefore focused on things that make it simple for the machine, not those that make it convenient for the human.
The BRR uses a fractional form, it clocks at a higher rate, and then a clock tap is taken out at the fourth bit, achieving a DIV16, ie 4 -bits can represent 16 states (0000..1111)
2018-01-16 12:40 PM
What is the reason of multiplying
USARTDIV
by 16 in the formula?2018-01-16 01:58 PM
Because the USART is sampling at 16 times the baud rate, and the synchronizer tries to align the data sample point for the BIT in the centre of the bit time. If this is confusing please review classical documentation related to UART implementations, ie something like an 8250, 16550 or 6580, or course note on computer peripheral design/function.
And for the same reason as
frequency = 1 / period
and
period = 1 / frequency
The USART doesn't think of things in terms of baud rate, but rather in clock ticks of the bus clock. The part doesn't 'know' what frequency it is clocking at, it just sees the clock signal going up and down, and the flip-flops change at the rising edge of the clock.
brr = (APBCLK / 16) / baud // what you're actually computing, ie the reverse of pulling the baud rate by knowing the brr and input clock source
brr = (72,000,000 / 16) / 9600
brr = 468.75 // the rate in a fractional sense in OVER16 mode
USART->BRR = (unsigned)(468.75 * 16.0); // fixed point 12.4 representation of fractional rate
USART->BRR = 7500
Or a more trivial computation
USART->BRR = APBCLK / baud;