本帖最后由 会笑的星星 于 2020-2-25 19:36 编辑
在程序设计时,我们可能需要建立一个直线方程,以根据输入值产生一个输出值,典型的一个应用就是获取温度传感器的A/D值,然后把A/D值通过直线方程转化为对应的温度(如图所示)。通过直线方程找到两个变量之间的关系看上去很简单,只需要做一个简单的运算就能完成,不少书上也是这么教的,但是如果考虑在单片机中应用就可能有问题。
温度与A/D之间的线性关系
一般而言建立直线方程需要做浮点运算,这对于有些单片机来说是有压力的,即使我们考虑把浮点数转换为整数,也会涉及大整数的乘除运算,同样对有些单片机来说是不合适的。除了考虑单片机的运算效率以外,还有一点更为关键,那就是一不小心造成运算出错,比如数据溢出的问题,一旦出现这样的问题,恐怕找bug都要找死你。因此,只要条件允许,不建议在单片机中通过建立直线方程来建立两个变量之间的关系。那通过什么办法找两个变量之间的关系呢 --- 查表法,下面就对这种方法做一个介绍。
什么是查表法呢,我以上图温度与A/D值的关系为例来说明。我们首先建立一个存储温度的数组,用A/D值做为数组索引,实际温度做为该数组的值,从而将A/D值与温度一一对应。例如A/D值为20时,对应的实际温度是20℃,存储温度的数组是temprature[](temprature的数据类型为const),我们需要确保这个数组在索引20的位置对应的温度为20,也就是temprature[20] = 20,当A/D值是40时,对应温度为40℃,那么temprature[40] = 40,其他温度以此类推。
如上建立温度与A/D值的映射关系,你会发现假如我要测量的温度就只有20-40℃,按照上述的一一映射关系,这个数组的前20个字节不是浪费了吗。的确如此,如果像上述直接映射,好处是十分简单,坏处是会有20个字节浪费,但是考虑该数组一般存储在flash空间,不占用RAM,而flash空间对于很多单片机来说是够用的,即使浪费一点也不需要太担心。
假如你实在不想浪费那多余的二十个字节,也是有办法的,你只要把做为数组索引的A/D值做一个简单的转换就可以。怎么做呢,只要把读取的A/D值-20,让有效温度对应的索引位置从20-40平移到0-20,这样就能节省20个字节的空间。比如A/D值为20,temprature[20-20] = 20,A/D值为40,temprature[40-20] = 40。
如上方法就是查表法,相比直线方程,查表法只需要根据索引取出对应的值即可,不像直线方程那样涉及到比较复杂的乘除运算。不过查表法有一个麻烦就是需要事先计算出(无法计算时则要估计)每一个A/D值与温度的映射关系,而直线方程不需要这样(只要确定y=ax+b中的a、b后就可以根据x值计算y)。
事实上,假如上述的A/D值与温度的关系并不是直线,而是曲线(如下图),此时采用直线拟合这条曲线可能就不准确了,但如果使用查表法却可以解决这个问题,因为查表法的映射关系是人工一个个准备好的,由此建立的变量关系具有更高的拟合度从而更接近实际情况。
温度与A/D值之间的曲线关系
当然,有时候我们无法事先建立好变量之间的映射关系,可能需要根据外部情况(比如传感器特性)调整一些数据,从而必须建立直线或者曲线方程才能很好的符合实际情况,此时查表法可能就无能无力了。到底使用查表法还是使用方程,需要视情况而定,没有哪一种方法是万能的。
|