码迷,mamicode.com
首页 > 其他好文 > 详细

STM32 波特率计算

时间:2015-07-13 00:37:41      阅读:282      评论:0      收藏:0      [点我收藏+]

标签:

The baud rate for the receiver and transmitter (Rx and Tx) are both set to the same value

as programmed in the Mantissa and Fraction values of USARTDIV.

技术分享

技术分享

从上图可以看出,该寄存器高 16 位无效,最低 4 位为小数部分,其余部分为整数部分。

这样的设计可以使波特率更加精确。关于波特率的产生,有这么一段话来解释:

分数波特率的产生:  接收器和发送器(RX和TX)都是设置成为 USARTDIV 整数和小数寄存器中配置的值。 

This give the following equation for baud rate:

Tx/Rx baud = CK_APB1 / (8 x (2 - OVER8) x USARTDIV)

Where USARTDIV is an unsigned fixed point number that is coded on the USART_BRR register.

  • When OVER8=0, the fractional part is coded on 4 bits and programmed by the DIV_fraction[3:0] bits in the USART_BRR register
  • Tx/Rx baud = CK_APB1 / (16 x USARTDIV)
  • When OVER8=1, the fractional part is coded on 3 bits and programmed by the DIV_fraction[2:0] bits in the USART_BRR register,
    and bit DIV_fraction[3] must be kept cleared.
  • Tx/Rx baud = CK_APB1 / (8  x USARTDIV)

The baud counters are updated to the new value in the baud registers after a write operation to USART_BRR.

Hence the baud rate register value should not be changed during communication.

 

The USARTs are on the APB1 bus, Figure 12 in the reference manual is the clock tree,
which shows how the APB1 clock is 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 will have to reduce the APB1 clock to 24MHz and set USARTDIV=1 (see table 131).

But note that the clock rate changes for all other APB1 peripherals too.

The simplest way to 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 STM‘s MicroXplorer tool.

Fpclk = 12 MHz, Baud = 460800 Bps : OVER8 = 0

DIV = 12000000 / ( 16 * 460800 ) = 1.6276

DIV_Mantissa = 1

DIV_Fraction = 0.6276 * 16 = 10

USARTDIV = ( 1 << 4 ) | 10 = 0x001 A = 1.625

12000000 / ( 16 * 1.625 ) = 12000000 / 26 = 461538.5 Bps

 

Fpclk = 12 MHz, 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波特率设置,在115200时候,实际是115384,会有0.15%的误差, 不过还是可以接受的。

其实stm32的uart还是蛮简单的,初始化4个寄存器完事,就是波特率方面需要算算。 原文:

stm32 中文资料中有如下计算公式 :

Tx / Rx 波特率 = fPCLKx/(16*USARTDIV);

这里的fPCLKx(x=1、2)是给外设的时钟(PCLK1用于USART2、3、4、5,PCLK2用于USART1)

USARTDIV是一个无符号的定点数。这12位的值设置在USART_BRR寄存器。 

如果使用USART1,系统时钟为72MHZ,USART1使用PCLK2时钟,也定义为72MHz.

定义波特率=9600,fPCLK2=72MHz,则: 计算USARTDIV=72MHz/9600/16=468.75

取整数468=0x1D4. 小数0.75*16=12=0x0C. 所以写入寄存器USART_BRR中的值为:USART_BRR=0x1D4C. 

如果使用USART2,USART2使用PCLK1时钟,PCLK1时钟为36MHz.

定义波特率=9600,fPCLK1=36MHz,则: 计算USARTDIV=36MHz/9600/16=234.375

取整数234=0xEA.小数0.375*16=6=0x06.所以写入寄存器USART_BRR中的值为: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)将算出的USARTDIV扩大100倍保留整数部分。

(2)百位以上的送入BRR[15:4],百位以下的换算成16进制值送入[3:0]

也即对于USARTDIV小数部分,只有小数点后两位保留,两位以后的全部舍去,

比如理论计算得到 USARTDIV = 234.28125 被处理为 USARTDIV = 234.28,这样就损失了精度,

造成了最终送入BRR的实际值并不是理论值的四舍五入(5以上的有可能也被舍去)

如想要得到完全符合四舍五入原则的精确结果,则USART至少应该放大 100000 倍,

保留小数点后5位,5位以后的部分全部舍去也仍然落在正确的区间内。新程序如下:

     baudsource = apbclock * 100000 / ( 16 * BaudRate );
     interger = baudsource / 100000;
     fractional = ( baudsource % 100000 + 3125 ) / 6250;
     USART1->BRR = ( interger << 4 ) + fractional;

以一个例子说明:  如设置波特率为Baud Rate = 19207 bps

72000000 / ( 16 * 19207 ) = 234.28958192325714583224865934295...

 (1) BRR[3:0]理论值:16 * 0.28958192325714583224865934295... = 4.6333107721143333159785494871661... 

按四舍五入的原则取 BRR[3:0] = 0x05

(2)官方库:( 28 * 16 + 50 ) / 100 = 498 / 100 = 4, BRR[3:0] = 0x04 与理论值差1

(3) 新程序:( 28958 + 3125 ) / 6250 = 32173 / 6250 = 5, BRR[3:0] = 0x05,与理论值一致。 

STM32的串口速率:APB速度/波特率 = 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 --> 234.3125

72000000 / ( 16 * 234.3125 ) = 19205 

 

STM32 波特率计算

标签:

原文地址:http://www.cnblogs.com/shangdawei/p/4641805.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!