使用HAL的STM32 ADC转换


10

我正在尝试学习如何从stm32使用“新” HAL库。
当我尝试进行简单的ADC转换时,它只能运行一次,但随后会停止转换。我想转换结束标志未设置。我正在使用STM32f429I发现板,板上有STM32f429ZI。
请注意,我知道sprintf是一种不好的做法,并且使带有中断的adc更好,我知道,请不要指出这一点,这与问题无关,我只是在这里测试HAL。
所以问题是为什么未设置EOC标志,或者我应该怎么做才能使其正常工作?谷歌搜索没有太大帮助,因为那里关于HAL的好材料很少。

这是代码:

__IO uint16_t ADCValue=0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc);

int main(void)
{
  char str[15];

  /* Various initializations */

  HAL_ADC_Start(&hadc1);
  while (1)
  {

        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
            sprintf(str, "%d", ADCValue);
            BSP_LCD_DisplayStringAt(130,30, (uint8_t*)str, LEFT_MODE);
        }

  }

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    ADCValue = HAL_ADC_GetValue(&hadc1);
}

我还使用CubeMX创建了项目,adc配置如下: 在此处输入图片说明

编辑1
我试图调试一切,似乎该程序被卡住进入检查EOC标志-它会看到它不显示,因此问题计时器等待EOC露面(但它从来没有得到一组)下面是代码的地方卡在调试器中:

/* Check End of conversion flag */
  while(!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC)))
  {
    /* Check for the Timeout */
    if(Timeout != HAL_MAX_DELAY)
    {
      if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
      {
        hadc->State= HAL_ADC_STATE_TIMEOUT;
        /* Process unlocked */
        __HAL_UNLOCK(hadc);
        return HAL_TIMEOUT;
      }
    }

Answers:


6

在原始代码中,将“转换结束选择”设置为“禁用”。

 hadc1.Init.EOCSelection = DISABLE;

事实证明,该#define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)值等于DISABLE。因此,实际上EOCSelection应该配置为: 能够多次轮询ADC。在此处输入图片说明

然后,您可以连续读取ADC,而无需停止和启动ADC:

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    ConfigureADC();

    HAL_ADC_Start(&hadc1);
    while(1)
    {
        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
        }
    }
}

这样对我来说很好。

由于HAL是一个相当新的库,因此找不到很多资源,但并非没有。我从本教程中学到了很多东西,它逐步演示了所有可能的ADC使用。从简单的轮询,到使用中断和DMA。


hm ...禁用EOCSelection使其起作用,但是从其定义开始,它说-指定是在单通道转换结束时还是在所有转换结束时设置EOC标志。从定义上禁用它应该无济于事,但它却有助混淆。您知道为什么完全禁用它才能使其正常工作吗?无论如何,谢谢您的回答
ScienceSamovar 2015年

我也正在学习HAL,所以我还不知道原因。这只是一种体验。我发现HAL可以引起很多争议。
Bence Kaulics,2015年

我已经检查了定义值,#define ADC_EOC_SEQ_CONV ((uint32_t)0x00000000)该值与禁用值相同,因此禁用实际上是ADC_EOC_SEQ_CONV。
Bence Kaulics,2015年

1
哦,好吧,所以从字面上看它不是禁用的。这是有道理的,以前是ADC_EOC_SINGLE_CONV,这可能仅意味着-它仅转换一次,而ADC_EOC_SEQ_CONV是连续转换。解决了另一个难题:)谢谢!
ScienceSamovar

是的,应该是这样。:)
Bence Kaulics 2015年

2

嗯...我发现了一些使用HAL_ADC_Stop(&hadc1)结束转换的教程...我以前看过这些教程,并认为这是蛮横的方式,似乎它完全禁用了ADC,所以我虽然应该不同的方法。但是看来,这实际上运作良好。
如果有更优雅的方法,欢迎发布答案,因为我认为使用HAL_ADC_Stop()非常糟糕,但可用于学习目的。

while (1)
  {
        HAL_ADC_Start(&hadc1);
        if (HAL_ADC_PollForConversion(&hadc1, 1000000) == HAL_OK)
        {
            ADCValue = HAL_ADC_GetValue(&hadc1);
                        sprintf(str, "%d", ADCValue);
                        BSP_LCD_DisplayStringAt(130,30, (uint8_t*)str, LEFT_MODE);
        }
        HAL_ADC_Stop(&hadc1);

  }

嗨,我发现此方法存在问题,它限制了ALOT可以达到的最大采样率,如果需要快速ADC转换,则不建议使用此方法。
理查德·班福德

2

我想补充一点,对于我的设置(nucleo-h743)来说,这还不够:

hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;

我还必须启用溢出设置:

hadc1.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;

没有这个,HAL_ADC_PollForConversion仍然会阻塞。我不完全理解为什么这样做是必要的,但确实允许我以连续模式进行轮询。


0

这对我有用,希望对您有所帮助:

if (HAL_ADC_Start(&hadc) != HAL_OK)
{
    /* Start Conversation Error */
    // Error_Handler();
}
if (HAL_ADC_PollForConversion(&hadc, 500) != HAL_OK)
{
    /* End Of Conversion flag not set on time */
    // Error_Handler();
    ADCValue=-1;
}
else
{
    /* ADC conversion completed */
    /*##-5- Get the converted value of regular channel ########################*/
    ADCValue = HAL_ADC_GetValue(&hadc);
}
HAL_ADC_Stop(&hadc);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.