The baud rate for the receiver and transmitter (RX and Tx) is both set to the same value
As programmed in the mantissa and fraction values of usartdiv.
As can be seen, the register is 16 bits high, the minimum 4 bits is the fractional part, the remainder is the integer part.
Such a design can make the baud rate more accurate. With regard to the generation of baud rate, there is a passage to explain:
The fractional baud rate is generated: both the receiver and transmitter (RX and TX) are set to the values configured in the Usartdiv integer and decimal registers.
This give the following equation for baud rate:
Tx/rx baud = CK_APB1/(8 x (2-over8) x usartdiv)
Where Usartdiv is a unsigned fixed point number, which is coded on the USART_BRR register.
- When Over8=0, the fractional part was coded on 4 bits and programmed by the div_fraction[3:0] bits in the USART_BR R Register
- Tx/rx baud = CK_APB1/(x usartdiv)
- When Over8=1, the fractional part was coded on 3 bits and programmed by the div_fraction[2:0] bits in the USART_BR R Register,
- and bit div_fraction[3] must be kept cleared.
- Tx/rx baud = CK_APB1/(8 x Usartdiv)
The baud counters is updated to the new value of the baud registers after a write operation to USART_BRR.
Hence the baud rate register value should isn't be changed during communication.
The usarts is on the APB1 bus, with the figure of the reference manual is the clock tree,
Which shows how the APB1 clock was derived from the PLL clock.
The maximum APB1 clock is 32MHz.
Over8=1 is required for higher speeds, Giving:baud = 32000000/(Usartdiv x 8).
So usartdiv = 32000000/(baud x 8)
For 4Mbps Therefore, usartdiv=1 (see table 138 s.no.12 for details).
For 2Mps, usartdiv=2.
To achieve 3Mbps you'll have to reduce the APB1 clock to 24MHz and set usartdiv=1 (see table 131).
But note, the clock rate changes for all other APB1 peripherals too.
The simplest-correctly program the USART baud rate is via the STM32L1XX standard Peripheral library.
Also to determine the correct peripheral clock settings (and more), and generate Initialisation code,
You can use the STM ' s Microxplorer tool.
FPCLK = Baud = 460800 Bps:over8 = 0
DIV = 12000000/(460800) = 1. 6276
Div_mantissa = 1
Div_fraction = 0.6276 * 16 = 10
Usartdiv = (1 << 4) | Ten = 0x001 A = 1.625
12000000/(1.625) = 12000000/26 = 461538.5 Bps
FPCLK = Baud = 460800 Bps:over8 = 1
DIV = 12000000/(8 * 460800) = 3. 255
Div_mantissa = 3
Div_fraction = 0.255 * 8 = 2.04
Usartdiv = (3 << 4) | 2 = 0x003 2 = 3.25
12000000/(8 * 3.25) = 12000000/26 = 461538.5 Bps
Stm32 baud rate setting, at 115200, the actual is 115384, there will be 0.15% error, but still acceptable.
In fact, the Stm32 UART is quite simple, initialize 4 registers done, is the baud rate needs to calculate. Original:
Stm32 The following formula is available in the Chinese literature:
Tx/rx baud rate = fpclkx/(16*USARTDIV);
The Fpclkx (X=1, 2) Here is the clock for the peripheral (PCLK1 for USART2, 3, 4, 5,PCLK2 for USART1)
Usartdiv is an unsigned fixed-point number. This 12-bit value is set in the USART_BRR register.
If you use USART1, the system clock uses the PCLK2 clock for 72mhz,usart1, which is also defined as 72MHz.
Define baud rate =9600,fpclk2=72mhz, then: Calculate usartdiv=72mhz/9600/16=468.75
Take an integer 468=0x1d4. Decimal 0.75*16=12=0x0c. So the value in the Write register USART_BRR is: usart_brr=0x1d4c.
If the PCLK1 clock is used with USART2,USART2, the PCLK1 clock is 36MHz.
Define baud rate =9600,fpclk1=36mhz, then: Calculate usartdiv=36mhz/9600/16=234.375
Take an integer 234=0xea. Decimal 0.375*16=6=0x06. So the value in the Write register USART_BRR is: Usart_brr=0xea6.
24000000 / 19200 = 1250 = 0x4E2 --> 78 + 2/16 = 78.125
24000000 / ( 16 * 19200 ) = 78.125
24000000 / 921600 = 26 = 0x1A --> 1 + 10/16 = 1.625
24000000 / ( 16 * 921600 ) = 1.625
uint32_t Tmpreg = 0x00, Apbclock = 0x00;
uint64_t Integerdivider = 0x00;
uint32_t fractionaldivider = 0x00;
/* Determine the integer part */
if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
{
/* Integer part computing in case Oversampling mode is 8 Samples */
integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate)));
// ( 2^^32 - 1 ) / 25 = 4294967295 / 25 = 171798691.84 = 171.8 MHZ
// STM32F429 MAX 180MHz
}
else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
{
/* Integer part computing in case Oversampling mode is 16 Samples */
integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));
}
tmpreg = (integerdivider / 100) << 4;
/* Determine the fractional part */
fractionaldivider = integerdivider - (100 * (tmpreg >> 4));
/* Implement the fractional part in the register */
if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
{
tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
}
else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
{
tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
}
/* Write to USART BRR register */
USARTx->BRR = (uint16_t)tmpreg;
(1) the calculated usartdiv is enlarged by 100 times times the reserved integer part.
(2) More than hundred into the brr[15:4], the hundred below the conversion into 16 binary values into [3:0]
That is, for the Usartdiv fractional part, only two digits after the decimal point is reserved, two after the whole of the shed,
For example, the theoretical calculation of Usartdiv = 234.28125 is treated as Usartdiv = 234.28, which results in loss of precision,
The actual value of the final feed brr is not rounded off the theoretical value (more than 5 may also be shed)
For precise results that fully conform to the rounding principle, the usart should be at least 100,000 times times larger,
Keep the 5 digits after the decimal point, and the rest of the 5 digits will still fall within the correct interval. The new program is as follows:
baudsource = apbclock * 100000 / ( 16 * BaudRate );
interger = baudsource / 100000;
fractional = ( baudsource % 100000 + 3125 ) / 6250;
USART1->BRR = ( interger << 4 ) + fractional;
Illustrated by an example: if the baud rate is set to baud rates = 19207 bps
72000000 - 19207 234.28958192325714583224865934295...
(1) brr[3:0] Theoretical value: 16 * 0.28958192325714583224865934295 ... = 4.6333107721143333159785494871661 ...
Take brr[3:0 by rounding principle] = 0x05
(2) Official library: (* + +)/+ = 498/100 = 4, brr[3:0] = 0x04 and theoretical value difference 1
(3) New program: (28958 + 3125)/6250 = 32173/6250 = 5, brr[3:0] = 0x05, consistent with theoretical values.
STM32 serial rate: APB speed/baud rate = usartdiv [OVER8 = 0]
uint32_t brr( uint32_t clock, uint32_t baud )
{
uint64_t clock_x_100000 = ( clock * 10000 );
return ( ( clock_x_100000 / baud ) + 5000 ) / 10000;
}
72000000 * 10000/19207 = 37486333
37486333 + 5000 = 37491333 3
7491333/10000 = 3749 = 0x0ea5 to 234.3125
72000000/(* 234.3125 ) = 19205
STM32 baud rate calculation