未添加主函数时ADC中断能正常运行,加入主函数以后,ADC中断只能进入几百或者几千次,然后无法再进入,请问是什么问题?
编译可以通过,运行无警告,只是中断进入几次后无法再进入
环境为CCS 硬件为DSP F28379d
下附部分代码:
主函数:
void main(void)
{
......
while(1)
{
CM();
}
/*******************/
while(1); 若如此注释掉主函数可以正常持续进入中断
/********************/
}
CM函数
#include "C_M.h"
#include "ADC.h"
#include "stdlib.h"
data_TYPE cap;
volatile data_TYPE Ucap[100] = {0};
volatile data_TYPE Iarm[100] = {0};
volatile unsigned int counter = 0;
volatile int flag_CM = 1; //置1:开始监测;置0:完成监测,等待下一次开始
volatile int flag_sample = 1; //置1:开始采样;置0:结束采样
unsigned int sample_end = 100; //50kHz ADC 0.5s
unsigned int period_end = 50001; //50kHz ADC 1s
void CM(void)
{
if ((flag_CM)&&(!flag_sample))
{
cap = C_Monitoring (Ucap, Iarm, sample_end);
flag_CM=0;
}
}
data_TYPE C_Monitoring (data_TYPE Uc[], data_TYPE Ic[], int order_end)
{
data_TYPE miu = 0.9; //NLMS步长
data_TYPE C = 1e-3; //电容标称值
data_TYPE fs = 50000; //数据采样频率
data_TYPE w0 = fs*C; //数据采样频率
int order = 0; //Uc&Ic起始序号
int num = 0; //投入窗口数量
inserted_window inwindow;
data_TYPE c_pu_all[30] ={0}; //监测时间段内投入窗口数,缓冲区设置为30,酌情更改
data_TYPE c_cul;
while (order < order_end)
{
inwindow = preprocessing (Uc, Ic, order, order_end); //得到投入窗口
if (inwindow.len >= 3)
{
num ++;
c_pu_all[num-1] = NLMS_filter (& inwindow, miu, w0);
}
order = inwindow.order;
}
data_TYPE c_pu = median(c_pu_all, num)/w0;
return c_pu;
}
inserted_window preprocessing (data_TYPE Uc[], data_TYPE Ic[], int order, int order_end) //数据预处理,筛选投入窗口
{
int i; //电压电流数据序号
int len = 0; //每个投入窗口实时长度
inserted_window window =
{
{0},{0},0,0
};
for (i = order; i<order_end-1; i++)
{
if (Uc[i+1] - Uc[i] > 1e-4)
{
len++;
window.inUc[len-1] = Uc[i+1];
window.inIc[len-1] = Ic[i+1];
if (len >= 30)
{
window.len = len;
window.order = i+1;
break;
}
}
else
break;
}
window.len = len-1;
window.order = i+1;
return window; //试着返回一个结构体
}
data_TYPE NLMS_filter (inserted_window *p1, data_TYPE miu, data_TYPE w0) //NLMS滤波器计算电容容值,一阶
{
/*
* miu: 滤波器步长
* p1: 投入窗口结构体指针
* w: 输出滤波器系数
* */
int N = 1; //一阶滤波器
int len = p1->len; //每个投入窗口实时长度
int i,j; //计数器
data_TYPE xn[1]; //滤波器迭代计算输入向量,长度为N
data_TYPE en = 0;
data_TYPE en_min = 1e6; //用于存储误差最小值,初始化为一个很大的数
data_TYPE yn;
data_TYPE wn[1]; //滤波器迭代计算输入向量,长度为N
data_TYPE wn_temp[1]; //滤波器临时迭代计算输入向量,长度为N
data_TYPE xn2; //对一维来说,xnT*xn = sum(xn[i]^2)
for (i = 0; i < N; i++)
wn[i] = w0;
for (i = N-1; i < len-1; i++)
{
yn = 0;
xn2 = 0;
for (j = 0; j < N; j++)
{
xn[j] = (p1->inUc[i-j+1]) - (p1->inUc[i-j]);
yn += (wn[j])*(xn[j]);
xn2 += (xn[j])*(xn[j]);
}
en = (p1->inIc[i]) - yn;
if (fabs(en) < fabs(en_min))
{
en_min = en;
for(j = 0; j < N; j++)
{
wn_temp[j] = wn[j];
}
}
for(j = 0; j < N; j++)
{
wn[j] = wn[j] + miu/xn2*en*(xn[j]);
}
}
return wn_temp[0];
};
data_TYPE median(data_TYPE s[], int num)//求中位数函数
{
int i,j;
data_TYPE t;
data_TYPE result;
for(i=0; i<num-1; i++)
for(j=0; j<num-1-i; j++)
if(s[j]<s[j+1])
{
t = s[j];
s[j] = s[j+1];
s[j+1] = t;
}
if(num%2 == 0)
{
result = (s[num/2-1]+s[num/2])/2;
}
else
{
result = s[(num-1)/2];
}
return result;
}
中断函数
void InitADC(void)
{
......
PieVectTable.ADCA1_INT = ControlLoop; //&ADCA1_ISR;
......
}
interrupt void ControlLoop(void)
{
......
Adccomplete(); //读取ADC
......
counter++;
if ((flag_CM)&&(flag_sample))
{
Ucap[counter-1]=(ADChan[9].output-1.432)/6.0;
Iarm[counter-1]=(ADChan[7].output-1.5)/0.5; //假设用IA通道
if (counter>=sample_end)
flag_sample=0;
}
if (counter>=period_end)
{
flag_CM=1;
flag_sample=1;
counter=0;
}
}
while循环里的代码不影响中断服务函数的调用!
引用chatGPT作答,出现ADC中断无法正常运行的问题,很可能是因为在加入主函数后,主函数占用了过多的CPU时间,导致无法及时响应中断。在主函数中应该尽量避免使用阻塞式的代码,例如while(1)这样的死循环,这会使主函数不断地占用CPU资源,从而影响中断的正常响应。
针对该问题,可以尝试以下几个解决方法:
1.优化主函数代码,尽量减少CPU资源的占用。例如,可以采用定时器等方式代替死循环,或者使用操作系统等方式进行任务调度,从而使CPU资源更加合理地分配。
2.将一些关键的操作放到中断服务程序中,从而减少主函数的占用时间。例如,可以将一些紧急的数据处理操作放到中断服务程序中,这样可以保证在出现紧急事件时,能够及时响应。
3.调整中断优先级,确保中断服务程序能够及时响应。在使用多个中断时,需要考虑中断的优先级问题,确保重要的中断能够及时响应。可以通过修改中断控制器的配置来调整中断优先级。
4.调整时钟配置,提高系统运行效率。时钟频率越高,CPU的运行效率就越高,可以通过调整时钟频率等方式来提高系统运行效率,从而减少CPU资源的占用,提高中断响应速度。
以上是一些可能的解决方法,具体的解决方案需要根据具体的情况进行调整。另外,为了更好地排查问题,可以使用调试器等工具对代码进行调试,定位具体出现问题的位置。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
首先,加入了主函数以后使得 ADC 中断只能进入几百或者几千次就无法再进入的问题,这给我们的启发是可能主函数中有某些可执行代码对 ADC 中断造成了影响,例如可能主函数中的某些代码在运行时被占用了中断向量表,从而导致 ADC 中断无法再进入。也有可能主函数中有一些耗时的代码,导致 ADC 中断处理时间较长,从而引起中断的堆积,最终无法再进入。
针对上述可能性,可以尝试进行以下优化:
将主函数中的可执行代码移到其他空闲的位置或者在 main 函数中加入延时函数,以使得 ADC 中断的处理能够得到更好的保障。
优化 ADC 中断的处理时间,让其可以更快地完成处理任务。可以考虑优化 ADC 中断服务程序的代码,将其尽量编写得更简单和高效。
调整系统时钟频率,减小主函数与 ADC 中断的抢占。
同时,是否有优化的空间还要考虑到对硬件环境的了解,需要进一步的探讨才可以继续优化。
补充:
根据你提供的部分代码,现将可能引起问题的地方列出来做一些分析:
main 函数中的 while(1) 循环会占用 CPU 资源,这会使得其他中断无法正常执行。建议将 while(1) 循环内的内容移到一个独立的线程中执行,以实现系统的多任务处理。
CM 函数中的 while 循环,则会占用 CPU 资源,使得其他中断无法正常执行。建议改用定时器中断的方式,实现系统的多任务处理。
在 ADC 中断服务函数 ControlLoop 中,执行的操作较多。尽量将每一个操作都缩短到最短时间内完成,以提高处理速度。另外,对于计数器 counter 的使用,一定要注意约束它的增长范围,以免出现乱码或计算错误。
如果我的回答解决了您的问题,请采纳!
在添加主函数后,如果在中断处理函数中使用了过多占用时间的操作,可能会影响ADC中断的正常运行。比如在中断处理函数中进行大量的数据处理、计算等操作,会使得中断处理时间较长,容易出现ADC转换数据不及时的情况。
如果需要调试或排查ADC中断错误,可以首先通过硬件排查,如检查ADC的输入电压是否在合理范围内、检查电路连接是否正常;其次可以通过调试代码的方式进一步分析错误。可以通过在中断处理函数中添加调试信息输出,如串口打印,观察ADC数据的变化和中断触发次数,判断是否存在异常情况。如果需要更详细的调试,也可以使用单步调试工具逐步分析代码执行过程,找出错误所在。
需要注意的是,在调试或排查错误时,应尽量避免使用过多占用时间的操作,以免干扰ADC中断的正常运行。可以通过在中断处理函数中设置标志位,在主函数中处理更复杂的操作,避免影响ADC的转换数据。