« 上一篇下一篇 »

数据处理及小数点显示

做AD/DA实验的时候,用它来测量电压,却发现显示的数值总是不对,细心想想,在没有大数据时,处理结果是对的,然而我给它放大1000倍之后就出现问题了。故写此文,一起学习。

1、数据处理


先来看看这样写对不对

  变量a的类型为unsigned long,对这个数据类型,书上是这样定义的, /*unsigned long     16bit     2字节      值域:0 ~ +4294 967 295*/,从这里来看,它可以存储很大一个数值的,最开始我是这么想的,但结果却是我错了,这么写的话,最后的结果就会出错,错误出在哪里呢?我测过AD的对应引脚,电压是正确的,但是显示没有对,很明显,问题出在数据的处理上面。我虽然知道这是问题的所在,但是却无法解释,如果哪位朋友能够解释不妨大家一起探讨下!

既然上面那样处理有问题,那自然得换种方法了,那就是尽量缩小这个表达式所进行处理的数据的大小。

看看这样子

  第一种写法,假如RcvByte()的值为100,则100 * 1000 = 100,000 * 5 = 500,000,然后再除以256,第二种写法,按优先级,先计算括号里的式子,1000 * 5 = 5000 / 256 = 19(实际值应约为19.53,不过这里是int型,所以整数后面的直接舍去了),两种方法一比较,很显然,第二种进行处理的数据小得多了,差不多小了几千倍,这样进行处理,便能够显示正确的测量电压值。

但是,我不知道第一种为什么错了!!!唉!!!

其实也可以不这样写,我们可以先将 1000 * 5 / 256 的值计算出来,再进行相乘,比如,1000 * 5 / 256 = 19.53,我们就可以这样

  这样写不仅不会出错,而且数据更加精确。

  上面的数字我解释下,AD用的是PCF8591,这是8位的ADC,28 = 256,参考电压为5V,所以它的测量单位为 5 / 256,由于显示要求有3位小数,而电压值较小,只有0 ~ 5V,所以这里进行了放大处理,倍数为1000。而RcvByte()则为AD的采样值。

开始我还以为变量a必须要是unsigned long 类型才够,后来发现这样不行,用第二种方法的话,变量a只要为unsigned int 类型就够了。



 2、小数点显示


  1、共阴极数码管

        Px = table[X] | 0x80;        //或者这样写   table[X] + 0x80,也是对的

但是,如果写到table[]数组里面的话,就不会起作用,像这张图

  共阴显示0本是0x3f,我心迹dp(即D7)位置1就行了,于是我就写成了0xbf,结果没用,又在它后面加0x80,也是没用的。


  2、共阳极数码管

        Px = table[X] & 0x7f;

   我没具体验证过,但理论上是对的,因为共阴时置高为亮,而共阳时置0亮,所以最亮位为0,而其他位为1并相与,如果原来值为0则依然为0,不会有问题。

   在具体点亮小数点的时候,一般来说,我们只需要点这第1位的小数点,这时,用个变量进行判断一下就可以了,不多说,还是上张图吧,省得我说不清楚

   只有变量 j = 0 时,才会点亮小数点,而此时位选选中的也是第1位(最高位),其他均不处理。


   说到这里顺带把那天解决的一个按键的问题也拿来献下丑吧!

   就是按键判别时进行的处理,还是上图吧,码字太累,看着也难。

    

   首先我们设一个标志位,并给一个值,不与后来重复的值。

   然后我们在判断读取的值时,就可以对这个标志位置不同的值,代表不同的键按下,当然,只要不与最开始的标志位值相等就是了

   接下来我们只要判断标志位的值是否与初始值相等,只要不相等就说明有键按下,我们就可以根据现在的标志位值进行处理,但是不要忘记,处理完后,要重新给标志位赋值,就是第一次赋的那个值。

   这种方法的话,就可以少写蛮多代码,若不这样的话,那switch()那里每个 case xxxx: 后面都要写一段处理代码来完成处理,而用标志位的方式,只需要在判断完之后,在后面集中处理就Ok了,其实这个说来想必大家都知道,虽不值一提,但也还是拿来说说吧,毕竟自己好不容易才想到的。


【此文系原创,转载请注明出处,谢谢!】