Cortex—M0单片机二-十进制整数转换的快速算法
扫描二维码
随时随地手机看文章
摘要:为了提高Cortex—M0系列单片机应用系统的二进制到十进制BCD码整数转换代码的执行效率,采用除十求余数法来实现。该快速算法的核心内容是通过高效的汇编语言来实现常数除法,无论在程序代码的运行时间和存储空间上,都远胜于sprintf函数。
关键词:Cortex-M0;单片机;二-十进制转换BCD码;常数除法;快速算法
引言
在单片机应用系统中,一般都需要高效快速地完成系统所需要的任务,并在任务完成后使系统进入睡眠或低功耗状态,以便最大限度地节省系统功耗,增强系统的抗干扰能力。因此,必须优化和提高系统中各个模块的运算速度,以最大限度地压缩软件运行时间。许多单片机应用系统中都需要进行二进制整数转换为十进制BCD码的操作,以便实现系统信息的显示。对于Cortex—M0系列单片机,由于其指令系统中没有十进制调整指令和除法指令,使得一些文献中提供的高效算法和技巧不再适用于这类单片机,从而造成上述转换操作成为影响系统性能的重要因素,因此提高上述数制转换速度对于提高系统运行效率有极大的促进作用。
1 传统的实现方法
要实现快速运算,很自然地想到经典的双字节二进制整数转换成3字节BCD码整数的子程序。其采用的算法是预先将一个3字节队列的内容清除为0,然后依次将需要变换成BCD码的二进制整数的每位依次左移至CY位,再把3字节队列中的数据带进位自身相加,并对相加的结果进行十进制调整。通过16次移位完成运算,结果为压缩格式的3字节BCD编码。由于ARM指令系统中没有类似于MCS-51单片机系统中的十进制调整指令,所以在Cortex—M0系列单片机上实现该算法比较困难。
2 快速算法概述
本快速算法采用除十求余数法来实现。设需要转换的数据也就是被除数为W,除数为10,整数除法的商为S,除法运算的余数为R,根据数学运算规则有:
S=W/10 (1)
R=W-S×10=W-(W/10)×10 (2)
经过上述的运算,所得余数R就是从被除数中分离出来的个位数字,也就是首先得到了被除数的最低位的BCD码。为了获取被除数其他位的BCD码,只需要将上面得到的商S作为新的被除数W,然后重复执行上述整数除法运算,就可以分别得到被除数其他位上的BCD码,从而完成将二进制数转换为BCD码的操作。实现上述操作的关键在于如何快速地完成除数为10的快速除法任务。
3 除法运算的实现
为了将被除数除以10,可以将其转化为将被除数乘以0.1来实现,为此可以先写出十进制数据0.1所对应的二进制小数的表示形式:
(0.1)D=0.000 1100 1100 1100 1100 1100 1100 1100 1100 1100……
为方便32位单片机进行整数运算,预先将上式中的二进制数左移35位,即将其扩大235倍后得到除数10的魔术数(Magic_Number)为:
Magic_Number=CCCCCCCDH(十六进制数)当得到除数10的魔术数后,将被除数与该魔术数相乘,然后将所得的乘积右移35位,即将乘积缩小235倍后得到最终的数据就是所期望的除法结果。
由于Cortex—M0系列单片机的乘法指令只能保留两个32位数相乘后的乘积的低32位,乘积的高32位被舍弃,所以不能直接采用被除数与除数的魔术数相乘的方法来实现将除法转换为乘法的运算。好在这个魔术数很有特点,可以将其表示为:
Magic_Number=C0000000H+0C000000H+0CC0000H+0CCCCH (3)
由于是通过求余数的方法来获取原始数据的各位BCD码,所以在不损失运算精度的原则下,舍弃了原魔术数Magic_Number的最低位,但这不妨碍最后通过式(2)来求余数的操作。下面就是对式(1)中的除10操作变换为乘法操作的具体实现方法:
通过(4)式,采用Cortex—M0系列单片机指令中的移位指令和加减法指令的组合运算就可以快速地得到整数除法的商S,进而采用式(2)来求余数R。
4 算法中除法运算的汇编代码实现
Cortex—M0系列单片机采用Thumb指令集,式(4)中各数据项中的分数项都可以利用该指令集中的右移指令来实现,并且采用多次累加的办法来完成运算。下面给出具体的汇编语言源程序:
结语
Cortex—M0系列单片机的开发一般采用集成开发环境,为方便使用,可以将上面的子程序封装成符合集成开发环境调用规则的函数,封装时最好包含有将单字节、双字节、三字节和四字节数据转化为BCD码的多个函数。为测试该函数的性能,在IAR集成开发环境下,将General options→Library Options选项卡中的Printf formatter设置成Tiny模式,以便尽量减小Sprintf函数的代码长度和运行时间。为叙述方便,这里假定封装好的函数名为Hex2Bcd,表1给出其与系统函数sprintf的指令运行周期数(CCSTEP)的对比数据。
由表1可以看出,Hex2Bcd函数的平均运行时间不足sprintf函数的5%,速度优势极其明显。另外Hex2Bcd函数的程序代码仅有100字节左右,远少于sprintf函数的1.5 KB,极大地节省了存储空间。因此,本文中的快速算法具有很强的实用性,值得推广应用。