RT_Thread:STM32L0系列ADC驱动的支持与修改

1.在项目中配置头文件《rtconfig.h》需要添加硬件外设的使用定义

#define BSP_USING_ADC1

2.而在《adc_config.h》头文件中,针对L0系列的配置参数内容也有区别,如下调整后的ADC1_CONFIG为L0系列的,而ADC2_CONFIG则为原有L4系列的内容。

#ifdef BSP_USING_ADC1
#ifndef ADC1_CONFIG
#define ADC1_CONFIG                                                 \
    {                                                               \
       .Instance                   = ADC1,                          \
       .Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV1,      \
       .Init.OversamplingMode      = DISABLE,                       \
       .Init.Resolution            = ADC_RESOLUTION_12B,            \
       .Init.SamplingTime          = ADC_SAMPLETIME_12CYCLES_5,     \
       .Init.DataAlign             = ADC_DATAALIGN_RIGHT,           \
       .Init.ScanConvMode          = ADC_SCAN_DIRECTION_FORWARD,    \
       .Init.EOCSelection          = ADC_EOC_SINGLE_CONV,           \
       .Init.LowPowerAutoWait      = DISABLE,                       \
       .Init.ContinuousConvMode    = DISABLE,                       \
       .Init.DiscontinuousConvMode = DISABLE,                       \
       .Init.ExternalTrigConv      = ADC_SOFTWARE_START,            \
       .Init.DMAContinuousRequests = DISABLE,                       \
       .Init.Overrun               = ADC_OVR_DATA_PRESERVED,        \
       .Init.LowPowerAutoWait      = DISABLE,                       \
       .Init.LowPowerFrequencyMode = DISABLE,                       \
       .Init.LowPowerAutoPowerOff  = DISABLE,                       \
    }
#endif /* ADC1_CONFIG */
#endif /* BSP_USING_ADC1 */

#ifdef BSP_USING_ADC2
#ifndef ADC2_CONFIG
#define ADC2_CONFIG                                                 \
    {                                                               \
       .Instance                   = ADC2,                          \
       .Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV4,      \
       .Init.Resolution            = ADC_RESOLUTION_12B,            \
       .Init.DataAlign             = ADC_DATAALIGN_RIGHT,           \
       .Init.ScanConvMode          = ADC_SCAN_DISABLE,              \
       .Init.EOCSelection          = ADC_EOC_SINGLE_CONV,           \
       .Init.LowPowerAutoWait      = DISABLE,                       \
       .Init.ContinuousConvMode    = DISABLE,                       \
       .Init.NbrOfConversion       = 1,                             \
       .Init.DiscontinuousConvMode = DISABLE,                       \
       .Init.NbrOfDiscConversion   = 1,                             \
       .Init.ExternalTrigConv      = ADC_SOFTWARE_START,            \
       .Init.DMAContinuousRequests = DISABLE,                       \
       .Init.Overrun               = ADC_OVR_DATA_OVERWRITTEN,      \
    }
#endif /* ADC2_CONFIG */
#endif /* BSP_USING_ADC2 */

3.对于《drv_adc.c》文件该文件L0系列没有,需要从L4系列中拷贝),同样有比较多的地方修改,以适应L071系列芯片

首先是通道数获取函数stm32_adc_get_channel,增加L0系列的宏定义

#if defined SOC_SERIES_STM32L0
#  if defined (STM32L053xx) || defined (STM32L063xx) || defined (STM32L073xx) || defined (STM32L083xx)
    case 16:
        stm32_channel = ADC_CHANNEL_16;
        break;
#  endif
#endif

获取ADC值的函数stm32_get_adc_value需要添加L0系列预编译分支

#if defined(SOC_SERIES_STM32F1)
    if (channel <= 17)
#elif defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) \
        || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0)
    if (channel <= 18)
#elif defined(SOC_SERIES_STM32L0)
    if (channel <= 18)  
#endif

同样在函数stm32_get_adc_value中,L0 的rank操作不一样的,需要增加L0的预编译定义

#if defined(SOC_SERIES_STM32L0)
    ADC_ChanConf.Rank = ADC_RANK_CHANNEL_NUMBER;
#else
    ADC_ChanConf.Rank = 1;
#endif

4.另外,注意打开hal_conf.h文件中的ADC选项

5.非常重要的一点,ST的驱动里面,关于通道channel的配置时,如果配置过一个通道,再去配置另一个通道,则会两个通道都打开,这时候,两个通道测试就会产生问题,即出现两个通道的值一样的情况(取了其中一个通道的值,取了哪个通道的值取决于采样转换是通道增序还是减序),根本原有在于驱动代码的HAL_ADC_ConfigChannel函数中,对通道的配置是采用或来取值了,如下

hadc->Instance->CHSELR |= (uint32_t)(sConfig->Channel & ADC_CHANNEL_MASK);

而实际使用时,又是一个通道一个通道来采样转换的,因此需要把“或”改成“等”,即:

hadc->Instance->CHSELR = (uint32_t)(sConfig->Channel & ADC_CHANNEL_MASK);

6.这时候如果直接使用,可能会出现实际值和ADC测量的值不准确的问题,这是由于ADC的误差造成的,ST的L071系列MCU支持了出厂校准,因此可以考虑在函数stm32_adc_init(void)中执行HAL_ADC_Init函数之后,做一次校准:

首先是在rtconfig.h头文件中添加BSP_ADC_CALIBRATION宏定义,然后在下面的HAL_ADC_Init函数成功之后执行一次校准

if (HAL_ADC_Init(&stm32_adc_obj[i].ADC_Handler) != HAL_OK)
        {
            LOG_E("%s init failed", name_buf);
            result = -RT_ERROR;
        }
        else
        {
#if defined(BSP_ADC_CALIBRATION) && defined(SOC_SERIES_STM32L0)
            if( HAL_ADCEx_Calibration_Start( &stm32_adc_obj[i].ADC_Handler, ADC_SINGLE_ENDED ) != HAL_OK )
            {
		result = -RT_ERROR;
            }
#endif

7.接下去就可以使用官方的ADC驱动demo的使用方式,使用ADC这部分的驱动,并且校准之后的ADC值也非常准确了,棒棒哒~~

 

你可能感兴趣的:(RT_Thread,STM32学习)