Nucleo-L476RG读取ADC1_IN6值时陷入EOC检测无限循环问题
Nucleo-L476RG ADC1_IN6读取EOC无限循环问题解决
问题根源分析
你的代码存在几个关键错误,导致ADC无法完成转换,EOC位始终不置位:
- GPIO引脚配置错误:你要读取的是ADC1_IN6,对应引脚为PA6,但代码里配置的是PA1的模拟模式(操作MODER位2、3),完全对应错了通道。
- ADC序列配置错误:单通道转换的通道选择应在
ADC1->SQR3寄存器中设置,而非SQR1。SQR1的位7-8用于配置第13、14个转换通道,单场景下需将SQR3的低5位设为6(对应IN6)。 - ADC使能流程不完整:
- 重复设置
ADVREGEN位,且未遵守电压调节器启动的最小延时要求(参考手册规定至少20us)。 - 置位
ADEN后未等待ADRDY位(ADC就绪位),直接启动转换会导致ADC未准备好。
- 重复设置
- 缺少ADC校准步骤:STM32L4系列ADC首次使能后必须执行校准,否则转换可能无法正常进行。
修正后的代码
#include "stm32l476xx.h" #include "adc.h" void pa6_adc1_init(void) { /************** 配置ADC GPIO引脚 ******************/ // 使能GPIOA时钟 RCC->AHB2ENR |= (1U << 0); // 设置PA6为模拟模式(ADC1_IN6对应引脚) GPIOA->MODER |= (1U << 12); GPIOA->MODER |= (1U << 13); /**************** 配置ADC外设 ******************/ // 使能ADC时钟 RCC->AHB2ENR |= (1U << 13); /******* 配置ADC参数 ****************/ // 单通道转换,序列长度设为1(SQR1的L[3:0] = 0) ADC1->SQR1 &= ~ADC_SQR1_L; // 转换序列第一个通道设为IN6(SQR3的SQ1[4:0] = 6) ADC1->SQR3 &= ~ADC_SQR3_SQ1; ADC1->SQR3 |= (6U << 0); /******** ADC使能流程 ********/ // 确保ADC处于禁用状态 if (ADC1->CR & ADC_CR_ADEN) { ADC1->CR |= ADC_CR_ADDIS; while (ADC1->CR & ADC_CR_ADEN); } // 关闭深层掉电模式 ADC1->CR &= ~ADC_CR_DEEPPWD; // 使能电压调节器 ADC1->CR |= ADC_CR_ADVREGEN; // 等待电压调节器启动(至少20us,此处用简单延时) for (volatile uint32_t i = 0; i < 1000; i++); // 执行ADC校准 ADC1->CR |= ADC_CR_ADCAL; while (ADC1->CR & ADC_CR_ADCAL); // 使能ADC ADC1->CR |= ADC_CR_ADEN; // 等待ADC就绪 while (!(ADC1->ISR & ADC_ISR_ADRDY)); } void start_conversion(void) { // 清除之前的EOC标志 ADC1->ISR |= ADC_ISR_EOC; // 启动ADC转换 ADC1->CR |= ADC_CR_ADSTART; } uint32_t adc_read(void) { // 等待转换完成 while (!(ADC1->ISR & ADC_ISR_EOC)); // 读取转换结果 return ADC1->DR; }
关键修正点说明
- 修正GPIO配置为PA6,对应ADC1_IN6。
- 将通道选择移至
SQR3寄存器,正确设置单通道序列。 - 完善ADC使能流程:先禁用ADC(若已开启),关闭深层掉电,使能调节器并等待延时,执行校准,最后使能ADC并等待就绪。
- 启动转换前清除EOC标志,避免残留标志影响判断。
内容的提问来源于stack exchange,提问作者Raed Banneni
相关产品推荐
相关产品推荐

