请各位版主,及大侠看看。
程序看了一遍又一遍,看不出问题,我在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;
}
|