单片机过采样程序递归方法实现,程序直接用

我们知道采样四次,做一次右移可提升一位精度那么

 

过采样技术原理介绍

假定环境条件: 10位ADC最小分辨电压1LSB 为 1mv 

假定没有噪声引入的时候, ADC采样上的电压真实反映输入的电压, 那么小于1mv的话,如ADC在0.5mv是数据输出为0 
我们现在用4倍过采样来, 提高1位的分辨率, 
当我们引入较大幅值的白噪声: 1.2mv振幅(大于1LSB), 并在白噪声的不断变化的情况下, 多次采样, 那么我们得到的结果有 
真实被测电压    白噪声叠加电压    叠加后电压    ADC输出    ADC代表电压 
   0.5mv             1.2mv          1.7mv          1           1mv 
   0.5mv             0.6mv          1.1mv          1           1mv 
   0.5mv            -0.6mv         -0.1mv          0           0mv 
   0.5mv            -1.2mv         -0.7mv          0           0mv 
ADC的和为2mv, 那么平均值为: 2mv/4=0.5mv!!!  0.5mv就是我们想要得到的 
这里请留意, 我们平时做滤波的时候, 也是一样的操作喔!  那么为什么没有提高分辨率????? 

是因为, 我们做滑动滤波的时候, 把有用的小数部分扔掉了, 因为超出了字长啊, 那么0.5取整后就是 0 了, 结果和没有过采样的时候一样是 0 ,  

而过采样的方法时候是需要保留小数部分的, 所以用4个样本的值, 但最后除的不是4, 而是2!  那么就保留了部分小数部分, 而提高了分辨率! 
从另一角度来说, 变相把ADC的结果放大了2倍(0.5*2=1mv), 并用更长的字长表示新的ADC值,  
这时候, 1LSB(ADC输出的位0)就不是表示1mv了, 而是表示0.5mv, 而(ADC输出的位1)才是原来表示1mv的数据位,  

下面来看看一下数据的变化: 

ADC值相应位                    9 8 7 6 5 4 3 2 1 0 
0.5mv测量值                    0 0 0 0 0 0 0 0 0 0   0mv(10位ADC的分辨率1mv,小于1mv无法分辨,所以输出值为0)            
叠加白噪声的4次过采样值的和    0 0 0 0 0 0 0 0 1 0   2mv 
滑动平均滤波2mv/4次            0 0 0 0 0 0 0 0 0 0   0mv(平均数, 对改善分辨率没作用) 
过采样插值2mv/2              0 0 0 0 0 0 0 0 0 0 1   2mv/2=0.5mv, 将这个数作为11位ADC值, 那么代表就是0.5mv 
                                                     这里我们提高了1位的ADC分辨率 

这样说应该就很简单明白了吧, 其实多出来的位上的数据, 是通过统计输入量的分布, 计算出来的,  
而不是硬件真正分辨率出来的, 引入噪声并大于1LSB, 目的就是要使微小的输入信号叠加到ADC能识别的程度(原ADC最小分辨率). 

 

#include <QCoreApplication>
#include <string.h>
#include <QTime>
 
//此处进行一次采样
unsigned int mydata()
{
    unsigned int data=0;
    data=qrand()%65535;
    return data;
}
 
//四次采样增加一位精确度
 
 
unsigned int oversampling(unsigned char Places,unsigned int (*p)(void))
{
    unsigned char i=0;
    unsigned int sum=0;
 
    if(Places==1)
    {
        for(i=0;i<4;i++)
            sum+=p();
        sum=sum>>1;//提升一位精度
        return sum;
    }
    else
    {
        for(i=0;i<4;i++)
            sum+=oversampling(Places-1,p);
        sum=sum>>1;//提升一位精度
        return sum;
    }
}
 
 
 
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
 
    printf("%ld\n",oversampling(6,mydata));
 
    return a.exec();
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值