目前所有dsPIC30F器件都拥有一个具备自动波特率检测能力的UART外设。UART接收引脚(RX引脚)上的信号能在内部传送至一个输入捕捉模块以获得输入信号边沿的时序。根据该时序,应用程序能正确设置UART的波特率。
当输入数据的波特率以及处理器的振荡器频率未知时,自动波特率检测是很有用的。由于RC振荡器经常不够精确且随时间变化会产生漂移,因此采用RC振荡器的系统非常适合采用自动波特率检测。
方法
自动波特率检测的方法取决于接收到的已知数据。为实现自动波特率检测,通常可使用通信协议发送特定数据。根据已接收数据的时序可计算U1BRG或U2BRG寄存器的值。上述寄存器用来设定UART的波特率。
本文的两个示例都使用输入数据0x55(ASCII字符“U”)来计算波特率发生器的值。该特定数据字节提供了最大数目的脉冲边沿,因此具有最大的准确度。实际上可采用任何数据字节,此时波特率计算将会自动适应被测数据。通常,数据中出现的边沿(位状态变化)越多,则结果会越精确。
信号
UART信号的发送顺序实行低位在先的原则。发送字节中首先是起始位(逻辑零),末尾则为停止位(逻辑1)。发送字节通常具有8个数据位,但也可使用不同长度的数据位,在数据位之后可加入奇偶校验位。所有这些都将对自动波特率检测的计算造成影响。但应事先知道数据的格式。
由于存在起始位和停止位,因此存在至少两个脉冲边沿,但也可能是10个或更多。
时序和采样
在记录了脉冲边沿的时序并去除偏移量t0后,可利用公式1来计算UxBRG寄存器的值。我们还采用线性回归算法对该公式进行了推导,具体过程见附录(http://ww1.microchip.com/downloads/en/AppNotes/00962a_cn.pdf)。计算是在最后一个脉冲边沿被记录后进行的,且应在下一个字节的起始位出现前完成以避免造成数据丢失。因此,计算过程须设定时间限制并应对其进行检查。在某些情况下,有必要使用一种具有较快执行速度的较简便计算方法。此时,同样需考虑误差检查所需的时间。
UxBRG=[2(t1+2t2+3t3+...+9t9)-9(t1+t2+t3+...t9)]/2640-1……公式1
误差
误差检查是一个好的编程习惯。输入信号中可能不包含期望数据0x55。误差可能是明显的,因为边沿之间的时间较长且简便的超时即可对该问题进行检测。假使所有边沿都出现在可接受的超时周期内,这些边沿仍然有可能与期望的顺序不匹配。有几种统计方法可用来显示被测信号偏离期望信号的程度。示例代码中使用了平均绝对误差。如果距离期望时间测量值偏移量的平均值超过位时间的5%,则该数据将被丢弃。
替代方法
因为使用了所有的输入捕捉数据,线性回归方法具有极佳的准确性。但这种方法对于某些应用来说计算量太大且太慢。我们还推导了一种简化的方法,该方法用两个边沿之间的时间差除以位数以计算单个位时间。
UxBRG=(t8–t0)/128–1……公式2
代码实例
本文附录中的代码实例(http://ww1.microchip.com/downloads/en/AppNotes/00962a_cn.pdf)是基于输入字节0x55(ASCII字符“U”)实现自动波特率检测。这些代码是使用MPLAB®C30编译器进行开发的。
结构
软件具有三个主要部分:主循环,初始化和中断服务程序。
主循环
main()函数具有一个执行自动波特率检测功能的无限循环。函数开头调用SetupAutoBaud()对所有外设和自动波特率检测过程所使用的中断进行初始化。随后代码处于循环等待状态直至U1BRG寄存器具有一个非零值,表明自动波特率检测过程已成功完成。
代码根据U1BRG中的值来计算实际波特率,并从UART发送一条报文显示计算后的波特率。波特率计算不是自动波特率检测工作所必需的,但该项工作用于演示目的。
待该文本发送后,程序重新循环并重新开始自动波特率检测过程。
初始化
SetupAutoBaud()函数对UART1外设、输入捕捉1模块和Timer 3进行初始化以对输入数据执行自动波特率检测。
UART1启用并使能自动波特率检测功能。此时U1RX引脚上的输入串行数据信号在内部传送到输入捕捉1模块。
为获得最高的精度,Timer 3设定在每一个指令周期进行递增计数。周期设置为最大值,以便在16位计数计满之后定时器才会出现溢出返回。
输入捕捉1模块设置为捕捉Timer 3且在输入信号的每一个边沿产生中断。输入捕捉1模块中断使能。
中断服务程序
共有两个中断服务程序,分别为Timer 3中断和输入捕捉1中断。
Timer 3中断服务程序对自上一次输入捕捉事件后的定时器溢出中断次数进行计数。如果脉冲边沿之间存在一次以上的溢出,则表明自动波特率检测失败并将重新开始该过程。这种情况发生在输入信号脉冲边沿间存在较大间隔时。
输入捕捉1中断服务程序是自动波特率检测过程的核心部分。根据当前执行的是简化计算或复杂的回归计算,该中断服务程序将有所不同。
中断服务程序首先将前一脉冲边沿的记录时间进行保存并读入与已经检测到的当前脉冲边沿对应的新时间值。
定时器溢出时计数将被复位为零以开始一个新的超时周期。
第一次捕捉中断将使能Timer3中断以对超时进行检查并对自动波特率检测计算变量进行初始化。
随后发生的每一次捕捉中断都用来从前一时间减去当前捕捉时间值以获得当前位的时间。该计算采用无符号整数来进行的,因此相邻捕捉间定时器是否溢出不会产生影响。
对于简便计算,位时间加入到一个累加和直至所有8个位时间都已被累积在一起。
对于回归计算,位时间加入到前一次记录的时间并存储到时间数组的下一个元素中。这为回归计算以及以后的误差检查提供了数据点。回归计算所需的累加运算也是在中断服务程序中完成的。
当最后一个(第十)捕捉中断发生后,中断服务程序随后禁止全部两个中断,结束自动波特率检测计算并使能使用新波特率的UART。
对于简化计算,除了超时检查外将不进行误差检查,且U1BRG寄存器的值直接来自8个位时间的累加和。在除以128前,该数通过加上64进行舍入。这将在截取前有效加入½。除以128的操作是通过进行7次移位来实现的。
对于回归计算,将计算回归线的斜率和Y截距。这将用来计算期望时间值,该值将从用于误差检查的实际时间测量值中减去。如果误差大于5%,自动波特率检测过程将重新开始。该门限值可以根据不同的准确度要求进行改动。最后,根据回归线的斜率计算U1BRG值。
代码的使用
本示例代码是使用运行于29.5MIPS的dsPIC30F6014器件在dsPICDEM1.1演示板上进行开发和测试的。
时序允许将代码应用于低至600的任何标准波特率。可通过以下步骤对示例代码进行测试:
• 使用标准的RS232电缆连接PC的COM口和dsPICDEM 1.1控制板上标有“PORT B”的连接器。
• 在PC上运行终端程序,如超级终端,应确保终端程序使用了正确的COM口。
• 编译代码,将代码烧写到dsPIC器件中,并运行代码。
• 在终端程序中键入“U”。
• dsPICDEM1.1演示板将以“Baud rate: xxxx”文本作出响应,其中xxxx是使用的波特率。
• 改变波特率并在终端程序中再次键入“U”。
• dsPICDEM1.1演示板将响应新的波特率。
使用的资源
除UART外,自动波特率检测代码还将用到程序存储器和数据存储器,一个输入捕捉模块以及一个定时器。自动波特率检测过程中用到的RAM很少且在执行完毕之后定时器和输入捕捉模块还可用于其它用途。程序存储器的使用取决于计算的复杂程度。
调整和改进
提供的示例代码给出了两种方法对输入数据字节0x55(ASCII字符“U”)执行自动波特率检测。这些方法可应用于任何已知的输入数据。所有方法都通过确定输入脉冲沿的时序来确定单个位周期。可以使用不同程度的分析和误差检查措施以提高可靠性或运行速度。
对于未知数据也可使用自动波特率检测方式,但难以确定单个位时间并难以将起始和停止位与数据位进行区分。理想的情况下自动波特率检测过程应利用数据的相关信息来简化计算。
自动波特率检测过程是利用中断在后台执行的。dsPIC器件灵活的中断优先级结构允许自动波特率检测中断配置为对应用的其余部分影响最小。用于自动波特率检测的定时器和输入捕捉资源在自动波特率检测计算完毕之后还可用于应用的其他部分。
备用中断矢量表可用于自动波特率检测中断,允许主应用程序拥有自己单独的输入捕捉和定时器中断。
两个UART都具有自动波特率检测能力。注意,由于UART1使用输入捕捉1模块而UART2使用输入捕捉模块2,因此两个UART都可同时执行自动波特率检测。
结论
内置的自动波特率检测功能使得未知波特率的UART的配置变得简便。由于该过程可在中断控制下在后台完成,因此其对应用的其余部分影响甚小。代码可根据用户需求,使用一种简便的计算方法来获得较高的执行速度,或使用一种具有完备误差检查功能且较为复杂的计算方法以实现更佳的可靠性。
进一步信息,请访问http://ww1.microchip.com/downloads/en/AppNotes/00962a_cn.pdf。