在何种情况下遇到的这个问题:使用S32K1系列芯片开发产品,同时用到了ADC采集与EEROM读写功能,官方推荐使用PDB触发ADC,另外这款芯片支持将芯片中的一部分空间模拟成EEROM,进行读写操作。对单个功能进行调试,ADC采集与EEROM读写都可以实现,但是当两者出现到一个工程中,会出现ADC采集功能瘫痪的问题。
注:本文仅是个人遇到问题后,自我总结的文章,所述见解不一定正确和通用,因此所述内容不可用于任何商业活动!!! 使用单片机制作产品或DIY时,请充分评估与规避风险,以免造成个人损失。
各位读者,如果遇到类似问题,欢迎在评论区讨论,如果发现我之观点有任何不妥之处,请批评指正。
现象描述:
现象1:
EEROM每次读写120字节数据,读写请求频率低于10Hz,ADC采样频率接近1KHz,则ADC中断回调函数停止访问(只要执行写操作就会停止);
现象2:
EEROM每次读写120字节数据,读写请求频率低于10Hz,ADC采样频率低于30Hz,则ADC中断回调函数访问正常,不会停止访问;
现象3:
EEROM每次写4字节数据,读请求的频率低于30Hz,ADC采样频约为1KHz,
将EEROM写操作放在LPIT回调函数中运行(定时任务),则ADC中断回调函数有一定概率会停止访问;
现象4:
EEROM每次写4字节数据,读请求的频率低于30Hz,ADC采样频约为1KHz,
将EEROM写操作放在main函数中运行(通过写请求标志位控制),则ADC中断回调函数访问正常,不会停止访问;
现象总结:
芯片上电后是对EEROM进行读操作,往往不会出现ADC中断回调函数停止访问的问题,对EEROM进行写操作,ADC中断回调函数停止访问的概率与EEROM写入的字节数或写入时间成正相关。
ADC中断回调函数停止访问的同时,PDB中断回调函数也停止了访问,EEROM写入操作正常生效。
解决方法:
步骤1(在哪里跌倒,在哪里站起来):
在EEROM执行写操作语句前,先关闭全局中断,再将PDB模块反初始化,
待EEROM执行完写操作,将PDB模块重新初始化,然后打开全局中断;
步骤2(打补丁):
PDB开启中断,定义两个变量A、B,A在PDB中断回调函数中进行加1计数(A++),B在10ms的定时任务中(在main函数中执行),判断A与B的数值相等否,
若A!=B,则将A的值赋值给B,
若A==B,则先关闭全局中断,将PDB模块反初始化,然后将PDB模块重新初始化,再打开全局中断;
void PDB_init_fun(void)
{
PDB_DRV_Init(INST_PDB1, &pdb1_InitConfig0);
PDB_DRV_Enable(INST_PDB1);
INT_SYS_InstallHandler(PDB0_IRQn,&PDB_IQR,(isr_t *)0);
INT_SYS_EnableIRQ(PDB0_IRQn);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0u, &pdb1_AdcTrigInitConfig0);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0u, &pdb1_AdcTrigInitConfig1);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0u, &pdb1_AdcTrigInitConfig2);
PDB_DRV_ConfigAdcPreTrigger(INST_PDB1, 0u, &pdb1_AdcTrigInitConfig3);
PDB_DRV_LoadValuesCmd(INST_PDB1);
PDB_DRV_SoftTriggerCmd(INST_PDB1);
}
void PDB_deinit_fun(void)
{
PDB_DRV_Deinit(INST_PDB1);
INT_SYS_DisableIRQ(PDB0_IRQn);
}
void PDB_IQR(void)
{
if(PDB_DRV_GetTimerIntFlag(INST_PDB1))
{
/*Clear PDB1 timer interrupt flag*/
PDB_DRV_ClearTimerIntFlag(INST_PDB1);
}
if(times_PDB_new<10000)
times_PDB_new++;
else times_PDB_new=0;
}
//EEROM写入操作
{
//关闭系统中断
INT_SYS_DisableIRQGlobal();
//测试关闭PDB功能
PDB_deinit_fun();
//将数组写入到内存中
mcal_wrEEPROM(address,sizeof(EEROM_array),EEROM_array);
//打开PDB功能
PDB_init_fun();
//打开系统中断
INT_SYS_EnableIRQGlobal();
}
//main函数中
if(times_PDB_new==times_PDB_Old)
{
//关闭系统中断
INT_SYS_DisableIRQGlobal();
PDB_deinit_fun();
PDB_init_fun();
//打开系统中断
INT_SYS_EnableIRQGlobal();
}else times_PDB_Old=times_PDB_new;
830

被折叠的 条评论
为什么被折叠?



