基于 RT_Thread 的ADC驱动源代码 drv_adc.c
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);
}
基于 RT_Thread 的ADC驱动源代码 drv_adc.c相关推荐
- s3c2410多通道adc驱动及测试程序
网上流行很多基于2410的ADC驱动及测试程序.本文所使用的是开发板光盘中带有了经过修改后的adc驱动.笔者在这个基础上再作一点修改.由于那个文件已经删除了版权信息,这里也不知道如何添加了,可以肯定的 ...
- MG995舵机工作原理及基于STM32的驱动源代码
MG995舵机工作原理及基于STM32的驱动源代码 一·MG995舵机工作原理 1.MG995舵机简介 产品型号 MG995 产品尺寸 40.7*19.7*42.9mm 产品重量 55g 工作扭矩 1 ...
- 基于HI3516/HI3518/HI3559内部ADC驱动实现
提示:除了以上三种SOC,海思HI35XX其他SOC实现流程也应该类似,本篇文章以HI3516为主体进行实现. 文章目录 前言 一.相关资料 二.实现原理及步骤 1.原理 2.步骤 三.代码实现 前言 ...
- 基于linux的驱动设计,《基于LINUX的虚拟驱动设计》-毕业论文.doc
PAGE 40 l 摘 要 驱动程序是当前最热门.最有发展前途的IT应用技术之一.目前的驱动程序的开发主要应用在包括键盘 .鼠标.扫描仪.打印机以及存储设备等日益普及的设备之间的通讯上.但是要使这些设 ...
- USB学习5---android usb驱动源代码目录说明
kernel\msm-3.18\drivers\usb下目录内容 我们msm8937+android7.1平台编译out目录下usb目录下有编译到的目录如下: 我们先参考kernel\msm-3.18 ...
- 基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ
基于OMAPL138的字符驱动_GPIO驱动AD9833(三)之中断申请IRQ 0. 导语 学习进入到了下一个阶段,还是以AD9833为例,这次学习是向设备申请中断,实现触发,在未来很多场景,比如做用 ...
- 基于MTD的NAND驱动开发(二)
基于MTD的NAND驱动开发(二) 基于MTD的NAND驱动开发(三) http://blog.csdn.net/leibniz_zsu/article/details/4977853 http:// ...
- ServerSuperIO Designer IDE 发布,打造物联网通讯大脑,随心而联。附:C#驱动源代码。
1.概况 注:ServerSuperIO Designer IDE 同行业网友随便使用,不涉及到软件使用限制的问题. 从2015年到现在的将近两年的时间,一直在开发.完善ServerSuperIO(S ...
- 基于Linux操作系统的底层驱动技术
5.3 基于Linux操作系统的底层驱动技术 这里的底层驱动是指Linux下的底层设备驱动,这些驱动通常都是加载在内核态的,可以提供给上层用户态的应用程序访问底层设备的能力.也就是说,上层应用程序通过 ...
最新文章
- opencv otsu二值化
- java代码编译之后是如何运行的?不知道这些,面试官问你jvm问题,你只能懵圈
- 边缘计算、区块链、5G,哪个能走的更远
- 企业架构规划及服务器优化参数
- C#.NET 消息机制
- win7卡在正在启动windows界面_win7开机一直卡在欢迎界面如何解决?
- linux如何卸载telnet命令,linux安装telnet命令
- 21年最新-李沐-动手学深度学习第二版
- AD18单位mm和mil切换
- Flink大声说,丢数据这个锅,我们不背!
- 某蒟蒻无聊竟用UNO做了个复读机?
- 【读书摘录】《沉默的大多数》(王小波)
- linux git版本更新
- 扫码支付 (基于微信)
- Filter过滤器基本内容
- 中国音乐史记•黄家驹列传
- MacBook Air老本重装系统
- 关于二分查找及其上下界问题的一些思考
- Linux实战技巧--文件系统操作(一)--文件查看(pwd/ls/cd)
- python中的方法
热门文章
- mysql linq any查询_LINQ标准查询操作符详解(转)
- Angular 小专题:玩转注射器
- ArcgisDestop提示修复许可问题解决
- K-均值聚类算法的原理与实现
- 昨夜无眠 转自科学网程代展博文] (2012-11-13 21:09:13)
- linux电脑声音手机播放,如何将电脑声音用手机扬声器播放?
- 使用iperf进行局域网内测速
- 交流电、交流信号、直流电、直流信号
- 上海物联网共享实验室揭牌
- arcgis js平滑线工具_ArcGIS For JavaScript API Drawing Tool —— 绘图工具