本帖最后由 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
最后的最后,附上完整的工程(代码有点乱,大家凑合着看 )
|