按下按钮时从 STM32 ADC 获取读数

Posted

技术标签:

【中文标题】按下按钮时从 STM32 ADC 获取读数【英文标题】:Getting a reading from STM32 ADC when pushing a button 【发布时间】:2020-08-05 18:11:11 【问题描述】:

使用 CubeIDE 和 STM32F4 板,我正在尝试启动 ADC 转换并根据 ADC 值使两个 LED 中的一个闪烁 - 如果值小于某个限制,则一个 LED 应该闪烁而另一个保持关闭,但如果 ADC 值大于我设置的限制,那么另一个 LED 应该闪烁。当我按下按钮时应该会发生这种情况,并且应该继续闪烁直到按下按钮。

所以我有 4 个引脚 - 两个(G2 和 D8)GPIO 输出用于闪烁 LED,一个 (A0) 引脚是模拟输入,一个引脚 (F2) GPIO 输入用于按钮。它设置为上拉,并通过按钮连接到 GND。

相关代码是

/* USER CODE BEGIN 0 */
uint32_t adcVal;
/* USER CODE END 0 */
  /* USER CODE BEGIN 2 */
//HAL_ADC_Start(&hadc1);
HAL_ADC_Start_IT (&hadc1);
  /* USER CODE END 2 */
/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

    adcVal = HAL_ADC_GetValue(&hadc1);
    if (!HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_2)) 
        HAL_ADC_Start_IT (&hadc1);
        adcVal = HAL_ADC_GetValue(&hadc1);
        if (adcVal > 2000) HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_8); HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_RESET);
        else HAL_GPIO_TogglePin(GPIOG, GPIO_PIN_2); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_RESET);
        HAL_Delay(500);
        //HAL_ADC_Start_IT (&hadc1);
    
    else HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_RESET);

/* USER CODE END 4 */

我没有在 while(1) 循环中添加任何内容。

编译时,我没有收到任何错误或警告,当我运行代码时,F2 引脚设置为高电平(当我用测试仪测量时为 3V,按下按钮时变为零)但 LED 不亮完全没有反应,尽管电压施加到 A0。我怀疑我以错误的方式使用 ADC。我希望 ADC 在连接到按钮的引脚变为低电平时保持空闲并读取和转换值。

当我将 GPIO 相关行放入 while(1) 循环时,它也不起作用。这可能是某个地方的一个简单错误,但谁能告诉我它在哪里?

我从自动生成的代码中找到了这样的行

/*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOD, GPIO_PIN_8, GPIO_PIN_RESET);

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_2, GPIO_PIN_RESET);

但是当我将它们注释掉时,它并没有帮助。我还添加了ADC设置,可能问题出在:

  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

【问题讨论】:

【参考方案1】:

问题是

您在HAL_ADC_ConvCpltCallback() 的执行上下文中调用HAL_Delay(),它由中断处理程序运行。这意味着您将阻塞主循环和中断(优先级不高于该 ADC 中断)的执行半秒!

据我所知,ADC 处于一次性模式(不是扫描或连续模式)。 如果在转换完成回调中发现设置了 GPIO F2,则不会调用HAL_ADC_Start_IT(),ADC 会静止。

【讨论】:

你说得对,它把触发 if 语句放到了 while 循环中: 我想补充一点,我只留下了 'adcVal = HAL_ADC_GetValue(&hadc1);' 到转换完成回调中,这样就可以了。我只是想知道,当 'HAL_ADC_Start_IT (&hadc1);' 紧随 'if (!HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_2))' 之后,当执行该 if 语句之后的代码时,首先使用旧的转换值。如果在输入电压改变后按下按钮以使另一个 LED 闪烁,那么在它开始闪烁之前,前一个 LED 会先亮一次闪烁......但是 ADC 不应该在第一个 if() 之后启动还带来了新的价值?

以上是关于按下按钮时从 STM32 ADC 获取读数的主要内容,如果未能解决你的问题,请参考以下文章

STM32 ADC 值读数过高

STM32F4程序只有在按下复位按钮后才会运行

在 STM32F103 中按下释放按钮时,EXTI 线获得奇/偶中断计数

Stm32CubeMX5 配置使用ADC

蓝桥杯扩展板模块(基于新版STM32G431)——ADC按键

蓝桥杯扩展板模块(基于新版STM32G431)——ADC按键