STM32WL55JC1 HAL ADC无法切换通道问题求助
ADC多通道轮询读取问题排查
需求说明
实现3个FreeRTOS线程,分别轮询读取ADC的3个通道(共5个可用通道),并将读取值存入FreeRTOS队列。
现有代码
1. ADC初始化函数
void MX_ADC_Init(void) { hadc.Instance = ADC; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV4; hadc.Init.ScanConvMode = DISABLE; hadc.Init.ContinuousConvMode = DISABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = 1; hadc.Init.DMAContinuousRequests = DISABLE; hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV; hadc.Init.LowPowerAutoPowerOff = DISABLE; hadc.Init.LowPowerAutoWait = DISABLE; if (HAL_ADC_Init(&hadc) != HAL_OK) { Error_Handler(); } for(int ch = 0; ch < GPIO_AI_COUNT; ch++) { ADC_Select_Ch(ch); } }
2. GPIO初始化代码
GPIO_InitTypeDef GpioInitStruct = {0}; GpioInitStruct.Pin = GPIO_AI1_PIN | GPIO_AI2_PIN | GPIO_AI3_PIN | GPIO_AI4_PIN | GPIO_AI5_PIN; GpioInitStruct.Pull = GPIO_NOPULL; GpioInitStruct.Speed = GPIO_SPEED_FREQ_LOW; GpioInitStruct.Mode = GPIO_MODE_ANALOG; HAL_GPIO_Init(GPIOB, &GpioInitStruct);
引脚定义
/* Analog Inputs ----------------------------------------------------------- */ #define GPIO_AI_COUNT 5 #define GPIO_AI1_PIN GPIO_PIN_3 #define GPIO_AI1_PORT GPIOB #define GPIO_AI1_CH ADC_CHANNEL_2 /* ADC_IN2, Datasheet P. 51 */ #define GPIO_AI2_PIN GPIO_PIN_4 #define GPIO_AI2_PORT GPIOB #define GPIO_AI2_CH ADC_CHANNEL_3 /* ADC_IN3, Datasheet P. 51 */ #define GPIO_AI3_PIN GPIO_PIN_14 #define GPIO_AI3_PORT GPIOB #define GPIO_AI3_CH ADC_CHANNEL_1 /* ADC_IN1, Datasheet P. 55 */ #define GPIO_AI4_PIN GPIO_PIN_13 #define GPIO_AI4_PORT GPIOB #define GPIO_AI4_CH ADC_CHANNEL_0 /* ADC_IN0, Datasheet P. 55 */ #define GPIO_AI5_PIN GPIO_PIN_2 #define GPIO_AI5_PORT GPIOB #define GPIO_AI5_CH ADC_CHANNEL_4 /* ADC_IN4, Datasheet P. 54 */
3. 通道切换函数
void ADC_Select_Ch(uint8_t channelNb) { adcConf.Rank = ADC_RANKS[channelNb]; adcConf.Channel = GPIO_AI_CH[channelNb]; adcConf.SamplingTime = ADC_SAMPLETIME_12CYCLES_5; if (HAL_ADC_ConfigChannel(&hadc, &adcConf) != HAL_OK) { Error_Handler(); } }
(注:ADC_RANKS和GPIO_AI_CH为存储通道优先级的静态数组,优先级随通道编号递增)
4. 通道读取函数
uint32_t ADC_Read_Ch(uint8_t channelNb) { uint32_t adc_value = 0; ADC_Select_Ch(channelNb); HAL_ADC_Start(&hadc); if(HAL_OK == HAL_ADC_PollForConversion(&hadc, ADC_CONVERSION_TIMEOUT)) { adc_value = HAL_ADC_GetValue(&hadc); } HAL_ADC_Stop(&hadc); printf("Ch%d / %x) %d\n", channelNb, adcConf.Channel, adc_value); return adc_value; }
问题描述
无论如何调整配置,ADC始终只返回最后配置的前一个通道的数值,HAL_ADC_GetValue无法返回当前所选通道的正确读数。
已尝试措施
- 修改ADC转换数量、扫描模式、连续转换模式等配置参数
- 强制所有通道仅使用Rank 1配置
- 移除
HAL_ADC_Stop调用(触发硬件错误) - 在main函数而非FreeRTOS线程中调用读取函数
- 调整GPIO引脚配置参数
- 将
adcConf设为全局变量 - 修改ADC时钟分频设置
- 仅保留目标通道,禁用其他所有通道
以上措施均未解决问题。
求助需求
希望实现轮询方式,通过动态切换通道,在不同FreeRTOS任务中读取单个ADC通道的正确数值,恳请协助排查并解决此问题。
内容的提问来源于stack exchange,提问作者Blub
相关产品推荐
相关产品推荐

