单片机/MCU论坛
直播中

穆宇

6年用户 14经验值
擅长:电源/新能源 MEMS/传感技术 控制/MCU
私信 关注
[问答]

求助!急求!STC12C5A60S2单片机 AD采样与定时器定时能否同时工作?

      STC12C5A60S2单片机,ad转换一直进行200ms,每次转换的结果都相加,200ms后求这么多次采样的平均值,平均值与某个值进行比较,然后再一次转换200ms,再求平均,再比较......这样一直循环下去。
      我用定时器定时50ms,4次中断后就是200ms,但是定时器开始工作后,ad转换能同时进行吗?还是定时器先工作,直到定时完50ms后才进行ad转换呢?
      新手求助,拜托各位大佬了!
void main()
{
       
        while(1)
        {
                n=0;
                sum=0;
                TMOD=0x01;                  
                TH0=0x4C;                  //11.0592MHZ晶振,定时50ms
                TL0=0;
                EA=1;
                ET0=1;
                TR0=1;                  //定时器开始工作
                while(n<=4)           //没到200ms就一直ad转换
                {
                        InitADC();                                                           //ad初始化
                        ADC_CONTR=ADC_POWER|ADC_SPEEDLL|P1ASF|ADC_START;
                        _nop_();
                        _nop_();
                        _nop_();
                        _nop_();
                        while(!(ADC_CONTR&ADC_FLAG));
                        ADC_CONTR&=~ADC_FLAG;                                 //一次ad转换结束
                        x=ADC_RES*256+ADC_RESL;
                        sum+=x;
                }
                //n=0;
                y=sum/2457;                                                          //求平均
                if(y>=31)                                                          //比较
                {       
                        D1=0;
                        Bee=0;
                }               
        }       
}

void InitADC()
{
        P1ASF=0X04;
        ADC_RES=0;
        AUXR1=0x04;
        ADC_CONTR=ADC_POWER|ADC_SPEEDLL;
        Delay(2);
}

void Delay(unsigned int n)
{
        unsigned int x;
        while(n--)
        {
                x=5000;
                while(x--);
        }       
}

void exter() interrupt 1
{
        TH0=0x4C;
        TL0=0;
        n++;       
}


回帖(6)

陈志超

2018-5-10 09:24:35
定时器是独立于cpu的外设   只要在初始化的时候设定了 模式和初值 他会自己不停的工作的,在你设置的定时器中断后  条件出发会进入中断,这时候cpu才会前去处理,所以说开启定时器之后ad是可以进行工作的
举报

穆宇

2018-5-10 10:18:25
引用: 向北c 发表于 2018-5-10 09:24
定时器是独立于cpu的外设   只要在初始化的时候设定了 模式和初值 他会自己不停的工作的,在你设置的定时器中断后  条件出发会进入中断,这时候cpu才会前去处理,所以说开启定时器之后ad是可以进行工作的

那定时器中断的时候,ad也在工作吗?因为我定时200ms,我想让ad在200ms内一直不间断工作
举报

人中狼

2018-5-10 10:32:29
这个问题取决于你的设计思路和目的,
定时50ms,如果定时到了时进行采样,那么200ms就是采样4次,
如果第一次采样开始进行定时,到200ms结束采样,定时50ms只是用来确定200ms是否到时,期间每次采样结束后就进行下一次采样,与定时器无关的话,那么200ms内的采样次数就取决于每次采样所需要的时间,这个次数通常都大于4次
举报

穆宇

2018-5-10 10:45:03
引用: 人中狼 发表于 2018-5-10 10:32
这个问题取决于你的设计思路和目的,
定时50ms,如果定时到了时进行采样,那么200ms就是采样4次,
如果第一次采样开始进行定时,到200ms结束采样,定时50ms只是用来确定200ms是否到时,期间每次采样结束后就进行下一次采样,与定时器无关的话,那么200ms内的采样次数就取决于每次采样所需要的时间,这个次数通常都大于4次 ...

我的思路是您说的第二种思路,是让采样次数大于4次的,但是我不知道我编的程序是不是这样的,能烦请您帮我看一下吗?
举报

人中狼

2018-5-10 13:05:02
试试这样改吧


unsigned char adc_times;


void main()

{
        n=0;
                sum=0;                adc_times = 0;
                TMOD=0x01;                  
                TH0=0x4C;                  //11.0592MHZ晶振,定时50ms
                TL0=0;               
                InitADC();                                                           //ad初始化
                EA=1;
                ET0=1;
                TR0=1;                  //定时器开始工作
        while(1)
        {
               
                while(n<=4)           //没到200ms就一直ad转换
                {
                        ADC_CONTR=ADC_POWER|ADC_SPEEDLL|P1ASF|ADC_START;
                        _nop_();
                        _nop_();
                        _nop_();
                        _nop_();
                        while(!(ADC_CONTR&ADC_FLAG));
                        ADC_CONTR&=~ADC_FLAG;                                 //一次ad转换结束
                        x=ADC_RES*256+ADC_RESL;
                        sum+=x;

                        adc_times ++;
                }
                n=0;
                y=sum/adc_times;                                                          //求平均
                if(y>=31)                                                          //比较
                {        
                        D1=0;
                        Bee=0;
                }         

               sum = 0;
               adc_times = 0;      
        }        
}



举报

武林

2018-5-10 15:51:29
//查询定时法ADC转换查程序,不受中断影响,适用于STC12/15系列单片机
#include                         //单片机头文件
#include                                 //库头文件
#define uint unsigned int                         //宏定义数据类型uint
#define uchar unsigned char                 //宏定义数据类型uchar
#define ulong unsigned long                        //宏定义数据类型ulong
//宏定义ADC的操作命令
#define ADC_POWER   0x80                        //ADC电源控制位
#define ADC_START   0x08                        //ADC启动控制位
#define ADC_FLAG    0x10                        //ADC完成标志位
//#define ADC_SPEEDLL 0x00                        //420时钟速度控制
#define ADC_SPEEDL  0x20                        //280时钟速度控制
//#define ADC_SPEEDH  0x40                        //140时钟速度控制
//#define ADC_SPEEDHH 0x60                        //70时钟速度控制
/********变量定义******/
uchar table[2];                                                //缓存
uint Average;                                                //ADC采样平均值变量
bit OUT=0;                                                        //输出标志
/*---------------------------------------------
  定时器0初始化,时钟12T、16位重载模式
----------------------------------------------*/
void Timer0Init(void)                                //2毫秒@11.0592MHz
{
        AUXR &= 0x7F;                                        //定时器时钟12T模式
        TMOD &= 0xF0;                                        //设置定时器自动重载模式
        TL0 = 0xCD;                                                //设置定时初值
        TH0 = 0xF8;                                                //设置定时初值
        TF0 = 0;                                                //清除TF0标志
        TR0 = 1;                                                //定时器0开始计时
//        ET0=1;                                              //允许T0中断
//        EA=1;                                               //开全局中断
}

/*-------------------------------
  1ms延时子程序(11.0592MHz 1T)
-------------------------------*/
void delayms(uint k)
{
        uint i,j;
        for(i=k;i>0;i--)
                for(j=1150;j>0;j--);
}
/*------------------------
  InitADC
-------------------------*/
void InitADC()
{
        P1ASF=0x01;                                                //设置P1的0通道端口作为模拟输入
        ADC_RES=0;                                                //清除ADC_RES存储器以前的结果
        ADC_RESL=0;                                                //清除ADC_RESL存储器以前的结果
        ADC_CONTR=ADC_POWER|ADC_SPEEDL; //ADC 开启电源、转换速度 1010 0000
        delayms(1);                                                //上电延时1ms                                                                                       
}
/*---------------------------
Get ADC Result
----------------------------*/
uint Read(uchar CHA)                                //获取ADC结果
{
        ADC_CONTR=ADC_POWER|ADC_SPEEDL|CHA|ADC_START;//启动转换1010 1000
    _nop_();                               //延时确保正确读到ADC_CONTR寄存器的值
    _nop_();
    _nop_();
    _nop_();
        while(!(ADC_CONTR & ADC_FLAG));        //等待ADC转换完成标志置位 1011 1000
        ADC_CONTR &=~ADC_FLAG;                        //关闭ADC
        return(ADC_RES*4+ADC_RESL);                //返回十位ADC结果
}

/****** ADC滤波子程序*******/
void LB_ADC()
{
        static ulong PJZ_ADC=0;                        //累加100次采样的变量
        static uchar count=0;                        //计数器变量
        PJZ_ADC += Read(0);                                //第1通道累加100次采样
        count++;                                                                //计数器变量自+1
        if(count>=100)                                                //如果计数到100次采样
        {
                count=0;                                                        //计数器清0
                Average=((PJZ_ADC+5)/100);        //获取平均值含四舍五入
                PJZ_ADC=0;                                                //采样变量清0
                OUT=1;                                                        //输出标志置1
        }
}
/*******计时采样程序***********/
void Time()       
{
        if(TF0==1)                                                //如果查询定时器溢出标志TF0为1
        {                                                                //定时器溢出周期2ms
                TF0=0;                                                //定时器溢出标志TF0清0
                LB_ADC();                                        //采用滤波
        }
}
/************数据解析保存*************/
void analysis()
{
        if(OUT==1)
        {
                OUT=0;
                table[0]=Average>>8;        //保存高8位数据
                table[1]=Average;                //保存低8位数据       
        }
}
/*********主函数****************/
void main()                                                       
{
        P1M1 = 0x01;                                         //设置P1.0高阻
        P1M0 = 0x00;                                         //设置P1.0高阻
        InitADC();                                                //初始化ADC
        Timer0Init();                                        //初始化定时器0
        while(1)
        {
                Time();                                                //运行计时采样程序
                analysis();                                        //200ms刷新缓存数据
        //可以插入计算/查表/显示/串口程序
        }
}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分