基于单片机数字拆分的一种高效算法
2015-06-01闫海环刘国华刘晨
闫海环 刘国华 刘晨
【摘 要】为了提高单片机在数据拆分程序中的执行效率,提出采用“二分拆分”算法。该方法不需要做16位的余数算法及16位的除法算法,采用简单的判断语句即可获得各位对应数值。文章对该算法在数据拆分中的应用进行原理分析,同时进行了软件设计,通过实验验证“二分拆分”算法的高效性。
【关键词】单片机 “二分拆分”算法 效率
随着科技的发展,在以单片机为核心的智能仪表系统中,常常遇到,需要将数据直观地显示出来,以方便人们监视智能系统的工作情况或直接读取各仪表测量的结果,此时就需要将程序中的数据进行拆分。目前国内许多单片机书籍或网络上介绍并提供了许多子程序,但程序执行效率不高。本文重点介绍了一种“二分拆分”算法,可以大大提高数据拆分的效率。
1“传统拆分”算法
“传统拆分”算法思想:两个整型数据进行除法或求余运算。C语言中,两个整数相除、求余运算的结果是整数。
三位数的“传统拆分”算法软件实现:假设预拆分的三位数data(569),首先进行高位数字的拆分:data(569)/100,得到高位数字5;其次进行中间位数字的拆分:data(569)% 100得到数据69,69/10得到中间位数字6;最后低位数据的拆分:data(569)% 10,得到低位数字9。
“传统拆分”算法C语言代码简单。但是大部分的C编译器的求余运算都是调用子程序来完成,代码长,执行速度慢。
2“二分拆分”算法
“二分拆分”的思想:首先确定有限区间,将区间分成两部分,通过判断数据的单调性,逐步将有限区间缩小,直至有限区间在所求范围内,便可拆分出满足要求的数值。“二分拆分”算法主要采用“if(表达式)语句1 else 语句2”,每次判断即可筛掉一半数据。针对单片机来说, “二分拆分”算法的效率远远高于全遍历的线性判断及传统的取余算法。
三位数的“二分拆分”算法软件实现方法:假设预拆分的三位数data(569),首先进行高位数字的拆分:①三位数的有限区间为[0,999],将该区间划分成两部分[0,599]和B(599,999]。数据data(569)与599进行比较,小于599,确定查找区域为[0,599]。②需要将区间[0,599]再划分成两部分[0,299]和(299,599]。数据data(569)与299进行比较,大于299,确定查找区域为(299,599]。③需要将区间(299,599]再划分成两部分(299,399]和(399,599]。数据data(569)与399进行比较,大于399,确定查找区域为(399,599]。④需要将区间(399,599]再划分成两部分(399,499]和(499,599]。数据data(569)与499进行比较,此时数据data(569)>499且<599,因此可以确定百位数字为5,剩余两位数为data(569)-500。以此类推在有限区间为:[0,999],可将数据划分成区域10个区域,每个区域对应百位数字:[0,99]→0,(99,199]→1,(199,299]→2,(299,399]→3,(399,499]→4,(499,599]→5,(599,699]→6,(699,799]→7,(799,899]→8,(899,999]→9。其次进行中间位数字的拆分:①两位数的有限区间为[0,99],将该区间划分成两部分[0,59]和B(59,99]。数据data(69)与59进行比较,大于59,确定查找区域为(59,99]。②需要将区间(59,99]再划分成两部分(59,79]和(79, 99]。数据data(69)与79进行比较,小于79,确定查找区域为(59,79]。③需要将区间(59,79]再划分成两部分(59,69]和(69,79]。数据data(69)与69进行比较,等于69,确定查找区域为(59,69]。因此可以确定中间位数字为6,剩余一位数为data(69)-60。以此类推在有限区间为:[0,99],可将数据划分成区域10个区域,每个区域对应百位数字:[0,9]→0,(9,19]→1,(19,29]→2,(29,39]→3,(39,49]→4,(49,59]→5,(59,69]→6,(69,79]→7,(79,89]→8,(89,99]→9。最后获得低位数字为9。
高位数字、中间位数字的拆分函数,采用数组名作为函数参数,由于数组名代表的是数组元素的首地址,传递的值是地址,因此要求形参为数组名或指针变量。通俗理解,形参指针变量与实参数组共占同一段内存单元,在调用函数期间,如果改变了形参数组的值,也就改变了实参数组的值。中间数字的拆分函数需特别注意:形参获得的地址是数组首地址,此时需要将形参地址+1,并赋给形参。如图1。
在C语言中,用指针编写的程序比用数组下标编写的程序执行速度快。因此形参采用指针变量。
static unsigned int high_data, mid_data, low_data; //高位、中间位、低位数字定义
static void baiwei(unsigned int *p); //高位数字的拆分函数
static void shiwei(unsigned int *p); //中间数字的拆分函数
static void dispose_datafunc(unsigned int data) //数据拆分函数定义
{
unsigned int array[3];
*array = data;
baiwei(array);
shiwei(array);
high_data = array[0];
mid_data = array[1];
low_data = array[2];
}
图1 中间数字的获取流程 图2 “二分拆法”与“传统拆分”的响应时间对比
3“二分拆分”算法的实验验证
编写简单的测试程序将“二分拆分”算法与“传统拆分”算法同时运行,采用单片机ATmega64的PA0的高低电平变换测试两段程序的运行时间,并用示波器测量,如图2。相同数据进行拆分,“二分拆分”算法运行时间为3us,传统拆分算法运行时间为18us。“二分拆分”算法的效率远远高于传统拆分算法。测试程序:
PORTA |= 0x01; //高电平开始
dispose_datafunc(569); //二分法数据处理,
PORTA &= ~0x01; //低电平
for (i=0;i<10;i++) delay_1us();
PORTA |= 0x01; //高电平
hex_bcd(569); //传统数字拆分法
PORTA &= ~0x01;
for (i=0;i<30;i++) delay_1us();
4结语
通过实验验证,“二分拆法”算法确实较“传统拆分”算法大大提高了MCU的执行效率。由此看来,好的单片机代码,并不是仅仅局限于各种功能的实现,还应该从执行效率、减少运算的强度、便于移植等方面综合考虑,选择合适的算法。
参考文献:
[1]邓勇,刘琪.智能仪表多字节二进制数转换BCD码.《电子产品世界》,1999年12期.
[2]沈文,詹卫前.AVR单片机C语言开发入门指导.
作者简介:闫海环(1982一),女,汉族,山西省交城县,本科,助理工程师,从事逆变电源的开发。