You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 01:20:41