异步通信SCI/UART大概是我们最最最常用的外设了吧(无以言表,只能用连续三个最来表示了),呵呵,目前绝大数的应用都离不开串口,串口配置简单,使用方便,家喻户晓,“居家旅行”必备工具啊,呵呵。至于具体的应用我这里就不一一举例了,这个大家几乎张口就来了。本篇博客的主要内容是想聊一聊串口初始化时波特率的计算问题,下面走起~
现在的单片机开发者几乎习惯了各种函数封装库(无论是官方的还是第三方的,这一点,其中利弊一直众说纷纭,定论不一,虽然简化了上手难度,但是过度的封装也的确弱化了开发者对底层的认识,个人觉着对硬件开发者来说长期来看不是一件好事),说到这我突然联想到一个值得思考的问题(思维有点发散哈,呵呵),现在受国内大环境的影响,一个产品的开发周期越来越被压缩(这点在深圳北京等一线城市尤为明显,因为时间就是市场就是利润已成为导向,这个的确也是有道理的),这个对一家企业来说至关重要,但是对研发工程师来说却不是好现象,急躁紧凑的开发周期带来的隐患是对平台和产品技术细节的把握和理解不深入,不利于个人能力水平的提高,开发者往往最开始的想法是先等产品研发出来之后再往回深入学习理解开发平台,但是事实却是,一个产品研发完了会有另一个项目进来(或者被产品的后期问题分散掉大部分精力),因此总是被动的学习,这点俺作为芯片原厂技术还是深有体会的,大多数的用户对一款芯片资源的利用不到50%(或者说很多芯片比较有特色的可以大幅提高开发效率的的资源都没有来得及被使用),存在着较大的资源浪费。
好了,不小心又啰嗦了半天的废话,言归正传,上文提到串口提到封装库,现在我们做串口初始化时关于波特率的配置往往不去关心,只是传递一个波特率参数,封装库里会根据输入的波特率换算成底层寄存器级别的配置,而我们知道对异步通信来说波特率的计算精度是比较重要的(这点不同于同步通信,异步通信没有外部时钟来同步),那在波特率换算成寄存器配置的过程中怎样保证这个精度呢,下面以飞思卡尔Kinetis E系列为例,下图为KE系列波特率计算公式,SBR为寄存器的配置,UART Module Clock为UART的输入时钟源,因此正常来说SBR=input clock/16/Baud Rate。
<img id="aimg_ZZOna" class="zoom" height="203" file="http://files.chinaaet.com/images/blog/2015/06/26/13678492614263.png" border="0" alt="" />
但是因为无论是输入时钟还是波特率参数,这几个变量的值都是整数,而整数间的除法如果有余数是都会被舍弃而不管是余多少的(不存在四舍五入),而在算波特率时如果舍弃的多的话会影响算到最后的寄存器配置值进而影响通信的精度,所以我们需要引入C语言中整数除法的四舍五入算法,即(b+a/2)/a,它是整数间除法四舍五入的公式(具体怎么得出公式的,你只需要随便给b和a赋几个值算一下就明白了),通过使用这种方法得出的实际UART初始化配置函数API如下,其中busClkHz为UART模块的输入时钟源,bitRate为波特率参数,可以看到((busClkHz>>4) + (bitRate>>1))/bitRate=(inputclock/16 + BaudRate/2)/BaudRate。
<img id="aimg_UCJQ5" class="zoom" height="225" file="http://files.chinaaet.com/images/blog/2015/06/26/13678498076315.png" border="0" alt="" />
这个简单的整数除法的四舍五入算法虽然很简单却挺实用的,不只是在波特率计算中会用到,在一些其他领域中也会用到,我们先留着这样一个概念,以后早晚会用到的,艺多不压身啊,呵呵。
—————————————————————————————————————— |