历史上的今天
今天是:2025年03月16日(星期日)
2021年03月16日 | STM32F30X禁止 ADC 已关闭情况下再次 关闭 ADC
2021-03-16 来源:eefocus
问题
某客户在其产品的设计中,使用了 STM32F302CCT6。客户在使用过程发现 ADC 在工作情况下会有各种各样奇奇怪怪的问题。
调研
1.了解问题
客户在开发中使用了 STM32F30x 的标准外设库 STM32F30x_DSP_StdPeriph_Lib_V1.2.3,在其程序设计中,ADC1 是在使用的时候才打开的,在不使用的时候将 ADC1关闭。通过调用 void ADC_DisableCmd(ADC_TypeDef* ADCx)子程序,执行ADC_DisableCmd(ADC1)将 ADC1 关闭。仔细察看程序,发现程序中在 ADC1 的“打开→关闭→打开→关闭→…”循环的关闭中,执行了两次ADC_DisableCmd(ADC1)。
2问题分析
通过学习 STM32F30x 的参考手册,可以知道 STM32F30x 在对 ADC 进行关闭的操作与其他系列是不一样的;其他系列只要将 ADON 位清零就可以停止转换并使 ADC 进入掉电模式,而 STM32F30x 则不一样,它是通过置位 ADDIS 位来关闭 ADC的。在 void ADC_DisableCmd(ADC_TypeDef* ADCx)程序中也可以看到这一点。

但是,问题来了,ADDIS 位是在什么情况下都可以置位的吗?
我们来看一下参考手册中对关闭 ADC 的软件流程的描述:

从描述中,我们可以知道:在置位 ADDIS 之前,必须先检测 ADSTART 位和 JADSTART 位,确保他们为零,也就是说没有正在进行的 A/D 转换。在 ADC Control register - ADCx_CR 寄存器中对 ADDIS 的描述也注明了:

关于这一点,大多数人都是会注意到的。但是,注意这个就够了吗?关于 ADC 的控制位,在参考手册特别使用一个小节对向控制位写访问的限制进行详细描述,此小节为“Contraints when writing the ADC control bits”,在这一小节中,有一句话值得注意:

注意这里的用词 only if,它的意思是“只有在 ADC 是打开状态,而且没有正在等待的关闭 ADC 的请求的情况下,也就是在ADEN=1 且 ADDIS=0 的情况下,才允许软件对 ADCx_CR 寄存器中的 ADSTART,JADSTART 和 ADDIS 位进行操作。在底下的“Note”注意中写道:

这个注意说,这些禁止的 ADC 写访问行为是没有硬件保护去禁止的,错误的操作行为将导致 ADC 进入一个未知的状态。要恢复这种状态,必须将 ADC 彻底关闭(将 ADCx_CR 中的所有位全清零)。
所以,现在可以知道,ADC1 工作不正常的原因正是因为连续执行了两次 ADC_DisableCmd(ADC1)。第一次执行ADC_DisableCmd(ADC1)时,当 ADC1 已经有效关闭时,ADEN 和 ADDIS 都被硬件清零,这个时候第二次再去写 ADDIS 位就是个错误的行为了,将会导致 ADC1 进入未知状态。
3. 问题解决
在解决问题之前,先来看一下 STM32Cube_FW_F3_V1.2.0 库中对 ADC 进行关闭的操作。打开 stm32f3xx_hal_adc_ex.c 文件,找到 static HAL_StatusTypeDef ADC_Disable(ADC_HandleTypeDef* hadc)函数,其程序内容为:
在这个函数注释中有个“Note: forbidden to disable ADC (set bit ADC_CR_ADDIS) if ADC is already disabled.”,再次告诉我们“禁止在 ADC 已经被关闭的情况下再次关闭 ADC”。然后,程序在运行中先对 ADC 是否已经被关闭进行了判断,如果已经被关闭,则不进行关闭操作;未被关闭情况下才会执行关闭操作。
所以,在使用标准外设库的时候,我们也可以参考 Cube 库中的这种操作来进行改善。
可以考虑对 void ADC_DisableCmd(ADC_TypeDef* ADCx)程序进行修改:

当然,不动 void ADC_DisableCmd(ADC_TypeDef* ADCx)程序也可以,只需在用户程序中对这些限制进行判断即可。上面的while 循环中,也可以加入超时退出机制。结论连续两次对 ADDIS 控制位进行写 1,是错误的操作行为,将会导致 ADC 进入未知状态,工作不正常。处理修改程序,避免错误的操作行为。建议在使用 STM32F30x 系列的 ADC 外设时,必须要对控制位的操作限制有明确的了解。

史海拾趣
|
电阻种类及特点简介 电阻,英文名resistance,通常缩写为R,它是导体的一种基本性质,与导体的尺寸、材料、温度有关。欧姆定律说,I=U/R,那么R=U/I,电阻的基本单位是欧姆,用希腊字母“Ω”表示,有这样的定义:导体上加上一伏特电压时,产生一 ...… 查看全部问答> |
|
我刚刚开始接触FPGA,资料也才看了一点,Verilog HDL也只是大致了解. 我在想要不要买块开发板,一边看资料一边在开发板上试试 以前学C的时候上课也觉得很枯燥,但是会经常自己编些小算术题之类的~呵呵 望有经验的兄弟姐妹给些建议 不慎感谢… 查看全部问答> |
|
想实现 运行状态 掉电保持,以便重新上电时恢复, 需要保持的数据大约 20字节, 该状态每秒更新一次。 请问有什么比较好的方法?掉电检测如何实现? //目前使用的方法是:Dallas SDRAM, 当作RAM一部分。 掉电检测没有,上电时检查状 ...… 查看全部问答> |
|
做应用的需要一片固定的内存,我在Config.bib中划好,在驱动里增加了MmIOMapSpace和MmIOUnMapSpace以及对应的IOCTL,在驱动内部测试,这片内存可以正常访问,map以及unmap。 我用IOCTL为应用返回这片内存的物理及虚拟地址,为什么在应用中使用该虚 ...… 查看全部问答> |
|
[求助]DPF播放一個半小時的幻燈圖片後就不再播放了。爲什麽? 在板子上做测试,从服务器上读图片,在板子上以幻灯片的形式播放,几乎每次一个半小时后就停止播放。系统是winCE的,网上查了好久,知道是订阅时间的问题,但不知道该改哪部分的代码,请达人们指教,小弟刚接触嵌入式开发。… 查看全部问答> |
|
AT89S51单片机控制GSM模块(M22)发送短信程序!~!~!~! AT89S51单片机控制GSM模块(M22)发送短信程序!~!~!~! 自己改的AT89S51单片机控制GSM模块(M22)发送短信程序,在Keil上编译没错,但还未试过烧入片内运行。。 大家看看,这个程序可行否? 还有什么错误的地方? 希望搞过GSM的朋友多提点 ...… 查看全部问答> |
|
@8000 30 40 04 80 FF 3F 31 40 00 06 3C 40 0C 02 3E 40 F8 00 B0 12 EE A7 3C 40 00 02 3E 40 0C A8 30 12 0B 00 B0 12 00 A8 21 53 B0 12 44 A0 B0 12 12 A4 0A 12 0B 12 08 12 09 12 06 12 07 12 04 12 05 12 D2 93 E5 02 C5 20 C2 43 E5 ...… 查看全部问答> |




