单片机型号:STC8A8K64S4A12 @24MHz
BUG描述:
多个ADC通道全部放在main函数while(1)主循环内轮询采样不会出问题,但是如果主循环内有ADC采样,定时器中断也调用ADC,则程序很容易出现假死现象。
我的程序有多个ADC通道没有时序要求放在主循环内采样,有另外两通道用于AC有效值检测的放在500uS的定时器中断内调用ADC采样。自己调试假死都停在ADC的while (!(ADC_CONTR & ADC_FLAG));语句上,就是ADC转换完成标识硬件不置1了?!而定时器中断任然能正常并不是真正跑飞,只是程序回不到main函数。
五一只放假1天早已经开始搬砖,这个问题折腾了好两天还是没解决,欸,大家帮忙看看吧,谢了! ,具体看代码吧,注释<---箭头指的部分是调试记录,,,大家能提供一些程序调试方法也好的,比如变量内存、堆栈溢出之类的问题如何debug
以下程序运行正常:
void main()
{
//...初始化过程...
while(1)
{
if(T1ms>=100) //T1定时中断1ms加1
{
T1ms = 0;
P77 = !P77; //main函数心跳指示灯,(示波器观察)100ms电平翻转正常 <---
ADC3 = GetADCResult(3);
ADC4 = GetADCResult(4);
ADC5 = GetADCResult(5);
ADC6 = GetADCResult(6);
//...其它程序...
}
if(1==T2_Flag) //T2定时中断500us 标识符
{
T2_Flag = 0;
AC1_Buffer[AC_Samples] = GetADCResult(1); //UAC1
AC2_Buffer[AC_Samples] = GetADCResult(2); //UAC2
if(++AC_Samples>=40) //采样数满40个(一个周期)
{
AC_Samples = 0;
AC_Volt_Sampling(); //计算均方根值+平均滤波
P43 = !P43; //(示波器观察)电平翻转正常,但是翻转时间不能保证每次都是(500*40)us <---
}
}
}
}
void TMR2_Isr() interrupt 12 //TMR2定时中断 500uS
{
AUXINTIF &= ~T2IF; //清T2中断标志
T2_Flag = 1;
}
unsigned int GetADCResult(unsigned char ch) //读取ADC结果,这个采样函数应该没问题
{
unsigned int ADCValue;
ADC_CONTR = ADC_POWER | ADC_START | ch;
while (!(ADC_CONTR & ADC_FLAG)); //等待ADC转换完成
ADC_CONTR &= ~ADC_FLAG; //清完成标志
ADCValue = (ADC_RES<<4)+(ADC_RESL>>4); //
return ADCValue; //返回ADC结果
}
而以下程序运行容易假死,而且把其它函数的调用时间间隔改越短越容易死机,比如if(T1ms>=100)调成10几秒钟就跑停了:
void main()
{
//...初始化过程...
while(1)
{
if(T1ms>=100) //T1定时中断1ms加1
{
T1ms = 0;
P77 = !P77; //main函数心跳指示灯,(示波器观察)假死后电平不翻转! <---
ADC3 = GetADCResult(3);
ADC4 = GetADCResult(4);
ADC5 = GetADCResult(5);
ADC6 = GetADCResult(6);
//...其它程序...
}
if(1==T2_Flag) //T2定时中断500us
{
T2_Flag = 0;
AC_Volt_Sampling(); //有效值计算+平均值滤波
}
}
}
void TMR2_Isr() interrupt 12 //TMR2定时中断 500uS
{
AUXINTIF &= ~T2IF; //清T2中断标志
//AC采样
AC1_Buffer[AC_Samples] = GetADCResult(1); //UAC1
AC2_Buffer[AC_Samples] = GetADCResult(2); //UAC2
//采样数+1
if(++AC_Samples>=40) //采样数满40个,一个周期
{
AC_Samples = 0;
T2_Flag = 1;
P43 = !P43; //(示波器观察)假死后(500*40)us电平翻转正常 <---
}
}
unsigned int GetADCResult(unsigned char ch) //读取ADC结果,这个采样函数应该没问题
{
unsigned int ADCValue;
ADC_CONTR = ADC_POWER | ADC_START | ch;
while (!(ADC_CONTR & ADC_FLAG)) //等待ADC转换完成
{
P77 = 0; //(示波器观察)假死后引脚低电平,用硬件debug调试运行也是一直停在这里 <--- 程序死在这里!
}
P77 = 1;
ADC_CONTR &= ~ADC_FLAG; //清完成标志
ADCValue = (ADC_RES<<4)+(ADC_RESL>>4); //
return ADCValue; //返回ADC结果
}