微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > MEGA16 ADC数据存储与匹配问题(求大神)

MEGA16 ADC数据存储与匹配问题(求大神)

时间:10-02 整理:3721RD 点击:
思路:在录入模式依次读取ADC数据存入数组Q,在匹配模式读取ADC数据与Q进行逐项匹配
问题:ADC读入相同的数据,在匹配模式总是不匹配
#define  SBIT(x,y)   (x|=(1<<y))                        //设置某端口为1
#define  CBIT(x,y)   (x&=~(1<<y))                //设置某端口为0
#define  GBIT(x,y)   (x&(1<<y))                        //得到某端口数据
#define  LEDPORT      PORTC        //数码管段码
#define  COMPORT      PORTD        //数码管位控制
#define  KEY_SET     0              //设置按键
#define  KEY_SET_PORT     PINB    //设置按键
#define        GetSet                        (GBIT(KEY_SET_PORT,KEY_SET))
#define  KEY_INC     1              //加按键
#define  KEY_INC_PORT     PINB    //加按键     
#define        GetInc                        (GBIT(KEY_INC_PORT,KEY_INC))
#define  KEY_DEC     2              //减按键
#define  KEY_DEC_PORT     PINB    //减按键     
#define        GetDec                        (GBIT(KEY_DEC_PORT,KEY_DEC))
#define  MCU_CLK  8     //单片机使用8M晶振
#define  us MCU_CLK     //us延时单位
#define  ms MCU_CLK*1000//ms延时单位
#define  delay    __delay_cycles

#define        uchar unsigned char

//******************************共阴数码管段码表*******************************//
unsigned char __flash DSYC[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
                     0x77,0x7c,0x39,0x5e,0x79,0x71,0x40,0x3e,0x38,0x77,0x73};
                     //a    b    c   d     e   f    -    V    L
                     //10   11   12  13    14  15   16   17   18
unsigned char fSet=0;   //设置状态标志位
unsigned char st=0;     //数码管扫描标志
unsigned char ut=15,bai=0,shi=0,ge=0;  //每位数码管显示值
unsigned char k=0,j=0,c=0;     //电压值和匹配差值,读取数据次数
unsigned char MQ2Val=0,set=0,AlarmVal=5;
unsigned char Q[]={0,0,0,0,0,0,0};     //存储数据

void MCU_Initial(void)
{
   DDRA=0x00;DDRB=0xf0;DDRC=0xff;DDRD=0xff;  //设置A口输入,B口高4位输出、第四位输入,C、D口输出
   PORTA=0x00;PORTB=0xff;PORTC=0xff;PORTD=0xff;
}

void delayus(int x)
{
   for(;x>0;x--) ;
}

void delayms(int x)
{
   for(;x>0;x--) delayus(1000);
}
/*--------------------------------------------------------
函数名称:Timer1_Initial
函数功能:定时器1初始化
注意事项:
提示说明:
输    入:
返    回:
---------------------------------------------------------*/
void Timer1_Initial(void)
{
   TCCR1A=0x00;   //定时器1设置定时模式,分频系数为1
   TCCR1B=0x01;
   TIMSK=1<<TOIE1;   //允许定时器1中断
   TIFR=1<<TOV1;     //清除定时器1中断标志
   SREG|=0x80;       //启动中断
   TCNT1=50000;      //定时器赋初始值
}

/*--------------------------------------------------------
函数名称:Timer1
函数功能:定时器1用来动态扫描数码管显示
注意事项:
提示说明:
输    入:
返    回:
---------------------------------------------------------*/
//#pragma vector=TIMER1_OVF_vect
#pragma interrupt_handler Timer1_break:9
void Timer1_break(void)
{
   TCNT1=50000;//
   switch(st)
   {
      case 0:  st=1;COMPORT=0xff;LEDPORT=DSYC[ut];COMPORT=0xfe;break;   //第1位显示
      case 1:  st=2;COMPORT=0xff;LEDPORT=DSYC[bai];COMPORT=0xfd;break;  //第2位显示
      case 2:  st=3;COMPORT=0xff;LEDPORT=DSYC[shi];COMPORT=0xfb;break;  //第3位显示
      case 3:  st=0;COMPORT=0xff;LEDPORT=DSYC[ge];COMPORT=0xf7;break;   //第4位显示
   }
}

/*--------------------------------------------------------
函数名称:ADC_Initial
函数功能:AD初始化
注意事项:
提示说明:
输    入:
返    回:
---------------------------------------------------------*/
unsigned char ADC_Initial(void)
{
   ADMUX=0x60; //设置VCC参考电压
   ADCSRA=0xd6;   //启动ADC转换,8位数据模式
   while(ADCSRA&0x10==0);  //等待转换完成
   ADCSRA|=0x10;  //清除转换标志位
   return ADCH;   //返回AD转换值
}
/*--------------------------------------------------------
函数名称:ADC_ch
函数功能:读取AD值
注意事项:
提示说明:
输    入:
返    回:
---------------------------------------------------------*/
unsigned char ADC_ch(void)
{
   unsigned char i=0;  
   ADMUX=0x60;  //设置VCC参考电压,读取0通道
   delayms(1);         
   ADCSRA|=0x40; //启动ADC转换
   while(ADCSRA&0x10==0);//等待转换完成
   ADCSRA|=0x10;//清除转换标志位
   i=ADCH;
   return i;   //返回AD转换值   
}

/*--------------------------------------------------------
函数名称:KeyFuntion
函数功能:按键功能函数,实现设置匹配功能
注意事项:
提示说明:
输    入:
返    回:
---------------------------------------------------------*/
void KeyFuntion(void)
{
   if(GetSet==0)  //设置按键按下
   {
      delayms(10);  //延时防抖
      if(GetSet==0)//设置按键按下
      {
         if(fSet==1) fSet=0;  //按键之前功能判断,之前是在设置模式时,退出设置模式
         else
         {
            fSet=1;  //设置模式
            ut=15;   //显示F
         }
         while(GetSet==0); //等待按键松开
      }
   }
   if(fSet==1)//设置模式
   {
      if(GetInc==0)//录入按键按下
      {
         delayms(10);
         if(GetInc==0)  //录入按键按下
         {
            k++;
                    Q[k]=ADC_ch();  //读取AD值
            bai=0; //显示报警值
            shi=0;
            ge=k;
            while(GetInc==0);//等待按键松开
         }
      }
      if(GetDec==0)//匹配按键按下
      {
         delayms(10);
         if(GetDec==0)  //匹配按键按下
         {
                    set=ADC_ch();  //读取AD值
                    if(set==Q[j])
                        {
            ut=11;   //显示对应数字
            bai=0;   //转换显示值到对应位
            shi=0;
            ge=j;
                        j++;
                        }
                    else
                        {
                    ut=18;   //不匹配
                    bai=0;   //转换显示值到对应位
            shi=0;
            ge=0;   
                        }
         }
      }
   }
}
/*--------------------------------------------------------
函数名称:main
函数功能:
注意事项:
提示说明:
输    入:
返    回:
---------------------------------------------------------*/
void main( void )
{
   MCU_Initial(); //单片机IO设置
   Timer1_Initial(); //定时器1初始化设置
   ADC_Initial(); //内部AD初始化设置
   while(1)
   {
      if(fSet==0) //非设置状态
      {
             ut=10;
         MQ2Val=ADC_ch();  //读取AD值
                 bai=MQ2Val/100;   //转换显示值到对应位
         shi=MQ2Val%100/10;
         ge=MQ2Val%10;
      }
      KeyFuntion();  //按键功能
   }
}

没有仔细看您的程序,但可以提出思路供选择:
1. 采用DMA方式,将一次需要读取的ADC数量存放在内存中,在定义的时间依次读出判别所需。这种方法实际上利用DMA技术存储量大并且速度较快。
2. 采用数组方式,先定义一个够用的数组,将每次读取的数据顺序存入数组,再在需要的时间读取判别,这种方法技术简单,操作容易,但数组占用内存。
此外的问题是:ADC读取的数值要完全匹配会有问题,建议在一个允差范围就是需要的ADC值即可。这个允差可以计算得出,也可实验后得出。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top