这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » STM32 » ADC周期采样之软件实现

共2条 1/1 1 跳转至

ADC周期采样之软件实现

院士
2026-05-17 11:04:27     打赏

ADC外设做为沟通数字电路与模拟电路的桥梁,其作用不言而喻。在大多数项目应用中,ADC采样均为周期采样。比如温度每5秒采样一次,电流采样可能10ms一次,1000ms一次等。这样,不仅便于滤波,而且更便于反映真实的模拟世界的情况。下面,我们就在STM32F407上实现ADC的软件方式触发周期采样。

STM32F407在实现软件触发ADC采样都是分为两部分,第一部分是ADC外设的初始化;第二部分是软件周期触发。第一部分的ADC外设初始化是标准的,流程的,必须按照手册来执行

/* ADC handle declaration */
ADC_HandleTypeDef hadc1;

/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
void MX_ADC1_Init(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};

    /* 1. Enable ADC1 Clock */
    __HAL_RCC_ADC1_CLK_ENABLE();

    /* 2. Configure ADC Global Parameters */
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; /* ADC clock <= 36MHz */
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;           /* 12-bit resolution */
    hadc1.Init.ScanConvMode = DISABLE;                    /* Single channel, no scan */
    hadc1.Init.ContinuousConvMode = DISABLE;              /* Single conversion mode */
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Software trigger */
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;           /* Right alignment */
    hadc1.Init.NbrOfConversion = 1;                       /* 1 conversion in sequence */
    hadc1.Init.DMAContinuousRequests = DISABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;

    if (HAL_ADC_Init(&hadc1) != HAL_OK)
    {
        /* Initialization Error */
        Error_Handler();
    }

    /* 3. Configure ADC Channel 0 (PA0) */
    sConfig.Channel = ADC_CHANNEL_0;      /* Select Channel 0 */
    sConfig.Rank = 1;                     /* Rank 1 in regular sequence */
    sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; /* Longest sampling time for stability */

    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
    {
        /* Configuration Error */
        Error_Handler();
    }
}

/**
  * @brief ADC MSP Initialization
  *        This function configures the hardware resources used in this example:
  *           - Peripheral's clock enable
  *           - Peripheral's GPIO Configuration
  * @param hadc: ADC handle pointer
  * @retval None
  */
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    if(hadc->Instance == ADC1)
    {
        /* 1. Enable GPIOA Clock */
        __HAL_RCC_GPIOA_CLK_ENABLE();

        /* 2. Configure PA0 as Analog Input */
        GPIO_InitStruct.Pin = GPIO_PIN_0;
        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
        GPIO_InitStruct.Pull = GPIO_NOPULL;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    }
}

第二部分就是软件周期触发。这里我常用两种方式来实现,一种是通过systick计时,并在while(1)检查是否溢出;

while(1)
{
    if(adc_tick_cnt == 0)
    {
        /* Start ADC Conversion */
        if (HAL_ADC_Start(&hadc1) != HAL_OK)
        {
            return 0; /* Return 0 if start failed */
        }

        /* Wait for End Of Conversion (with timeout) */
        if (HAL_ADC_PollForConversion(&hadc1, 100) != HAL_OK)
        {
            return 0; /* Return 0 if timeout or error */
        }
    
        /* Get ADC Converted Value */
        adc_value = HAL_ADC_GetValue(&hadc1);
    
        /* Stop ADC to save power (optional for single shot) */
        HAL_ADC_Stop(&hadc1);    
    }
}

另一种是通过RTOS的delay()函数来实现的周期触发;

void adc_sample_task(void)
{
    vTaskDelay(100);
    adc_volt_get(&volt_buf[0]);
}

ADC软件触发流程简单,代码清晰,检查起来也非常方便。但由于ADC软件触发的周期性并不严格,所以对于一些实时性强要求的应用来说,软件触发的时间偏差不是被允许的。下一期,我们一起使用定时器来实现严格的周期采样。




关键词: ADC     软件触发    

院士
2026-05-17 11:27:21     打赏
2楼

学习了,谢谢分享。


共2条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]