- 之前写过关于MCU内部参考电压的文章,不熟悉的话可以点击直达 MCU内部参考电压几种妙用你都知道嘛
- 近期回顾测试中却发现唤醒后测量内部电压的数值是有问题的,带问题运行这么久也真是…[捂脸(*/ω\*)]
发现问题
- 进入停止模式前为了更节省能源,对ADC进行了
HAL_ADC_DeInit(&hadc)
,并在唤醒后对其进行了MX_ADC_Init()
重新开启再测量。本以为就OK了,实际运行中不知道是不是没遇到过电压掉下阈值的情况,反正也没触发相应动作就没管了…哎,测试不到位啊,深刻反省中… …
- 问题还是在一次调试中暴露了,发现用
HAL_ADC_GetValue(&hadc)
获取值后计算出来是有问题的,是一个极大的数(对测量电压毫无意义),于是开始找问题。
排查原因
1. 起初,以为是进入STOP模式前开启的HAL_PWREx_EnableUltraLowPower()
和HAL_PWREx_EnableFastWakeUp()
引起的。
: 这两个API大致作用是忽略唤醒后ADC的恢复时间同时让ADC在STOP下不再工作,进一步减低了功耗。
- 于是就在唤醒后又用
HAL_PWREx_DisableUltraLowPower()
和HAL_PWREx_DisableFastWakeUp()
把他们失能了。但… …并没有什么luan用。
2. 再来,是不是因为偷懒,所以唤醒后没有重新配置时钟导致ADC初始化不成功呀…
: 唤醒前用的就是HSI,而唤醒后MCU默认就是HSI,所以没有再次去初始化时钟
- 那就加上嘛,吭哧吭哧把Cube生成的从
SystemClock_Config()
到MX_XXX_Init()
都加到唤醒后第一条开始执行… …依然没有什么作用,通过调试ADC寄存器发现还是没有任何位被置起,也就是ADC初始化无效。
3. 秉承着有问题,找售后的原则,开始在官方生成的库HAL文件中翻来翻去,看看接口注释上是不是有什么提示。
- 还是找到了,在
HAL_ADC_Init()
的注释中发现这么一段:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200115180535151.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0VtbXlfa2FubHk=,size_16,color_FFFFFF,t_70#pic_center)
HAL_ADCEx_EnableVREFINT()
是个什么,进去看看
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200115180723560.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0VtbXlfa2FubHk=,size_16,color_FFFFFF,t_70#pic_center)
- 原来问题在这里呢,
HAL_ADCEx_EnableVREFINT()
把使用的内部参考电压Vrefint
缓冲区重新使能,并且从低功耗模式唤醒后一定要在HAL_ADC_Init()
之前使用。
解决问题
- 把
HAL_ADCEx_EnableVREFINT()
加到唤醒后对ADC初始化HAL_ADC_Init()
的前面,终于OK了,读数正常,问题解决。
碎碎念
- 使用官方提供的API,如果遇到问题,看看注释中使用注意事项没准会有提示的,也希望以后官方可以把"在什么情况下调用就一定要做什么的事情一并写到接口中直接运行,减少这种令人摸不着头脑的情况"… …