引言
C语言以其编程效率高、代码可移植性好、程序易于维护等特点,在仪表系统及其他嵌入式系统开发中应用十分广泛。尤其在处理浮点数的运算过程中,C语言与汇编语言相比其优势更加明显。因此,C语言深得项目开发人员的青睐。但是在浮点数处理过程中,若处理不当,则会在系统调试过程中出现异常,致使系统无法工作。
本文以笔者开发的某型号流量计为背景,讨论了在仪表设计过程中应用C语言处理浮点数时出现的问题及相应的解决办法,以供读者在遇到类似的问题时参考。流量计的MCU为Microchip公司的PIC16F876A,集成开发环境是Microchip公司的MPLAB8.3,C编译器选用HITECH公司的PICC9.5。
1 精度问题
项目要求实时计算累积流量并刷新数据显示,同时为防止掉电时累积量丢失,要求系统定时刷新EEPROM中累积量的值。为此,软件设计时设置两个变量Cumulation和Instant,分别用来存储累计量和瞬时量。Instant根据相应的计算公式计算得到,Instant每秒累加便得累积量Cumulation。累积量的数据显示范围为0~99 999 999,至上限值后回零,重现从零显示,要求满量程内累积精度优于0.3%。瞬时量的数据显示范围为0.000 1~99 999,需实时刷新,测量精度优于0.5%。
程序编制完毕,在调试时发现下列问题:瞬时量测量精度高于指标要求,累积量在程序运行的开始阶段精度也满足要求,但随着测量时间的增长,累积量的实际测量值和理论计算值之间的差别越来越大,超过了技术指标的要求。若不加干涉任其运行,当时间足够长时,显示模块显示的数据不再发生变化,即流量计的累积量不再发生变化了,但此时瞬时量显示的数据依旧正确。某次测试时,通过设置流量计参数,使瞬时量理论值为3600 m3/h,以10min为一个测量周期进行测量,理论计算得累积量每个周期应累加600。实测数据如表1所列。
由表1中的数据可知,第1个测试周期精度满足要求,从第2个周期开始误差已经超过了技术指标要求,并且误差随着时间的增加而增大,在这种状态下流量计是无法正常工作的。那么问题出现在什么地方呢?经过查阅资料和仔细研读程序发现,在定义累积量和瞬时量时采用了如下形式:
double Cumulation;
float Instant;
使用了编译器PICC 9.5的默认编译设置。查阅编译器的使用手册得知,HI-TECH公司的编译器PICC 9.5的浮点数采用IEEE754规范,一个float类型数据占24位,同时支持以24位、32位两种方式存储一个double型数据,但为了节约存储空间,在不对编译器选项修改的情况下,double型数据采用的也是24位。显然,在此默认情况下累积量的计算精度不能满足要求。
通过修改编译器选项,使double型数据以32位格式存储,同时修改程序的其他相关地方后,重新进行测试。测试时通过设置流量计参数,使瞬时流量理论值为3600m3/h,以1个小时为一测量周期,显然累积量每小时的累积值理论上应为3600。实测数据如表2所列,测试开始时刻Cumulation等于50。
比较表1和表2的数据可知,修改效果十分明显,在同等的测量条件下仪表连续运行27小时后,累积量的测量精度仍然满足技术指标要求。但存在的问题也很明显,通过对比数据发现,累积量的测量误差是随着时间的增加而增加的。可以预见,当运行的时间足够长时测量误差最终会突破技术指标的要求,实验结果确实也证明了这一点。