引言

    在实际项目大批量生产调试设备时,笔者发现同样版本的程序在不同设备上运行时效果不一致,一部分设备串口通信正常,另外一部分串口通信不正常。通过示波器对多个设备的串口波特率及系统时钟频率测试,发现不同设备之间的系统时钟频率及波特率存在差异,与理论值不一致,用示波器测试出的系统时钟频率及波特率与理论值偏差较大。由于系统时钟频率的偏差导致波特率设置值超过了串口所允许的最大误差值,故而导致串口通信失败。其根本原因是系统的时钟频率会随环境温度、电压或其他因素变化。



1 原因分析

    
在异步通信中,波特率是很重要的指标,表示为每秒传送二进制数码的位数,反映了异步串行通信的速度。MSP430的波特率发生器使用一个分频计数器和一个调整器来构成分频因子,此方法能够用较低时钟频率实现高速通信,从而在系统低功耗的情况下,实现高性能的串行通信。MSP430波特率发生器的时钟源可以为通用时钟(Universal Clock,UCLK)、辅助时钟(Auxiliary Clock,ACLK),子系统时钟Subsystem Master Clock,SMCLK)。其中,ACLK通常为32
768 Hz,稳定但无法满足高速串口通信;SMCLK为可配置的系统频率,可满足高速串口通信,但不稳定。SMCLK是由数字控制振荡器(Digitallycontrolled Oscillator,DCO)的调节器模块混合两个频率Fdco和Fdco+,用以产生介于Fdco和Fdco+1之间的频率。从本质上来说,这种调制将时钟能量扩散到一个宽带中,减少了电磁干扰(EMI)。但这样得到的平均频率的调制时钟,其负面影响的表现形式就是频率的抖动。

    DCO频率会随着温度和电压的变化而有所波动,在fDCO=1 MHz时,飘移频率随漂移温度变化的比例为0.1%/℃,飘移频率随漂移电压变化的比例为1.9%/V。因此使用SMCLK作为串口时钟源时,用理论频率计算的分频因子和实际频率分频因子有差异,导致串口无法通信。



2 解决方案

2.1 方案1——自动波特率检测模式

    
MSP430串口通信支持自动波特率检测,在这种通信模式下,在数据帧前面会有一个包含打断/同步域的同步序列,如图1所示。为了LIN的一致性,该模式下字符格式应为8个数据位,低位优先,没有奇偶校验位和停止位,且地址位不可用。在接收打断/同步域时,串口是不能发送数据的,如果在帧错误下接收到一个0H字节,那么此时发送的任何数据都会遭到破坏。由此可见其通信过程较复杂,使用不便。

2.2 方案2——外接高频晶振

    
MSP430可外接稳定的高速晶振,但该系列芯片设计为超低功耗的单片机,如外接高频晶振,与该系列低功耗设计理念相违背。即MCU进入低功耗模式(Low-Power Mode,LPM)下晶振并不进入低功耗模式,且会一直耗电,因此会增加系统的耗电量,减少续航时间。

2.3 方案3——根据时钟源自动计算波特率

    可使用内部低频晶振,通常为32 768 Hz。经过DCO调节器,产生较高的可供串口高速通信的频率FSMCLK。该频率是由DCO调节器模块在32个DCO时钟周期内混合Fdco和Fdco+1产生的介于Fdco和Fdco+1之间的频率,该调节模式从本质上减小了电磁干扰。并且FSMCLK会在MCU进入LPM模式后自动关闭以节电,直至MCU退出低功耗模式。得到高频时钟后,可通过两个定时器精准计算出FSMCLK,并根据该值设置波特率,此方法可消除器件差异性,以保证单片机串口在不同温度和电压下正常工作。该方案简单、易实现、抗电磁干扰强、省电效果好,并且从一定程度上消除了系统频率随温度、电压变化所带来的影响。该方案优于方案1和方案2;其实现流程如图2所示。

3 系统工作频率计算

    对于定时器A0,其时钟源频率为F0,使定时器A0工作在计数器模式下并设置每计数T0次产生一次中断,即每中断一次的时间t0为:

    

    对于定时器A1,其时钟源频率为F1,使定时器A1工作在计数器模式下并设置每计数T1次产生一次中断,即每中断一次的时问t1为:

    





4 波特率设置

    对于给定串口时钟源BRCLK,分频因子N满足:

    N=BRCLK/Baudrate

    分频因子N常常不是整数,因此,至少需要一个分频计数器和一个调整器来产生一个近似于分频因子N的数。

    在低频模式下,整数部分分频因子满足:

    UCBRx=INT(N)

    且分数部分满足下列公式:

    UCBRSx=round[(N-INT(N))×8]

    设置波特率程序如下:

    division_factor=f_smclk/(Baudrate*1.0);

    UCA0BR0=(int)division_factor;

    UCA0BR1=((int)division_factor)>>8;

    UCA0MCTL|=(int)((division_factor_(int)division_factor)*8);



5 方案验证

    如方案3所述,先测出串口时钟源的当前频率,再根据该频率设置波特率寄存器及调整器的值。将修改后的程序下载到串口能通信和串口不能通信的多个设备进行验证。通过示波器测试发现,被测设备的时钟频率存在差异,各设备之间的频率不一定相同,同时发现串口的实际波特率与理论波特率一致,其表现形式为串口能正常通信。至此,方案3通过验证,该方案可有效避免因串口时钟源时钟偏移导致不能通信的问题。



结语

    实践证明,计算出内部时钟经过倍频后的高频时钟,再根据该时钟频率设置串口波特率的方法可行。该方法从纯软件的角度有效地解决了单片机内部时钟频率不稳定,单片机因环境温度、气压、电磁等导致系统时钟频率偏差,以及单片机器件之间的差异性等因素导致串口通信失败的问题。

MSP430精准配置高速串口波特率的方法的更多相关文章

  1. MSP430设置串口波特率的方法

    给定一个BRCLK时钟源,波特率用来决定需要分频的因子N:               N = fBRCLK/Baudrate 分频因子N通常是非整数值,因此至少一个分频器和一个调制阶段用来尽可能的接 ...

  2. 痞子衡嵌入式:在串口波特率识别实例里逐步展示i.MXRT上提升代码执行性能的十八般武艺

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在串口波特率识别实例里逐步展示i.MXRT上提升代码执行性能的十八般武艺. 恩智浦 MCU SE 团队近期一直在加班加点赶 SBL 项目 ...

  3. 3、CC2541芯片中级教程-OSAL操作系统(ADC光敏电阻和修改串口波特率)

    本文根据一周CC2541笔记汇总得来—— 适合概览和知识快速索引—— 全部链接: 中级教程-OSAL操作系统\OSAL操作系统-实验01 OSAL初探 [插入]SourceInsight-工程建立方法 ...

  4. #51单片机#蓝牙模块(ATK-SPP-HC06从机串口)的使用方法

    #include <AT89X51.H> #include <intrins.h> // 函数原形定义 #define uchar unsigned char #define ...

  5. FPGA小白学习之路(6)串口波特率问题的处理

    串口波特率问题的处理 此博文一共包含三个方面的内容:(1)异步串口通信的数据格式:(2)为何串口通信中接收端采样时钟频率是传输的波特率的16倍:(3)串口波特率等概念. 1.异步串口通信的数据格式 串 ...

  6. 使用 VSCode 给STM32配置一个串口 printf 工程

    使用 VSCode 给STM32配置一个串口 printf 工程 gcc 重定向 printf 和 keil 不一样. 文件准备 先从以前的工程中拷过一份串口的代码来,然后在 main 函数中初始化串 ...

  7. 【系统Configmachine.config与自己的应用程序的App.config/Web.Config配置节点重复】解决方法

    自己的应用程序的App.config或Web.Config文件中与系统的C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Configmachine.co ...

  8. 配置本地yum源的方法

    配置本地yum源的方法 1. 挂载光驱 如果是上传iso镜像到服务器上,则直接挂载iso镜像即可: #mount -o loop -t iso9660 /xxxx.iso /挂载目录 开机自动加载#v ...

  9. 【转】Win7下VS2010中配置Opencv2.4.4的方法(32位和64位都有效)(亲测成功)

    在vs2010下配置opencv是件痛苦的事情,一点点错误可能就会导致莫名其妙的报错,各种error让人郁闷不已,这里提供给大家一篇vs2010下配置opencv2.4.4的方法,我是64位的win7 ...

随机推荐

  1. openfire源码修改聊天消息发送内容

    /** * $RCSfile: MessageRouter.java,v $ * $Revision: 3007 $ * $Date: 2005-10-31 13:29:25 -0300 (Mon, ...

  2. 页面加载后resize页面布局

    在我们写web的时候,有的时候页面加载完以后,布局位置有一些问题,手动改变窗口大小后则正常显示位置. 其实,我们手动改变窗口大小,是执行了resize方法. share一下兼容方法: coffee c ...

  3. 分部类(partial)

    一般来说,一个类.结构或接口位于一个源文件中,但某些情况,比如大型项目.特殊部署时,可能需要把一个类.结构或接口放在几个文件中来处理.等到编译时,自动把它们合起来,这就得应用 C# 分部类了. C# ...

  4. CSS实现垂直居中

    Hack技术就可以啊!所以在这里我还要啰嗦两句,CSS中的确是有vertical-align属性,但是它只对(X)HTML元素中拥有valign特性的元素才生效,例如表格元素中的<td>. ...

  5. Construct Binary Tree from Preorder and Inorder Traversal [LeetCode]

    Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that ...

  6. HTML 折行 <br/>标签

    定义和用法: <br/>可插入一个简单的换行符. br标签是单独出现的,<br /> 当使用br标签时,其后面的所有内容都将在下一行出现 属性 Common -- 一般属性 c ...

  7. java 代理的三种实现方式

    Java 代理模式有如下几种实现方式: 1.静态代理. 2.JDK动态代理. 3.CGLIB动态代理. 示例,有一个打招呼的接口.分别有两个实现,说hello,和握手.代码如下. 接口: public ...

  8. DataTable 导到Excel

    /// <summary> /// 将DataTalbe导出到Excel中 /// </summary> /// <param name="dt"&g ...

  9. 循环报数 Java实现

    输入1个数字和多个字符,中间均以空格隔开.假设数字取值为m(范围1~9),后面字符个数为n.假设n个字符围成一圈,从第一个字母开始循环报数,当数到m以后,第m个字母就出列,直到这n个字母全部出列.最后 ...

  10. poj 2777

    题意:两个操作:c l r x   l到r之间的颜色变成x q l r      询问l到r有多少种颜色 思路:记一个整数表示哪种颜色是否取了 这里真的是煞笔了,看到这一题第一直觉是异或,但是A^A= ...