/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2018-12-05 zylx first version * 2018-12-12 greedyhao Porting for stm32f7xx */ #include #if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3) #include "drv_config.h" //#define DRV_DEBUG #define LOG_TAG "drv.adc" #include static ADC_HandleTypeDef adc_config[] = { #ifdef BSP_USING_ADC1 ADC1_CONFIG, #endif #ifdef BSP_USING_ADC2 ADC2_CONFIG, #endif #ifdef BSP_USING_ADC3 ADC3_CONFIG, #endif }; struct stm32_adc { ADC_HandleTypeDef ADC_Handler; struct rt_adc_device stm32_adc_device; }; static struct stm32_adc stm32_adc_obj[sizeof(adc_config) / sizeof(adc_config[0])]; static rt_err_t stm32_adc_enabled(struct rt_adc_device *device, rt_uint32_t channel, rt_bool_t enabled) { ADC_HandleTypeDef *stm32_adc_handler = device->parent.user_data; RT_ASSERT(device != RT_NULL); if (enabled) { #ifdef SOC_SERIES_STM32L4 ADC_Enable(stm32_adc_handler); #else __HAL_ADC_ENABLE(stm32_adc_handler); #endif } else { #ifdef SOC_SERIES_STM32L4 ADC_Disable(stm32_adc_handler); #else __HAL_ADC_DISABLE(stm32_adc_handler); #endif } return RT_EOK; } static rt_uint32_t stm32_adc_get_channel(rt_uint32_t channel) { rt_uint32_t stm32_channel = 0; switch (channel) { case 0: stm32_channel = ADC_CHANNEL_0; break; case 1: stm32_channel = ADC_CHANNEL_1; break; case 2: stm32_channel = ADC_CHANNEL_2; break; case 3: stm32_channel = ADC_CHANNEL_3; break; case 4: stm32_channel = ADC_CHANNEL_4; break; case 5: stm32_channel = ADC_CHANNEL_5; break; case 6: stm32_channel = ADC_CHANNEL_6; break; case 7: stm32_channel = ADC_CHANNEL_7; break; case 8: stm32_channel = ADC_CHANNEL_8; break; case 9: stm32_channel = ADC_CHANNEL_9; break; case 10: stm32_channel = ADC_CHANNEL_10; break; case 11: stm32_channel = ADC_CHANNEL_11; break; case 12: stm32_channel = ADC_CHANNEL_12; break; case 13: stm32_channel = ADC_CHANNEL_13; break; case 14: stm32_channel = ADC_CHANNEL_14; break; case 15: stm32_channel = ADC_CHANNEL_15; break; case 16: stm32_channel = ADC_CHANNEL_16; break; case 17: stm32_channel = ADC_CHANNEL_17; break; #if defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) case 18: stm32_channel = ADC_CHANNEL_18; break; #endif } return stm32_channel; } static rt_err_t stm32_get_adc_value(struct rt_adc_device *device, rt_uint32_t channel, rt_uint32_t *value) { ADC_ChannelConfTypeDef ADC_ChanConf; ADC_HandleTypeDef *stm32_adc_handler = device->parent.user_data; RT_ASSERT(device != RT_NULL); RT_ASSERT(value != RT_NULL); rt_memset(&ADC_ChanConf, 0, sizeof(ADC_ChanConf)); #if defined(SOC_SERIES_STM32F1) if (channel <= 17) #elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) if (channel <= 18) #endif { /* set stm32 ADC channel */ ADC_ChanConf.Channel = stm32_adc_get_channel(channel); } else { #if defined(SOC_SERIES_STM32F1) LOG_E("ADC channel must be between 0 and 17."); #elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) LOG_E("ADC channel must be between 0 and 18."); #endif return -RT_ERROR; } ADC_ChanConf.Rank = 1; #if defined(SOC_SERIES_STM32F1) ADC_ChanConf.SamplingTime = ADC_SAMPLETIME_55CYCLES_5; #elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) ADC_ChanConf.SamplingTime = ADC_SAMPLETIME_112CYCLES; #elif defined(SOC_SERIES_STM32L4) ADC_ChanConf.SamplingTime = ADC_SAMPLETIME_247CYCLES_5; #endif #if defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) ADC_ChanConf.Offset = 0; #endif #ifdef SOC_SERIES_STM32L4 ADC_ChanConf.OffsetNumber = ADC_OFFSET_NONE; ADC_ChanConf.SingleDiff = LL_ADC_SINGLE_ENDED; #endif HAL_ADC_ConfigChannel(stm32_adc_handler, &ADC_ChanConf); /* start ADC */ HAL_ADC_Start(stm32_adc_handler); /* Wait for the ADC to convert */ HAL_ADC_PollForConversion(stm32_adc_handler, 10); /* get ADC value */ *value = (rt_uint32_t)HAL_ADC_GetValue(stm32_adc_handler); return RT_EOK; } static const struct rt_adc_ops stm_adc_ops = { .enabled = stm32_adc_enabled, .convert = stm32_get_adc_value, }; static int stm32_adc_init(void) { int result = RT_EOK; /* save adc name */ char name_buf[6] = {0}; int i = 0; for (i = 0; i < sizeof(adc_config) / sizeof(adc_config[0]); i++) { /* ADC init */ stm32_adc_obj[i].ADC_Handler = adc_config[i]; if (HAL_ADC_Init(&stm32_adc_obj[i].ADC_Handler) != HAL_OK) { LOG_E("ADC%d init failed", i + 1); result = -RT_ERROR; } else { rt_sprintf(name_buf, "adc%d", i + 1); /* register ADC device */ if (rt_hw_adc_register(&stm32_adc_obj[i].stm32_adc_device, name_buf, &stm_adc_ops, &stm32_adc_obj[i].ADC_Handler) == RT_EOK) { LOG_D("ADC%d init success", i + 1); } else { LOG_E("ADC%d register failed", i + 1); result = -RT_ERROR; } } } return result; } INIT_BOARD_EXPORT(stm32_adc_init); #endif /* BSP_USING_ADC */