单片机ADC采样算法

您所在的位置:网站首页 c语言求平均值代码怎么写 单片机ADC采样算法

单片机ADC采样算法

2024-01-04 22:30| 来源: 网络整理| 查看: 265

       在上一篇文章单片机ADC采样算法---平均值采样法中分析了平均值采样法的使用,上篇文章中的平均值采样法是连续采样100个数据,然后求平均值,这种方法存在一个问题,就是采集100个值之后,下一次又重新采集100个新的值,这两次采集的值是不连续的,相当于每次都是独立的采集来100个值,然后求平均值。这样计算出来的值有可能看不出来数据的变化趋势。希望在求平均值的时候每次读取到一个新的值,就将最早读取的旧值丢弃一个,相当于水管中的流水一样,有新的水流进来,就让最早进来的水流出去。这样采集到的数据就是连续变化的。这样通过采样值就能看出来采样数据是否发生了波动。

    算法如下:

#define N 100 unsigned int filter4( void ) { static unsigned int value_buf[N]; static unsigned int i = 0; unsigned int count; int sum = 0; value_buf[i++] = ReadVol_CH3(); if( i == N ) { i = 0; } for( count = 0; count < N; count++ ) { sum += value_buf[count]; } return ( unsigned int )( sum / N ); }

           通过数组将采样的数据存储起来,若数组存满之后,数组下标直接跳转到数组头,覆盖最早采样的数据。然后再计算平均值 。但是用数组存储的话会浪费单片机大量的存储空间,如果采样的数据比较多,单片机的空间有可能不够用。所以为了节省单片机的空间,这里不用数组存储,而是用另一种方法来实现  。

        改进后的算法如下:

#define CNT 100 u16 get_ave( void ) { static u8 count = 0; static u32 S = 0; //累加和 static u16 C = 0; //本次采样值 static u16 A = 0; //平均值 C = ReadVol_CH3(); if( count == 0 ) { A = C; S = A * CNT; count = 1; } S = S - A + C; //加上本次采样值,减去上次平均值 A = S / N; //计算本次平均值 return A; }

      不用数组存储的话就不知道最早采样的值是多少,这里用上次采样的平均值代替最早的采样值。A代表上次采样的平均值,C代表本次采样的值,S代表100次数据的累加和,每次采样到新数据时,就用累加和减去上一次的平均值,然后再加上本次采样的值,计算出本次采样新的平均值。

   这样S就相当于连续100个数据的累加和,每次有新的数据进来之后,先减去旧的数据,再加上新的数据。这样计算出来的平均值就是连续的。下来测试一下优化算法。

 

这是函数发生器产的一个100HZ的正弦波,最小值是0V,最大值是4V,平均值是2.02V。单片机通过串口将采样回来的平均值发送出来,用串口波形显示软件,将采样值的波形显示出来。

通过串口波形软件可以看出,采样回来的值是波动的,说明优化后的采样算法更能实时的反应出来采样波形的波动情况。

在波形显示软件右下角可以看到,采样回来的值最小是419,最大是427,单片机ADC是10位分辨率 2^10=1024,所以采样的平均电压为 419/1024*5=2.0458984375V         427/1024*5=2.0849609375V  采样的平均值在2.04和2.08V之间波动。和示波器测出来的平均值2.02V有一点误差,误差最大值为0.06V左右,上一篇平均值采样法的最大误差为0.02V。

    改进后的平均值采样算法和上一篇单片机ADC采样算法---平均值采样法采样的值相比,误差增大了,但是相对于平均值采样法来看,采样的值能更快速的反应出采样数据的变化情况。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3