你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

教你怎么测量实际的波特率

[复制链接]
eefishing 发布时间:2020-2-25 23:55
平时使用串口打印出现乱码的绝大部分原因是串口波特率没对。那么我们怎么测量实际的波特率呢?在这之前,顺便一起回顾一下波特率的概念。
1 [! ]$ B/ Y; a8 u
什么是波特率、比特率?
比特率(Bitrate)表示每秒钟传输的二进制位数,单位为比特每秒(bit/s)。
& c- l/ |& S1 ^) v
波特率(Baudrate)表示每秒钟传送的码元符号的个数,是衡量数据传送速率的指标。

/ Q8 P. q4 H5 m2 R6 S% {码元是通讯信号调制的概念,通讯中常用时间间隔相同的符号来表示一个二进制数字,这样的信号称为码元。
! S+ n8 l4 D' K# P9 V" I& ?: r
常见的通讯传输中,用 0V 表示数字 0, 5V 表示数字 1,那么一个码元可以表示两种状态 0 和 1,所以一个码元等于一个二进制比特位,此时波特率的大小与比特率一致。

9 r; @8 ~; |4 r+ |* c) o! G, a& A如果在通讯传输中,有 0V、2V、 4V 以及 6V 分别表示二进制数 00、 01、 10、 11,那么每个码元可以表示四种状态,即两个二进制比特位,所以码元数是二进制比特位数的一半,这个时候的波特率为比特率的一半。
% I5 E: b; `. U2 A: d0 @' i
因为很多常见的通讯(比如串口通讯)中一个码元都是表示两种状态,所以大家常常直接以波特率来表示比特率 。
4 d* V1 e8 l7 @5 C9 J8 h9 `7 s
串口通讯协议
在串口通讯的协议层中,规定了数据包的内容,它由启始位、主体数据、校验位以及停止位组成,通讯双方的数据包格式要约定一致才能正常收发数据,其数据帧组成如下:

5 G$ ]7 e( U0 L# _
6 ?1 {9 R% y/ A+ N( J" L( F
下面我们来实际验证一下其数据帧是不是真的是这样的。编写如下代码:
3 D3 C9 p+ E8 a
5 O; f/ y& h' f
代码很简单,就是使用串口不断地往外发数据 0xAA(当然发送其它数据也是可以的)  。我们的串口配置如下:
2 E' A. b% A3 R+ E2 k

5 ~# V6 I) {) q3 w0 p5 Q
我们可以使用示波器或者逻辑分析仪抓取实际信号看看数据是不是符合上面的帧格式。这里,我们使用逻辑分析仪抓取 USART1 的发送信号线(TX):
: A. i3 {( B! H! Y% ]
3 z( \: R9 `$ @; }  j2 Q6 z
从实际结果中我们可以看到的确是按帧格式来发的。这里可能会有人有疑问,上面那个数据帧的图片中有个空闲状态,这个又是什么呢?空闲、空闲,当然是没有在发数据时候的状态呀,我们把我们的代码改为:

7 x0 f, v: l4 i+ A" h3 m) G

5 c. L1 ~' l8 j& `
在初始化完成之后只发送一次 0xAA,逻辑分析仪抓到的数据为:
6 T4 K* i+ ~  ]& X/ l
5 z- z: ]' e3 s2 |) {9 i% c1 n
可见,空闲状态是个高电平。在上一个的范例中,我们一直在 while 循环中发送数据 0xAA,所以就没有空闲状态。
3 c. G/ w; P4 @7 l! I7 E
在这个实验中我们需要知道的是两个点是:

8 i2 r9 s0 n4 ^2 X2 ~: z3 y  z串口发送数据是低位先发的。我们单片机发 0xAA(10101010B),所以逻辑分析仪抓到的有效数据是 01010101B。
2 l+ ~  N; B- @9 w
单片机的串口使用的是 TTL 电平,为正逻辑电平信号。逻辑分析仪抓到的数据 0 对应着实际电压 0~0.5V,数据 1 对应着实际电压 2.4V-5V,
8 t1 F$ }7 _9 x$ A1 |; a1 z
经常与 TTL 电平标准做对比的是 RS-232 电平标准,如:

, g$ M# L* I4 T3 S5 G3 n& g$ K
& i/ t" N+ ]' |6 S3 i, v1 \
常见的电子电路中常使用 TTL 的电平标准,理想状态下,使用 5V 表示二进制逻辑 1,使用 0V 表示逻辑 0;而为了增加串口通讯的远距离传输及抗干扰能力,RS-232 电平标准使用 -15V 表示逻辑 1, +15V 表示逻辑 0。

7 G7 z( }4 ^9 e. h3 u在旧式的台式计算机中一般会有 RS-232 标准的 COM 口(也称 DB9 接口)  :
- B  m  O! V. R7 m
8 K6 @; }& Q; j2 I$ |+ `
在这个示例程序中,我们设置的串口波特率为 115200bps。在串口通讯中,码元只用 1 个二进制数来表示(即只有 0 和 1 两种状态),所以波特率与比特率在数值上是相等的。
- |. t1 C9 O, N" @  n
而比特率表示的是每秒钟传输的二进制位数,那我们知道传一位数据的时间岂不是就可以反推出波特率是多少了吗?从逻辑分析仪中,我们可以知道发送一位数据的时间如下:
: ?1 T/ g6 C, V$ y4 N3 J+ H) A
! P+ k, W2 O; }. {4 X$ f3 h: x
发送一位数据的时间大约为 8.667us,所以 1 秒钟发送多少位数据是可以算出来的:
& H0 F% e; u& r
: J# k& ?" h- O9 z: l2 i9 a
算出来的波特率为 115380bps,与 115200bps 很相近。最终肯定是有一定的误差,这个误差产生的原因包括逻辑分析仪的质量及我们的测量环境等等因素。但是这个误差也是在允许的范围内的,可以看看串口助手接收到的数据是不是正确的:

  v* ^( e$ t0 l% u) n" Y4 ~! C( a
/ Q6 t* L' q7 a6 w1 |- l- [7 l1 i
可见,数据接收正确,也就是波特率对的上了。

1 \8 A' a9 ?- P串口波特率对不上怎么解决?
在实际中。我们可能会遇到这样的情况,代码里配置的波特率与串口助手上设置的波特率一样了,但还是出现异常情况。

3 ?  Q4 c" y3 G, b异常情况如我们往串口助手发送字符串,串口助手上本该显示的字符串出现了乱码。或者我们往串口助手发送一个数据,发现数据移位了。
) }6 S3 ], ?# J6 K
出这种情况大多是波特率对应不上,我们就得自己检查我们的底层文件了,代码中的某个与波特率计算相关的值(时钟)与实际不匹配了,就会出现这样的现象,比如之前我的一位同事就遇到这样的情况就是这个原因导致的。
* c5 T0 d& Q  i' ?7 U7 j9 m% }2 A# x
我们用 STM32 的时候,一般都是使用外部晶振,比如 STM32F103 系列,可输入的外部晶振的范围是 4~16MHz:

+ a9 n" i& J/ Y# w0 J. Q

3 }0 g7 u4 t) K5 `6 D: P% u* l# i经验值往往是 8MHz,而且一般的 demo 工程底层代码里默认的也是设置为 8MHz,比如:

4 i& N: l5 A& n
. C0 j! n( [( ]5 C
但是,如果实际晶振贴的不是 8M 的话,就出问题了(比如串口波特率就不正确了)。追根溯源,串口波特率是配进 USART_Init 函数中的,打开这个函数:

6 n6 p4 L5 F) [' Z5 o7 M

5 P; F2 T: N8 K; n) f. V4 O计算串口波特率需要一个 apbclock 变量,而这个值得来源从 RCC_GetClocksFreq 函数来,再打开这个函数:
+ Y4 e! h6 c5 o2 |7 a; N

6 Y5 V: U9 E- O2 r所以要注意的是,HSE_VALUE 这个值要与实际做对应。

' ]: ]. [: b  g) b. {( K1 Q$ o1 _遇到这种问题找谁说理去。。经验就是不断采坑不断积累的一个过程,早点遇到坑可能也是一件好事。像类似底层的问题很少遇到,但是一旦遇到那就得比较棘手的问题了,需要很有耐心地去查找。
$ m- Z* N8 K- o3 p
能用稳定的芯片是一件很幸福的事情,用不稳定、不成熟的芯片的时候,那个才是真的难啊,遇到问题真是让人怀疑人生啊,软件、硬件、芯片都可能有问题。
赞 收藏 1 评论0 发布时间:2020-2-25 23:55

举报

0个回答

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版