打印
[PIC®/AVR®/dsPIC®产品]

PIC16F1937 AD问题,不是菜鸟遇到的问题,请教各位

[复制链接]
2820|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
MIKEZHONG|  楼主 | 2014-11-10 11:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请各位版主,及大侠看看。

    程序看了一遍又一遍,看不出问题,我在16F726上也用过没有发现问题,会不会是PIC 16F1937的BUG?

/*
  我用到PIC16F1937,QFP44脚的单片机。用到机器上我们发现AD的问题,我们这个AD用来检测NTC的温度,同时如果NTC开路了,或NTC短路了,
  检测到后会停机报警。

  问题是:一台机器运行一天,可能不会出问题,但有时运行1小时就会出现ERR2(NTC开路了)的报警。我查了原因就是在case 4:中的ntc1avr,
          当出现问题时,ntc1avr值很大为255,我是用的8位的,正常时一般在200以下,我用串口打印出来ADRESH,读出来就是FF,此时NTC上
          的电压值一定在200以下。要过一段时间又会正常,或者重新上电。

  我的分析,可能是这个AD这里有问题,因为我以前判断ADGO是否为0来判断(没有加超时判断)是否转换完成,就会出现一直转换不完成的情况,
            但是加了超时后发现,它转换出来的值也不对。为FF

*/
//***************************************************
//ADC检测子程序,
//***************************************************
void AdcAction(void)
{
    unsigned int sum,j;
    unsigned char max,min,i,delay,n;
    unsigned char i;
    if (adc2msfg ==1)
    {
            adc2msfg=0;
        switch (adcmode)
        {
          case 0://----检测RA0通道-----------------------------
                 ADCON1 = 0b00110000; //0b01010000;//
                 ADCON0 = 0b00000001;    //转换结果右对齐,通道0,AD模块开始工作。Fosc/32, CH=0, ADON
                 for (delay=20;delay;--delay);
                 ADGO = 1;//启动AD转换
                 //while(ADGO);//转换完毕,跳出。
                 j=40000;
                 while ((j!=0)&&ADGO)
                 {
                    nop();
                    j--;
                 }
                 adc0_value[0] = ADRESH;

                 max=adc0_value[0];
                 min=adc0_value[0];
                 sum=adc0_value[0];
                 n=34; //34次取采样,去掉最大,最小,余下的平均
                 for (i=n-1;i!=0;i--)
                 {
                    if (adc0_value[i]>max)
                        max=adc0_value[i];
                    else if (adc0_value[i]<min)
                        min=adc0_value[i];
                    sum=sum+adc0_value[i];
                    adc0_value[i]=adc0_value[i-1];

                 }
                 i=n-2;
                 sum=sum-max-min+i/2;
                 sum=sum/i;
                 ra0_adcvalue=(unsigned char)sum;
                 adcmode=1;
                 break;
          case 1://----检测RA1通道----------------
                 ADCON1 = 0b00110000; //0b01010000;// ADCON1 = 0b01010000;//
                 ADCON0 = 0b00000101;     //转换结果右对齐,通道1,AD模块开始工作。Fosc/32, CH=0, ADON
                 for (delay=20;delay;--delay);
                 ADGO = 1;//启动AD转换
                 //while(ADGO);//转换完毕,跳出。
                 j=40000;
                 while ((j!=0)&&ADGO)
                 {
                    nop();
                    j--;
                 }
                 adc1_value[0] = ADRESH;
                 max=adc1_value[0];
                 min=adc1_value[0];
                 sum=adc1_value[0];
                 n=34; //34次取采样,去掉最大,最小,余下的平均
                 for (i=n-1;i!=0;i--)
                 {
                    if (adc1_value[i]>max)
                        max=adc1_value[i];
                    else if (adc1_value[i]<min)
                        min=adc1_value[i];
                    sum=sum+adc1_value[i];
                    adc1_value[i]=adc1_value[i-1];

                 }
                 i=n-2;
                 sum=sum-max-min+i/2;
                 sum=sum/i;
                 ra1_adcvalue=(unsigned char)sum;
                 adcmode=2;
                 break;
          case 2://----检测RA5通道----------------
                 ADCON1 = 0b00110000; //0b01010000;//ADCON1 = 0b01010000;//
                 ADCON0 = 0b00010101;    //转换结果右对齐,通道0,AD模块开始工作。Fosc/32, CH=0, ADON
                 for (delay=20;delay;--delay);
                 ADGO = 1;//启动AD转换
                 //while(ADGO);//转换完毕,跳出。
                 j=40000;
                 while ((j!=0)&&ADGO)
                 {
                    nop();
                    j--;
                 }
                 adc2_value[0] = ADRESH;
                 max=adc2_value[0];
                 min=adc2_value[0];
                 sum=adc2_value[0];
                 n=34; //34次取采样,去掉最大,最小,余下的平均
                 for (i=n-1;i!=0;i--)
                 {
                    if (adc2_value[i]>max)
                        max=adc2_value[i];
                    else if (adc2_value[i]<min)
                        min=adc2_value[i];
                    sum=sum+adc2_value[i];
                    adc2_value[i]=adc2_value[i-1];

                 }
                 i=n-2;
                 sum=sum-max-min+i/2;
                 sum=sum/i;
                 ra2_adcvalue=(unsigned char)sum;
                 adcmode=3;
                 break;
          case 3://----检测RA3通道----------------
                 ADCON1 = 0b00110000; //0b01010000;//ADCON1 = 0b01010000;//
                 ADCON0 = 0b00001101;    //转换结果右对齐,通道0,AD模块开始工作。Fosc/32, CH=0, ADON
                 for (delay=20;delay;--delay);
                 ADGO = 1;//启动AD转换
                 //while(ADGO);//转换完毕,跳出。
                 j=40000;
                 while ((j!=0)&&ADGO)
                 {
                    nop();
                    j--;
                 }
                 adc3_value[0] = ADRESH;
                 uarttestntc2avr=adc3_value[0];
                 if (uarttestntc2avr <=28)
                 {
                    uarttestntc2avr=28;       
                 }               
                 max=adc3_value[0];
                 min=adc3_value[0];
                 sum=adc3_value[0];
                 n=34; //34次取采样,去掉最大,最小,余下的平均
                 for (i=n-1;i!=0;i--)
                 {
                    if (adc3_value[i]>max)
                        max=adc3_value[i];
                    else if (adc3_value[i]<min)
                        min=adc3_value[i];
                    sum=sum+adc3_value[i];
                    adc3_value[i]=adc3_value[i-1];

                 }
                 i=n-2;
                 sum=sum-max-min+i/2;
                 sum=sum/i;
                 ra3_adcvalue=(unsigned char)sum;
                 ntc2avr=ra3_adcvalue;
                 //--------ntc2-------------------------
                 if ((ntc2avr <=4)&&(ntcerrorfg==0)) //NTC短路
                 {
                           ntc2shortcnt++;
                           if (ntc2shortcnt >= 6000)//60s
                           {
                              ntc2shortcnt=0;
                              ntcerrorfg=1; //NTC故障。
                              ntcerrmode=3; //NTC2
                            
                       testgunfg=0; //test
                       heatercompletefg=0;
                       startstopfg=0;
                           }
                 }
                 else
                 {
                         ntc2shortcnt=0;
                 }
                 if (ntc2avr <=28)
                 { ntc2avr=28;}
                 adcmode=4;
                 break;
          case 4://----检测RA4通道----------------
                 ADCON1 = 0b00110000; //0b01010000;//ADCON1 = 0b01010000;//
                 ADCON0 = 0b00010001;    //转换结果右对齐,通道0,AD模块开始工作。Fosc/32, CH=0, ADON
                 for (delay=20;delay;--delay);
                 ADGO = 1;//启动AD转换
                 //while(ADGO);//转换完毕,跳出。
                 j=40000;
                 while ((j!=0)&&ADGO)
                 {
                    nop();
                    j--;
                 }
                 adc4_value[0] = ADRESH;
                 max=adc4_value[0];
                 min=adc4_value[0];
                 sum=adc4_value[0];
                 n=34; //34次取采样,去掉最大,最小,余下的平均
                 for (i=n-1;i!=0;i--)
                 {
                    if (adc4_value[i]>max)
                        max=adc4_value[i];
                    else if (adc4_value[i]<min)
                        min=adc4_value[i];
                    sum=sum+adc4_value[i];
                    adc4_value[i]=adc4_value[i-1];
                 }
                 i=n-2;
                 sum=sum-max-min+i/2;
                 sum=sum/i;
                 ra4_adcvalue=(unsigned char)sum;
                 ntc1avr=ra4_adcvalue;
                 //----------锅炉NTC短路检测----------
                 if ((ntc1avr <=4)&&(ntcerrorfg==0)&&(startstopfg==1)) //机器启动后再检测NTC短路
                 {
                           ntc1shortcnt++;
                           if (ntc1shortcnt >= 6000)//60s
                           {
                              ntc1shortcnt=0;
                              ntcerrorfg=1; //NTC故障。
                              ntcerrmode=1; //NTC1
                             
                       testgunfg=0; //test
                       heatercompletefg=0;
                       startstopfg=0;

                       //dispten_buf=~0x86;//e
                       //dispone_buf=~0xF9;//1
                           }
                }
                else
                {
                           ntc1shortcnt=0;
                }


                 if (ntc1avr <=28)
                 { ntc1avr=28;}
                 adcmode=0;
                 break;
          default:
                 break;
        }
    }
}

//-------------------------------------------------------
//这是在其它函数中调用的用来检测NTC开路的。
//-------------------------------------------------------
            if (ntc1avr >=245) //温度仍低于10度
            {
                    ntc1opencnt++;
                if (ntc1opencnt >=3000)
                {
                   ntc1opencnt=0;

                   ntcerrorfg=1;
                   ntcerrmode=2; //ntc1

                   L_HEATER_LOW();//机器停止工作
                   testgunfg=0; //test
                   heatercompletefg=0;
                   startstopfg=0;
                   //Stspledoff(); //启动/停止灯灭
                   //Heaterledoff(); //灭加热LED
                   //dispten_buf=~0x86;//e
                   //dispone_buf=~0xf9;//1
                   //beepfg=1;   //打开蜂鸣器响
                   //beepcnt=1;  //响多少10次
                   //beeptime=80;//决定响的间隔
                }
            }
            else
            {
                    ntc1opencnt=0;
            }

沙发
yklstudent| | 2014-11-10 19:29 | 只看该作者
这种代码,简直让人无法忍受,呵呵

使用特权

评论回复
板凳
yewuyi| | 2014-11-11 09:57 | 只看该作者

#define              ADCHS              0b00001100
#define              AD0                  0b00000000
#define              AD1                  0b00000100
#define              AD2                  0b00001000
#define              AD3                  0b00001100

#define              InitAD0()            ADCON0=0b00000001
#define              InitAD1()            ADCON0=0b00000101
#define              InitAD2()            ADCON0=0b00001001
#define              InitAD3()            ADCON0=0b00001101

uint                    AdVal;
uchar                  MeasureCount;

void                    Measure(void)
{
if(MeasureCount<64){
                               if(!MeasureCount){AdVal=0;}
                               GO_nDONE=true;
                               while(GO_nDONE){}
                               AdVal+=(ADRESH<<8)+ADRESL;
                               MeasureCount++;
                              }
else{
    MeasureCount=0;
    switch(ADCON0&ADCHS){
                                       case AD0:
                                                    InitAD1();
                                                    break;
                                       case AD1:
                                                    InitAD2();
                                                    break;
                                       case AD2:
                                                    InitAD3();
                                                    break;
                                       case AD3:
                                                    InitAD0();
                                                    break;
                                       default:   Rstmcu();
                                                    break;
                                       }
    }
}

使用特权

评论回复
地板
yewuyi| | 2014-11-11 09:59 | 只看该作者
临时给你写了一个范例,if(MeasureCount<64)的意思就是对一个通道累计连续采集64次,64次的AD值累加后保存在AdVal变量中

使用特权

评论回复
5
MIKEZHONG|  楼主 | 2014-11-14 10:57 | 只看该作者
谢谢Yewuyi无私帮助,我后面尝试解决了。

问题在:
1,切换AD通道的时间短了,我之前是用的2MS,后面改用了20MS。

   但是看规格书,切换通道不需要这么久吧?

2,MAX,MIN处理程序有点问题,改了。

使用特权

评论回复
6
MIKEZHONG|  楼主 | 2014-11-14 10:58 | 只看该作者
j=200;
                 ADokfg=0;
                 while (--j)
                 {
                    if (ADGO==0)
                    {
                       ADokfg=1;
                       break;
                    }
                 }
                 if (ADokfg ==1)
                 {
                   ADokfg=0;
                   for (i=17;i!=0;i--) //先移位
                   {
                      adc2_value[i]=adc2_value[i-1];       
                   }
                   adc2_value[0] = ADRESH;
                 
                   max=adc2_value[0];
                   min=adc2_value[0];
                   sum=adc2_value[0];
                   for (i=1;i<18;i++)
                   {
                    if (adc2_value[i]>max)
                        max=adc2_value[i];
                    else if (adc2_value[i]<min)
                        min=adc2_value[i];
                    sum=sum+adc2_value[i];
                   }
                   sum=sum-max-min;
                   sum=sum/16;
                   ra2_adcvalue=(unsigned char)sum;
                 }

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

51

主题

250

帖子

1

粉丝