本帖最后由 JasonLee27 于 2020-3-4 15:13 编辑
软件环境: keil 5.23 SecureCRT
硬件环境: AC7811通用开发板 ATC-LINK
汽车上的电子产品采用汽车蓄电池供电,一般要求的正常工作电压范围是9~16V,过低,过高都需要记录故障。
对于这个功能,我们都会使用ADC来采集计算主电电压值。但如果一直采用软件的方式去判断是否过压欠压,未免太浪费CPU,所以ADC都会提供一个门限功能(AC7811叫模拟看门狗)。
工程师可以设置触发中断的上下限,在采样值未超出门限时,不会有中断,一旦超出后,就会产生ADC中断,这个时候在处理异常,就可以节省很多CPU资源。
我们可以看下7811的模拟看门狗配置说明
这里我使用mode5(连续扫描模式),模拟看门狗选择单规则组通道。
通用开发板上刚好有个ADC_IN1的模拟按键,可以产生不同的AD值,便于我测试
在代码中定义上下门限,以及超出门限后的恢复门限,这里异常门限和恢复门限值不同,是为了防止电压刚好在门限上下范围浮动,造成一直触发中断的问题。
#define AMOHighValue (3000)
#define AMOLowValue (1000)
#define AMOLowRecoverValue (1100)
#define AMOHighRecoverValue (2900)
然后是adc中断程序,根据采样值判断当前状态(AC7811并不能直接告诉你是超出上门限还是下门限,so,自己判断吧。根据当前状态重新设置门限,这是因为当采样值超出门限后,是会一直产生中断的,所以,要么产生中断后,关闭中断,要么重新设置门限将当前采样值包含进去,否则会一直产生中断,导致其他程序无法运行(话说我最开始还吐槽过这个设定,觉得这么搞怎么用,后来看了下瑞萨和NXP的,发现貌似别人也差不多。)
void ADC_Callback(void)
{
if (ADC_GetIntFlag(ADC, ADC_FLAG_AMO)) ///<发生模拟看门狗事件
{
if (s_sampleValue[0] > AMOHighValue) ///<超出上限
{
ADC_SetAnalogWatchDogThreshold(ADC, 4095, AMOHighRecoverValue); ///<设置恢复门限
printf("\r\n too High %d ", s_sampleValue[0]);
}
else if (s_sampleValue[0] < AMOLowValue) ///<低于下限
{
ADC_SetAnalogWatchDogThreshold(ADC, AMOLowRecoverValue, 0); ///<设置恢复门限
printf("\r\n too Low %d ", s_sampleValue[0]);
}
else if ((s_sampleValue[0] > AMOLowRecoverValue) || (s_sampleValue[0] < AMOHighRecoverValue)) ///<进入正常值
{
ADC_SetAnalogWatchDogThreshold(ADC, AMOHighValue, AMOLowValue); ///<重设异常门限
printf("\r\n Recover %d ", s_sampleValue[0]);
}
else
{
///<should not be here
printf("\r\n error %d", s_sampleValue[0]);
}
}
ADC_ClearFlag(ADC, ADC_FLAG_AMO | ADC_FLAG_EOC | ADC_FLAG_IEOC); ///<直接清除所有标志,
}
下面是我测试的打印内容
This is adc_sample1 demo
too High 4095
Recover 2088
too High 4095
Recover 2090
too High 4095
Recover 2108
too High 4095
too Low 928
too High 4092
too Low 893
too High 4095
Recover 2101
too High 3164
Recover 2111
too High 4043
最后的最后,附上完整的工程(代码有点乱,大家凑合着看)
|