【问题标题】:Individually read distinct inputs with STM32L ADC使用 STM32L ADC 单独读取不同的输入
【发布时间】:2022-12-13 11:07:52
【问题描述】:

目标是通过轮询读取多个 ADC 通道。它不需要很快——想法是读取所连接的不同电池的电压。我有一个 STM32L071 微控制器。与 STM32F0 模型相比,编程有点不同。我正在使用平台。

我在这里找到了非常有用的信息:

但是,不幸的是我无法读出多个频道。这些问题可能与HAL_ADC_InitHAL_ADC_ConfigChannel 有关。

这是一个最小的代码示例:

#include <Arduino.h>
#include <STM32IntRef.h>

uint32_t a1=0, a2=0;

#define HAL_ADC_MODULE_ENABLED
ADC_HandleTypeDef hadc1;

void displaying(){
    Serial.println("values:");
    Serial.println("-------");
    Serial.print("ch1 - ");
    Serial.println(a1);
    Serial.print("ch2 - ");
    Serial.println(a2);
    Serial.println("");
}

void config_ext_channel_ADC(uint32_t channel, bool val) {
  hadc1.Instance = ADC1;
  hadc1.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
  HAL_ADC_Init(&hadc1);
  
  ADC_ChannelConfTypeDef sConfig;
  sConfig.Channel = channel;
  if (val == true)  {
    sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
  } else {
    sConfig.Rank = ADC_RANK_NONE;
  }
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) {
        Serial.println("Error ADC Config Channel");
        //Error_Handler();
  }
}

uint32_t r_single_ext_channel_ADC(uint32_t channel) {
  /* read the ADC and output result */
  uint32_t digital_result;
  config_ext_channel_ADC(channel, true);
  HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED);
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1, 1000);
  digital_result = HAL_ADC_GetValue(&hadc1);
  HAL_ADC_Stop(&hadc1);
  config_ext_channel_ADC(channel, false);
  return digital_result;
}

void readBat() {
  /* read voltages */
  a1 = r_single_ext_channel_ADC(1);
  a2 = r_single_ext_channel_ADC(PA2);
}

void setup() {
  // put your setup code here, to run once:
  // Serial monitor
  Serial.begin(9600);
  Serial.println(F("Starting now"));
  // initialize pins for ADC
  analogReadResolution(ADC_RESOLUTION);
  pinMode(PA1, INPUT);
  //pinMode(BATTERY_SENSE_PIN2, INPUT);
  pinMode(PA2, INPUT_ANALOG);
}

void loop() {
  // put your main code here, to run repeatedly:
  readBat();
  displaying();
  delay(2000);
}

输出是:

values:
-------
ch1 - 0
ch2 - 140

听起来很合理,但在引脚上施加一些电压不会改变值。

有人可以给我一些建议,想法吗?

【问题讨论】:

    标签: stm32 microcontroller adc platformio


    【解决方案1】:

    好的,与此同时我发现了问题。软件很好;我采用了 Arduino 框架并使用了analogRead()

    我需要清除 PCB 上的所有助焊剂,这些助焊剂会导致引脚之间发生一些接触。 此外,如果想直接使用 HAL 地址,则应设置 ClockDivider,使 ADC 采样频率低于 1 MHz。

    【讨论】:

      【解决方案2】:

      分别读取不同 ADC 通道(这里是 ADC2 有 2 个通道)的代码(由 CubeMX 生成):

      注意:我们必须使用ScanConvMode加上DiscontinuousConvMode和NO ContinuousConvMode

      
      /* ADC2 init function */
      void MX_ADC2_Init(void)
      {
      
        /* USER CODE BEGIN ADC2_Init 0 */
      
        /* USER CODE END ADC2_Init 0 */
      
        ADC_ChannelConfTypeDef sConfig = {0};
      
        /* USER CODE BEGIN ADC2_Init 1 */
      
        /* USER CODE END ADC2_Init 1 */
        /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
        */
        hadc2.Instance = ADC2;
        hadc2.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
        hadc2.Init.Resolution = ADC_RESOLUTION_12B;
        hadc2.Init.ScanConvMode = ENABLE;
        hadc2.Init.ContinuousConvMode = DISABLE;
        hadc2.Init.DiscontinuousConvMode = ENABLE;
        hadc2.Init.NbrOfDiscConversion = 1;
        hadc2.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
        hadc2.Init.ExternalTrigConv = ADC_SOFTWARE_START;
        hadc2.Init.DataAlign = ADC_DATAALIGN_RIGHT;
        hadc2.Init.NbrOfConversion = 2;
        hadc2.Init.DMAContinuousRequests = DISABLE;
        hadc2.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
        if (HAL_ADC_Init(&hadc2) != HAL_OK)
        {
          Error_Handler();
        }
        /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
        */
        sConfig.Channel = ADC_CHANNEL_8;
        sConfig.Rank = 1;
        sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;
        if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
        {
          Error_Handler();
        }
        /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
        */
        sConfig.Channel = ADC_CHANNEL_9;
        sConfig.Rank = 2;
        if (HAL_ADC_ConfigChannel(&hadc2, &sConfig) != HAL_OK)
        {
          Error_Handler();
        }
        /* USER CODE BEGIN ADC2_Init 2 */
      
        /* USER CODE END ADC2_Init 2 */
      
      }
      
      

      现在,阅读:

      
      void readChannel(){
          //read the next channel
          HAL_ADC_Start(&hadc2);
          uint8_t ret = HAL_ADC_PollForConversion(&hadc2, 1000 /*timeout*/);
          uint16_t value = HAL_ADC_GetValue(hadc);
          printf("HAL_ADC_PollForConversion status: %d, VALLLL: %d
      ", ret, value);
      }
      
      
      int main(){
          while(1){
              //Automatically read the first channel (channel 8):
              readChannel();
              HAL_Delay(100);
              
              //Automatically read the second channel (channel 9):
              readChannel();
              HAL_Delay(100);
              
          }
      }
      

      【讨论】:

        【解决方案3】:

        您是否错过了将 io 设置为模拟输入模式?某处应该是这样的(uslay 在你的 hal msp 文件中,adc_init func)。

        GPIO_InitStruct.Pin = GPIO_PIN_1;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
        

        编辑 => 你错过了 ch1

        analogReadResolution(ADC_RESOLUTION);
        pinMode(PA1, INPUT);
        //pinMode(BATTERY_SENSE_PIN2, INPUT);
        pinMode(PA2, INPUT_ANALOG);
        

        应该和PA2一样,输入是“数字模式”。

        【讨论】:

        • 谢谢。我将 PA1 和 PA2 设置为 INPUT_ANALOG。与此同时,我让它运行起来,即我可以看到不同的 ADU 值取决于电压。但问题仍然存在,相邻的 ADU 通道受到影响。这表示;如果我在 PA1 (4095 ADU) 施加 3.3V;我在 PA2 看到大约 1400 ADU。
        猜你喜欢
        • 2017-12-30
        • 2020-11-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-28
        • 1970-01-01
        • 2021-12-20
        • 2021-11-22
        相关资源
        最近更新 更多