您的位置:首 页 > 新闻中心 > 新闻资讯 > 简述仪表设计中的浮点数问题及解决办法

新闻资讯

简述仪表设计中的浮点数问题及解决办法

发布时间:2021-12-16 11:03:00  浏览量:3455
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所列。

a.JPG


由表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。

b.JPG


比较表1和表2的数据可知,修正作用非常显着,在平等的检测条件下仪器接连运转27小时后,累积量的检测精度依然满意技术目标要求。但存在的问题也很显着,通过比照数据发现,累积量的检测差错是跟着时间的添加而添加的。能够预见,当运转的时间足够长时检测差错终究会打破技术目标的要求,试验成果的确也证明了这一点。

通过研讨发现,问题呈现在处理累积量的方法上。在前面的程序中直接通过每秒履行一次句子“Cureulation=Cumulation+Instant;”来核算累积量。而参阅文献清晰通知我们,两个浮点数相加时,其差错跟着两个数不同的增大而增大,表2中差错的改变规则也证明了这一点。这是因为每次履行句子“Cumulation=Cumulation+Instant;”时,Instant是不变的,而Cumulation在不断添加。当两者巨细相差的数量级足够大时,Instant与Cumulation相加会丢掉Instant,致使流量计累积量读数不再发生改变,这也是前面调试时呈现问题的原因。
这个问题能够使用汇编编程的处理方法来处理,但此种方法比较繁琐,编程比较困难。本文给出了一种新的处理方法。上述大数加小数丢掉小数的状况在整数相加时是不存在的,一起,流量计在运转时当检测的瞬时流量小于下限流量时会当作搅扰信号切除掉,累积量无需累加。试验数据标明,当瞬时流量在下限流量和上限流量限定的全量程规模内改变时,累积量小于4000时检测精度彻底满意技术目标的要求。我们选用的方法是,将累积量分两部分来存储。为此,另界说一个unsigned long型变量HBCumu,每逢Cumulation累加超过2000时履行下述操作:
HBCumu=HBCumu+2000;
Cumulation=Cumulation-2000;
即每次将Cumulation中的2000转存到HBCumu中,因为核算HBCumu时选用的是整数相加,因而不存在精度问题。一起通过此种操作,能够把Cumulation和Instant的巨细不同限定在一个适宜的规模内,然后确保核算Cumulation时精度满意要求。在EEPROM中别离给HBCumu、Cumu-lation开辟有独立的存储单元,每个存储周期别离存储两者的值。当时累积量的实在值等于HBCumu和Cumulation的和,显现数据时先求两者的和再进行显现。选用新方法后,在与前述相同的测验条件下从头对流量计进行测验,实测数据如表3所列。测验开端时间,流量计的初始读数为86。

c.JPG


比较表3和表2的数据能够看出,选用转存方法对累积量进行存储后,很好地处理了检测精度随时间添加而变差的问题。我们对累积量计数满99 999 999的前后阶段也进行了测验,试验成果标明,检测差错与表3中的差错共同,这标明在全量程规模内差错都稳定在一个令人满意的规模内。此种方法与使用汇编编程处理的方法比较,避免了使用汇编代码处理浮点数的繁琐作业,坚持了C言语的高效性和代码的杰出移植性。

2 存储问题
项目要求在流量计正常运转时能够随时设定液体的密度、流量系数等参数,而且这些参数小数点后数据的位数固定。比方密度设定值,数据设定规模为0.001~999.999,小数点后固定为3位数据。程序编制结束在调试阶段发现的问题是,当把参数设置结束存入EEPROM、再读出来时,读出的数据和存入的数据并不共同。比方设定密度值为123.456,设定结束存入EEPROM,然后读出来的数据是形如123.454这样的数据。
通过细心研讨终究发现,问题仍是呈现在对float型数据的处理上。由参阅文献可知,float型数据在存储时,存储的并不是准确值,而是近似值。而在规划程序时,界说密度设定值dEn为float型,并直接对其进行存取处理。针对这个问题的处理方法是,界说dEn为unsigned long型的数据,其间寄存的数据是密度实践设定值放大1000倍后的数据,在程序其他地方用到密度设定值时,只需要将其除以1000得到实在值即可。这样在参数设定结束存入。EEPROM及从EEPROM中读出数据时,实践上都是以整数方式进行操作的,这样就能够确保数据的正确性。为了给操作者一种仍旧是在设定一个小数点后有3位小数的参数的感觉,在设定和显现参数过程中,一直点亮LCM141相关数据位的小数点。

结语
本文评论了笔者在规划流量计的过程中,使用C言语操作浮点数所遇到的问题,这种问题在其他仪器及嵌入式体系规划中也是普遍存在的。针对这些问题给出了处理方法,且现已成功地在实践项目中得到使用,具有必定的参阅价值。