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 ) = .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.

 /  =  = 0x4E2 -->  + / = 78.125

 / (  *  ) = 78.125

 /  =  = 0x1A -->  + / = 1.625

 / (  *  ) = 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) != )
{
/* Integer part computing in case Oversampling mode is 8 Samples */
integerdivider
= (( * apbclock) / ( * (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 = (( * apbclock) / ( * (USART_InitStruct->USART_BaudRate)));
}
tmpreg = (integerdivider / ) << ; /* Determine the fractional part */
fractionaldivider = integerdivider - ( * (tmpreg >> )); /* Implement the fractional part in the register */
if ((USARTx->CR1 & USART_CR1_OVER8) != )
{
tmpreg |= ((((fractionaldivider * ) + ) / )) & ((uint8_t)0x07);
}
else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
{
tmpreg |= ((((fractionaldivider * ) + ) / )) & ((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 *  / ( 16 * BaudRate );
interger = baudsource / ;
fractional = ( baudsource % + ) / ;
USART1->BRR = ( interger << ) + fractional;

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

 / (  *  ) = 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 USART_BRR( uint32_t clock, uint32_t baud )
{
uint64_t clcok_x = clock * 10000ULL;
uint64_t brr = ( ( clcok_x / baud ) + 5000ULL ) / 10000ULL;
return brr;
}

72000000 * 10000 / 19207 = 37486333

37486333 + 5000 = 37491333

37491333 / 10000 = 3749 = 0x0EA5 --> 234.3125

72000000 / ( 16 * 234.3125 ) = 19205

#define UART_BRR_SAMPLING16(_PCLK_, _BAUD_)     (((_PCLK_)+(_BAUD_)/2)/_BAUD_)
__INLINE static uint16_t UART_BRR_SAMPLING8(uint32_t _PCLK_, uint32_t _BAUD_)
{
uint16_t Div = (_PCLK_ + _BAUD_/)/_BAUD_;
return ((Div & ~0x7)<< | (Div & 0x07));
}

精度能到多高,由BRR的4bit小数决定了,不管乘多大的数,最终一除还是4bit小数。

理论误差最大就是正负0.5bit了,也就是分频系数的1/32。

如果要保证1%的精度,分频系数>100/32=3.125就够了,一般系统都可以满足。

也就是要么分频系数够大,要么尽量整除,误差就可以满足要求。

如果硬要扯绝对精度,当BAUD为奇数时,除了那0.5bit的误差,

还有因为BAUD/2除不尽再来的误差,也就是1/BAUD bit。

那0.5bit的误差都可以忽略了,1/BAUD bit的误差就更不用提了吧?

而且有谁的系统里波特率是奇数?

PS:我们用的系统都是有限精度系统,只要精度满足要求就行了。

STM32库函数USART波特率计算的奇葩问题

不管乘多大数再除掉,精度不可能超过这个算法:

(PCLK + BAUD/2)/BAUD,

只不过增加运算法。

STM32库函数USART波特率计算的奇葩问题

STM32 USART 波特率计算的更多相关文章

  1. 【原创】STM32下波特率计算详解

    波特率的计算 STM32下的波特率和串口外设时钟息息相关,USART 1的时钟来源于APB2,USART 2-5的时钟来源于APB1.在STM32中,有个波特率寄存器USART_BRR,如下:     ...

  2. 单片机stm32 USART串口实际应用解析

    stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...

  3. USART波特率 vs SPI速率--学习笔记

    本篇文章将与大家探讨USART波特率 vs SPI速率.这里提出一个问题,为什么USART的波特率是内核时钟的1/8或者1/16,而SPI最快的频率可以是内核时钟的1/2. 请大家带着这个问题来阅读本 ...

  4. [stm32] USART USART1收发功能工程

    >_<!功能:PC端发送一个特定的字符:0x0d 0x0a,单片机则返回一句话,如图: >_<!知识: 1.复用功能I/O和调试配置(AFIO)  为了优化外设数目,可以把一些 ...

  5. STM32之串口波特率计算

    1.1 波特率结构框图 1.2 波特率寄存器示意图 1.3 波特率计算公式示意图 两图看出,串口波特率寄存器是一个32位,只用低16位,低16位又划分,低4位用来装小数,其他用来装整数. 波特率计算公 ...

  6. stm32 usart 异步传输示例

    STM32F103xE的USART异步数据传输示例 USART全称Universal Synchronous/Asynchronous Receiver/Transmitter,是一种可以进行同步/异 ...

  7. stm32 USART rs485 rs232

    转载自:http://www.cnblogs.com/chineseboy/archive/2013/03/06/2947173.html 前题: 前段时间,在公司调试了一个项目,很简单,但对于初学的 ...

  8. STM32 CAN 波特率设置及采样点设置

    一.CAN波特率 STM32 位时间定义: ● 同步段(SYNC_SEG):通常期望位的变化发生在该时间段内.其值固定为1个时间单元(1 x tCAN).● 时间段1(BS1):定义采样点的位置.它包 ...

  9. hi3531串口波特率计算

    波特率配置 通过配置寄存器UART_IBRD 和UART_FBRD 可以设置UART 工作的波特率,波特率 计算公式为: 当前波特率=UART 参考时钟频率(1/2 总线时钟频率)/(16 x 分频系 ...

随机推荐

  1. 第9月第6天 push pop动画 生成器模式(BUILDER)

    1. https://github.com/MichaelHuyp/QQNews 2.生成器模式(BUILDER) class MazeBuilder { public: virtual void B ...

  2. Casper带有4个内建记录级别

    默认情况下,CasperJS会在‘error’级别过滤日志.所以如果你开始记录日志后没有看到任何东西,可能就是这个原因.为确保显示日志输出,我把它设置为‘debug’.而且我关闭了‘verbose’选 ...

  3. 分析占用了大量CPU处理时间的是Java进程中哪个线程

    下面是详细步骤: 1. 首先确定进程的 ID ,可以使用 jps -v 或者 top 命令直接查看 2. 查看该进程中哪个线程占用大量 CPU,执行 top -H -p [PID] 结果如下: 可以发 ...

  4. centos6.5环境DNS-本地DNS服务器bind的搭建

    centos6.5环境DNS-本地DNS服务器bind的搭建 域名系统(英文:Domain Name System,缩写:DNS)是因特网的一项服务.它作为将域名和IP地址相互映射的一个分布式数据库, ...

  5. 不借助autolt实现下载文件到指定目录

    今天尝试了下不用借助autolt完成下载文件到指定目录, 好处:在于集成回归,远程机可以绕过执行autolt程序权限问题,导致autolt程序无法调用,不能完成脚本的回归 Firefox浏览器已经成功 ...

  6. 虚拟机 VMware安装系统,提示此主机支持Intel VT-x,但Intel VT-x处于禁用状态

    VMware提示此主机支持Intel VT-x,但Intel VT-x处于禁用状态 VMware提示此主机支持Intel VT-x,但Intel VT-x处于禁用状态这是怎么回事呢? Intel VT ...

  7. extjs6入门:用sencha cmd搭建简单的extjs6项目

    开发准备 1.sencha cmd安装 2.extjs6.0.0 gpl正式版下载,地址:https://www.sencha.com/legal/gpl/ ,解压ext-6.0.0-gpl.zip ...

  8. Android应用--QR的生成(二维码)

    二维码的定义: 二维码(2-dimensional bar code),是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的. 在许多种类的二维条码中,常用的码制 ...

  9. .NetCore源码阅读笔记系列之Security (二) 自定义认证实践

    通过前面对AddCookie 或者 AddOpenIdConnect 等了解,其实里面都实现了一个AuthenticationHandler<TOptions>的认证处理,接下来我们来简单 ...

  10. hdu 5011 nim博弈 (2014西安网赛E题)

    n堆石子,每次可以选一堆取走至少一个,之后你可以不操作或者把该堆石子分成两堆,每堆至少一个,和还是原来(取完石子后)的石子个数. Sample Input1121 131 2 3 Sample Out ...