1、开发环境
RT_Thread Studio 开发编译软件
RT_Thread latest 版本
2、代码配置
2.1 打开stm32f1xx_hal_conf.h中的HAL_ADC_MODULE_ENABLED宏定义注释
#define HAL_ADC_MODULE_ENABLED
2.2 ADC驱动源代码drv_adc.c (基于RT_Thread系统)
#include <rthw.h>
#include <rtdevice.h>
#include <rtthread.h>
#include <board.h>
#if defined(BSP_USING_ADC1) || defined(BSP_USING_ADC2) || defined(BSP_USING_ADC3)
#include "adc_config.h"
//#define DRV_DEBUG
#define LOG_TAG "drv.adc"
#include <at_log.h>
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)
{
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0)
ADC_Enable(stm32_adc_handler);
#else
__HAL_ADC_ENABLE(stm32_adc_handler);
#endif
}
else
{
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0)
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_STM32F0) || 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_STM32F0) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) \
|| defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0)
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_STM32F0) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) \
|| defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G0)
LOG_E("ADC channel must be between 0 and 18.");
#endif
return -RT_ERROR;
}
ADC_ChanConf.Rank = 1;
#if defined(SOC_SERIES_STM32F0)
ADC_ChanConf.SamplingTime = ADC_SAMPLETIME_71CYCLES_5;
#elif 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, 100);
/* 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,
};
void MX_ADC_Init(void)
{
RCC_PeriphCLKInitTypeDef ADC_CLKInit;
ADC_CLKInit.PeriphClockSelection=RCC_PERIPHCLK_ADC; //ADC外设时钟
ADC_CLKInit.AdcClockSelection=RCC_ADCPCLK2_DIV6; //分频因子6时钟为72M/6=12MHz
HAL_RCCEx_PeriphCLKConfig(&ADC_CLKInit); //设置ADC时钟
__HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟
}
int stm32_adc_init(void)
{
int result = RT_EOK;
/* save adc name */
char name_buf[5] = {'a', 'd', 'c', '0', 0};
int i = 0;
for (i = 0; i < sizeof(adc_config) / sizeof(adc_config[0]); i++)
{
/* ADC init */
name_buf[3] = '0';
stm32_adc_obj[i].ADC_Handler = adc_config[i];
#if defined(ADC1)
if (stm32_adc_obj[i].ADC_Handler.Instance == ADC1)
{
name_buf[3] = '1';
}
#endif
#if defined(ADC2)
if (stm32_adc_obj[i].ADC_Handler.Instance == ADC2)
{
name_buf[3] = '2';
}
#endif
#if defined(ADC3)
if (stm32_adc_obj[i].ADC_Handler.Instance == ADC3)
{
name_buf[3] = '3';
}
#endif
MX_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
{
/* 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("%s init success", name_buf);
}
else
{
LOG_E("%s register failed", name_buf);
result = -RT_ERROR;
}
}
}
return result;
}
INIT_APP_EXPORT(stm32_adc_init);
#endif /* BSP_USING_ADC */
2.3 ADC的HAL库源代码drv_adc_hal.c
(注:HAL库源代码,不限制RT_Thread嵌入式实时操作系统)
#include <rthw.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "board.h"
#define DBG_TAG "drv_adc_hal"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
ADC_HandleTypeDef hadc1;
int MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
RCC_PeriphCLKInitTypeDef ADC_CLKInit;
ADC_CLKInit.PeriphClockSelection=RCC_PERIPHCLK_ADC; //ADC外设时钟
ADC_CLKInit.AdcClockSelection=RCC_ADCPCLK2_DIV6; //分频因子6时钟为72M/6=12MHz
HAL_RCCEx_PeriphCLKConfig(&ADC_CLKInit); //设置ADC时钟
__HAL_RCC_ADC1_CLK_ENABLE(); //使能ADC1时钟
hadc1.Instance=ADC1;
hadc1.Init.DataAlign=ADC_DATAALIGN_RIGHT; //右对齐
hadc1.Init.ScanConvMode=DISABLE; //不扫描模式
hadc1.Init.ContinuousConvMode=DISABLE; //不连续转换
hadc1.Init.NbrOfConversion=1; //一个规则通道转换
hadc1.Init.DiscontinuousConvMode=DISABLE; //禁止不连续采样模式
hadc1.Init.NbrOfDiscConversion=0; //不连续采样通道数为0
hadc1.Init.ExternalTrigConv=ADC_SOFTWARE_START; //软件触发
HAL_ADC_Init(&hadc1); //初始化
HAL_ADCEx_Calibration_Start(&hadc1); //校准ADC
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE(); //开启GPIOB时钟
GPIO_Initure.Pin=GPIO_PIN_1|GPIO_PIN_0; //PA1和PA0
GPIO_Initure.Mode=GPIO_MODE_ANALOG; //模拟输入
GPIO_Initure.Pull=GPIO_NOPULL; //不带上下拉
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
return 0;
}
static rt_uint32_t 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_STM32F0) || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4)
case 18:
stm32_channel = ADC_CHANNEL_18;
break;
#endif
}
return stm32_channel;
}
rt_uint32_t get_adc_value(rt_uint8_t channel)
{
ADC_ChannelConfTypeDef ADC1_ChanConf;
ADC1_ChanConf.Channel= adc_get_channel(channel); //通道
ADC1_ChanConf.Rank=1; //第1个序列,序列1
ADC1_ChanConf.SamplingTime=ADC_SAMPLETIME_55CYCLES_5; //采样时间
HAL_ADC_ConfigChannel(&hadc1,&ADC1_ChanConf); //通道配置
HAL_ADC_Start(&hadc1); //开启ADC
HAL_ADC_PollForConversion(&hadc1, 10);
return (rt_uint32_t)HAL_ADC_GetValue(&hadc1);
}