引言

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



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. linux驱动初探之字符驱动

    关键字:字符驱动.动态生成设备节点.helloworld linux驱动编程,个人觉得第一件事就是配置好平台文件,这里以字符设备,也就是传说中的helloworld为例~ 此驱动程序基于linux3. ...

  2. 最短路径——Floyd算法

    如何求一张图中任意两顶点之间的最短路径长度,这里写一种最简单的算法——Floyd算法: #include<stdio.h> #define inf 9999 int main() { ][ ...

  3. Java之美[从菜鸟到高手演变]之设计模式

    设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  4. Android 之 Activity的生命周期

  5. MVC发布问题(一直显示目录浏览)

    写了一个MVC的Demo,发布之后一直显示目录浏览,始终无法展示网站. 步骤如下: 1.生成解决方案,发布应用程序 2.打开IIS,新建网站,选择发布程序的代码路径 3.设置应用程序池为4.0,集成 ...

  6. Intellij快捷键

  7. iOS开发多线程篇—NSOperation基本操作

    iOS开发多线程篇—NSOperation基本操作 一.并发数 (1)并发数:同时执⾏行的任务数.比如,同时开3个线程执行3个任务,并发数就是3 (2)最大并发数:同一时间最多只能执行的任务的个数. ...

  8. BestCoder Round #39

    -------好久没更新博客了,发现还是需要不断总结才能进步,所以还是把最近打的一些比赛记录一下. T1:Delete (hdu 5210) 题目大意: 给出n个数,然后要删掉k个,要求剩下的数中 不 ...

  9. 解决 iOS7 通过tag 找不到 UITableViewCell 的子控件

    当iOS7问世,程序的世界就混乱了,以前良好的程序,现在是一塌糊涂,于是只能把问题一个一个攻破. 由于项目当中需要每个cell显示数目不同的图片,于是我在每个cell 赋值之前,通过一下方法把cell ...

  10. HDFS中的checkpoint( 检查点 )的问题

    1.问题的描述 由于某种原因,需要在原来已经部署了Cloudera CDH集群上重新部署,重新部署之后,启动集群,由于Cloudera Manager 会默认设置dfs.namenode.checkp ...