
STM32L4 系列中ADC 通道配置上的区别 ) W* m) P8 V. J% W前言 即使同是STM32L4 系列中的子系列,其配置也可能会有微小的变化,需要注意一下。 ' v5 W2 L" t7 }# F# Z/ p 问题0 \; F! K' p* A, o: z4 d 某客户在其产品的设计中,使用了STM32L476RGT6。客户在开发过程中,调试程序时发现不管ADC 通道在外部连接的电压如何变化,ADC 通道采样进来的电压始终在0.7V 左右。8 l& l3 p6 n) p2 b# W; b" \; P ) b5 L) T7 h, Q 3 r! Z4 m6 M# G& _ 调研 1.了解问题 客户在开发中使用了STM32L4Cube 库STM32Cube_FW_L4_V1.5.0,在STM32L476RG-Nucleo 板子上进行调试。由于STM32Cube_FW_L4_V1.5.0 下的STM32L476RG-Nucleo 并没有ADC 的例程,所以客户工程师将STM32L432KC-Nucleo中的ADC_RegularConversion_Interrupt 例程拷贝到STM32L476RG-Nucleo 底下进行调试。 在项目配置中,客户已经在Project Options 中将Device 配置成STM32L476RG 了,在“C/C++ Compiler”的Preprocessor页面中的Defined symbols 也已经将STM32L432xx 改成STM32L476xx 了。 C3 V- G1 J& R- V* z* A* k" t ![]() ![]() 但是,当编译调试时,发现ADC 通道采样进来的电压不管输入电压如何,始终是在0.7V 左右。 " q' k. T# y: ]9 o# O# f 2.问题分析, K& d! w9 a4 S3 W 由于程序的采样电压不会随着外部的电压变化而变化,所以怀疑在I/O 配置上会有问题。客户使用STM32L432 的例程,在未做修改的情况下来调试STM32L476,并不能正常工作。我们需要来仔细比对一下STM32L432 和STM32L476 的ADC 通道配置的情况。* g1 J8 k' i- o1 G( \# G1 x4 ^) X1 P STM32L432 的参考手册为RM0393,而STM32L476 的参考手册为RM0351。通过仔细阅读ADC 和GPIO 两章,可以发现在ADC 输入通道上,STM32L476 与STM32L432 是存在区别的,如下: · STM32L476* J* K" l6 w* c# H) j8 H 在ADC 的“16.3.11 Channel selection (SQRx, JSQRx)”有如下注意事项: ![]() 在 GPIO 的“9.3.2 I/O pin alternate function multiplexer and mapping”一节中,附加功能的描述: ![]() · STM32L4325 Y- m' @. L" _8 H& u 在ADC 的“16.4.11 Channel selection (SQRx, JSQRx)”并没有那个注意事项。 在GPIO 的“9.3.2 I/O pin alternate function multiplexer and mapping”一节中,附加功能的描述也不一样:3 M) O5 d# J+ x; j' A! s ![]() 也就是说,相比STM32L432,STM32L476 在ADC 通道的配置需要多配置一个寄存器GPIOx_ASCR。来看一下RM0351 的GPIO 寄存器中对这个寄存器的描述: ![]() 如果需要将模拟开关连接到ADC 输入,就必须在相应的位写“1”。这个位必须在ADC 转换之前设置。只能连接到ADC 输入的IO 口才进行设置,其他IO 口必须保持复位值。 现在回到STM32L4Cube 库来看这个程序如何对这个寄存器进行设置的。在stm32l4xx_hal_gpio.c 中的void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)函数,有以下一段代码: ![]() 首先,这段代码仅对STM32L471、STM32L475、STM32L476、STM32L485 和STM32L486 有效。它的目的是先判断GPIO的模式是否为模拟口,是的话而且是连接到ADC 的话,将相应的GPIOx_ASCR 位写1。来看一下GPIO 的模式定义就知道了:: ]% q, W3 O6 l; |, P- I R$ u ![]() 在此GPIO 模式预定义中,可以看到模拟口分成两种:GPIO_MODE_ANALOG 和GPIO_MODE_ANALOG_ADC_CONTROL。在注释中我们看GPIO_MODE_ANALOG_ADC_CONTROL 是针对ADC 转换的模拟模式。我们将其值放到刚才的那一段代码中去看,就会发现在相应的GPIOx_ASCR 位会进行写1 的情况。 所以,当使用STM32L476 的ADC 转换中,其ADC 输入通道的GPIO 模式配置必须配置为+ ]) P4 q2 G7 } GPIO_MODE_ANALOG_ADC_CONTROL 才可以。如果只是配置成GPIO_MODE_ANALOG,相应的GPIOx_ASCR 没有 置1,模拟开关没有进行连接,就会检测不到引脚上的电压。! J( P# [) V* q& R% b! \. q0 P 来看一下STM32L432 的例程,在stm32l4xx_hal_msp.c 中的void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)函数中, GPIO 是这样配置的: ![]() 它配置的Mode 是GPIO_MODE_ANALOG,这在STM32L432 没有问题,但是在STM32L476 却是有问题的,必须改正。) l% m6 s- ?8 }; a- l" {$ F8 X& L$ @ ![]() # \6 ^$ S' w0 `% z 3.问题解决 将stm32l4xx_hal_msp.c 中的void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc)函数中GPIO 配置修改为:! x, C2 o# h1 @$ q, N ![]() 问题解决,ADC 可以正常工作了。+ M% C: S- X2 Q# Y: G7 M; \( E ( Q1 s4 |# t7 F 结论% v* w# ?! \1 { 由于STM32L476 和STM32L432 的ADC 通道配置上存在区别,所以STM32L432 的例程并不能直接使用,需要对其GPIO配置进行修改才可以。 $ t$ {: a$ [$ y7 w5 D J- ]! G 处理 需要根据STM32L4 相应的具体型号对ADC 输入通道的GPIO 模式进行相应的配置。在此,根据STM32L4 几份参考手册RM0351、RM0392、RM0393、RM0394、RM0395,对现有产品整理如下,以供查阅。0 n& a7 V' m8 Z) _1 t- _; ~9 o ; T. i# ^9 c: k t: l ' ^/ X2 H" V+ ^ _0 I! M8 V. k 3 ~; y: F% ~" L& Q! c$ g0 } ![]() |
NICE THANKS 帮助很大谢谢哈,我说嘛,为什么所有通道采集的都是0.7V电压不变 |
确实是个很容易忽略的问题 |
STM32如何分配原理图IO
【实测教程】STM32CubeMX-STM32L4之研究(ADC)
【STWINKT1B评测】2.初步测试IIS3DWB振动传感器
【圣诞专享活动】使用TouchGFX做GUI显示:圣诞快乐&Merry Christmas!
串口通信波特率异常的解决办法
【STWINKT1B 评测】6. NanoEdge AI 音频分类器 (2)
【STWINKT1B 评测】5. NanoEdge AI 音频分类器 (1)
STWINKT1B评测】4.测试板载ISM330DHCX(6轴)
【STWINKT1B评测】-03-CoreMark跑分测试
【STWINKT1B评测】-02-串口-定时器LED灯测试