标题: 单片机AD采样,算术平均滤波后得到的数据出错 [打印本页]

作者: 1027669350    时间: 2021-11-16 09:45
标题: 单片机AD采样,算术平均滤波后得到的数据出错
请教各位大佬,我想用51单片机写一个定时器每10ms进行一次AD采样,对16次的采样值进行算术平均滤波,采样函数和滤波函数都应该在哪调用,中断还是主函数?

作者: wyqf    时间: 2021-11-16 10:59
采样函数和滤波函数均在主函数中调用,使用标记位的方式,在主函数中去检测标记位是否被触发,然后执行相应的函数即可
作者: 小黑屋525    时间: 2021-11-16 11:43
滤波在主函数最好,ADC转换完成一般也可以有个引脚触发中断,在这个中断读取转换的值就好了,只要中断里面不加延时函数一般都没多大问题的。
作者: Y_G_G    时间: 2021-11-16 13:05
在中断中进行ADC数字量的累加和平均,最大值最多加到一个32位整型数据,256次以下的累加用不了多少时间的,平均后的数据存放到一个全局变量中,在主程序中通过这个全局变量来处理就可以
中断中不能有延时,等待,浮点运算
作者: 1027669350    时间: 2021-11-16 13:46
本帖最后由 1027669350 于 2021-11-16 15:57 编辑
Y_G_G 发表于 2021-11-16 13:05
在中断中进行ADC数字量的累加和平均,最大值最多加到一个32位整型数据,256次以下的累加用不了多少时间的,平 ...

不好意思,问一个低级的问题,我这样写数码管是不会显示的,能帮忙修改一下吗
void main()
{
        adcs=0;
        Init();
        while(1)
        {
                display(2*value);
        }
}
//定时器中断函数
void time0() interrupt 1
{
        
        TH0=(65536-9174)/256;      //重新装入初值
  TL0=(65526-9174)%256;
        num++;
        myvalue=getad();
        sum+=myvalue;
     
        if(num==16)
        {
                value=sum/16;
        }
}
作者: 13205495918    时间: 2021-11-16 14:37
主函数里面吧,
作者: 188610329    时间: 2021-11-16 16:42
我很好奇,你怎么会认为:“每10ms进行一次AD采样,对16次的采样值进行算术平均滤波,” 这个操作对“滤波”是最优解的?
我们撇开Hz率不讲,举个现实中的例子, 要统计地铁的平均客流量, 是每天定时去采样1小时,连续30天(共计30小时)来的准确,还是, 直接去连续统计24小时平均后来的准确?
作者: 1027669350    时间: 2021-11-16 16:52
188610329 发表于 2021-11-16 16:42
我很好奇,你怎么会认为:“每10ms进行一次AD采样,对16次的采样值进行算术平均滤波,” 这个操作对“滤波 ...

那我应该采用什么方法进行采样和滤波呢,刚接触这一方面,知道的太少了

作者: azjdly    时间: 2021-11-16 17:13
耗时时间短的操作在中断里去做,耗时时间长的如计算在主函数做
作者: 188610329    时间: 2021-11-16 17:22
1027669350 发表于 2021-11-16 16:52
那我应该采用什么方法进行采样和滤波呢,刚接触这一方面,知道的太少了

采样不要用定时器间隔,直接连续采样,计算可以参考地板。
作者: Y_G_G    时间: 2021-11-16 17:29
1027669350 发表于 2021-11-16 16:52
那我应该采用什么方法进行采样和滤波呢,刚接触这一方面,知道的太少了

ADC采用中断方式呀
我一开始没有认真看,还以为你是采用ADC中断模式
ADC采用中断模式,128次ADC累加后,取平均值就行,我试过,去不去掉这个最大和最小值,对于结果影响并不大,可以说是没啥效果以下是我STC8G的ADC,你参考一下
/*stc8g系列单片机ADC程序*/

#include "Stc8g.h"
#include "Stc8g_Adc.h"
#define         ADC_P10 0x80
#define         ADC_P11 0x81
#define         ADC_P12 0x82
#define         ADC_P13 0x83
#define         ADC_P14 0x84
#define         ADC_P15 0x85
#define         ADC_P16 0x86
#define         ADC_P17 0x87
#define         ADC_P1f 0x8f
#define     ADC_COUNT 128
/*需要在主程序使用以下变量,可以在变量声明前加上 extern 来声明,就可以直接调用了*/
//──────────────────────────────────────────────────────────────────────────────────

unsigned char                          ADC_LINE;                //ADC通道记录
unsigned long int                 ADC_AN7;                //ADC0数据
unsigned long int                 ADC_ANf;                //ADCf数据                  
//──────────────────────────────────────────────────────────────────────────────────
void Stc8g_Adc_int()//stc8gadc初始化
{
        unsigned int i;
        P1M0=0;
        P1M1=0x80;                //p1.7用作ADC端口       
        ADC_CONTR=0x80;//打开adc电源
        ADCCFG=0x2f;        //设定ADC转换结果保存格式       
        for(i=10000;i>0;i--);            //延时
        ADC_LINE=ADC_P1f;
        ADC_CONTR=ADC_CONTR|0x40;        //启动ADC
        EADC=1;
}
//──────────────────────────────────────────────────────────────────────────────────
void Adc_Isr() interrupt 5                         //Adc中断函数
{

static unsigned char                          count7;                        //ADC通道6转换次数记录
static unsigned char                          countf;                        //ADC通道f转换次数记录,内部参考电压通道
static unsigned long int                 ADC_DATA7;                //ADC0数据,累加
static unsigned long int                 ADC_DATAf;                //ADCf数据,累加               
ADC_CONTR=ADC_CONTR&0xdf;                  //清除中断标志位
                //──────────────────────────────────────────────────────────────────────────
                if(ADC_LINE==ADC_P1f)                                                          //检测触发ADC中断的通道
                        {  
                                if(countf>=ADC_COUNT)                                         //检测ADC转换次数
                                        {
                                                 ADC_ANf=ADC_DATAf/ADC_COUNT;          //取平均值
                                                 ADC_DATAf=0x00;                                          //清除ADC累加结果
                                                 countf=0x00;                                          //清除ADC转换次数记录
                                        }
                                ADC_DATAf+=ADC_RES*256+ADC_RESL;                //ADC结果累加
                                countf++;                          
                                ADC_CONTR=ADC_LINE=ADC_P17;                                //选择下一个ADC通道
                        }
                //──────────────────────────────────────────────────────────────────────────
                else if(ADC_LINE==ADC_P17)
                        {  
                                if(count7>=ADC_COUNT)
                                        {
                                                 ADC_AN7=ADC_DATA7/ADC_COUNT;
                                                 ADC_DATA7=0x00;
                                                 count7=0x00;
                                        }
                                ADC_DATA7+=ADC_RES*256+ADC_RESL;       
                                count7++;                                                          
                                ADC_CONTR=ADC_LINE=ADC_P1f;
                        }
                //──────────────────────────────────────────────────────────────────────────                  
ADC_CONTR=ADC_CONTR|0x40;                                                                //启动ADC
}


作者: yzwzfyz    时间: 2021-11-18 15:02
采样在中断中进行,计算在主程序是进行。




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1