RT-Thread 设备驱动ADC浅析与改进
OS版本:RT-Thread 4.0.0
芯片:STM32F407
下面时官方ADC提供的参考访问接口
访问 ADC 设备
应用程序通过 RT-Thread 提供的 ADC 设备管理接口来访问 ADC 硬件,相关接口如下所示:
| 函数 | 描述 |
|---|---|
| rt_device_find() | 根据 ADC 设备名称查找设备获取设备句柄 |
| rt_adc_enable() | 使能 ADC 设备 |
| rt_adc_read() | 读取 ADC 设备数据 |
| rt_adc_disable() | 关闭 ADC 设备 |
下面对驱动源码主要实现方式做简要分析:
在drv_adc.c中,缺少对 RT_USING_DEVICE_OPS 项的支持,增加如下代码
#ifdef RT_USING_DEVICE_OPS //增加对RT_USING_DEVICE_OPS的支持
const static struct rt_device_ops adc_ops =
{
RT_NULL,
RT_NULL,
RT_NULL,
_adc_read,
RT_NULL,
_adc_control
};
#endif rt_err_t rt_hw_adc_register(rt_adc_device_t device, const char *name, const struct rt_adc_ops *ops, const void *user_data)
{
rt_err_t result = RT_EOK;
RT_ASSERT(ops != RT_NULL && ops->convert != RT_NULL); device->parent.type = RT_Device_Class_Miscellaneous; #ifdef RT_USING_DEVICE_OPS
device->parent.ops = &adc_ops;
#else
device->parent.init = RT_NULL;
device->parent.open = RT_NULL;
device->parent.close = RT_NULL;
device->parent.read = _adc_read;
device->parent.write = RT_NULL;
device->parent.control = _adc_control;
#endif device->ops = ops;
device->parent.user_data = (void *)user_data; result = rt_device_register(&device->parent, name, RT_DEVICE_FLAG_RDWR); return result;
}
其中设备ops接口要实现 adc_ops
const static struct rt_device_ops adc_ops =
{
RT_NULL,
RT_NULL,
RT_NULL,
_adc_read,
RT_NULL,
_adc_control
};
设备的子类 rt_adc_device 需要实现的ops 为 rt_adc_ops
static const struct rt_adc_ops stm_adc_ops =
{
.enabled = stm32_adc_enabled,
.convert = stm32_get_adc_value,
};
其中 _adc_control 调用 stm32_adc_enabled, _adc_read 调用 stm32_get_adc_value;
官方示例为了简化ADC驱动操作,直接export相关adc操作函数供用户使用,使用方式如下:
rt_adc_device_t adc_dev;
rt_uint32_t value, vol;
rt_err_t ret = RT_EOK; /* 查找设备 */
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
if (adc_dev == RT_NULL)
{
rt_kprintf("adc sample run failed! can't find %s device!\n", ADC_DEV_NAME);
return RT_ERROR;
} /* 使能设备 */
ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL); /* 读取采样值 */
value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);
rt_kprintf("the value is :%d \n", value); /* 转换为对应电压值 */
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / , vol % ); /* 关闭通道 */
ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);
既然有I/O设备模型,再使用这种方式现得驱动接口太分散了,下面以 I/O device接口实现adc采集示例:
使用 rt_device_read 时,注意 pos 和 size 的含义
rt_device_t adc_dev = rt_device_find(ADC_DEV_NAME);
rt_device_open(adc_dev, RT_DEVICE_FLAG_RDWR); //记住一定要有打开设备操作,否则后面的rt_device_read无法使用 ret = rt_device_control(adc_dev, RT_ADC_CMD_ENABLE, (void*)ADC_DEV_CHANNEL); //使能ADC ret = rt_device_read(adc_dev, ADC_DEV_CHANNEL, &value, ); //程序不做修改时,_adc_read函数的pos项表示adc通道,size为4的倍数,大于4则依序读取后面的通道
// value = rt_adc_read((rt_adc_device_t)adc_dev, ADC_DEV_CHANNEL);
rt_kprintf("the value is :%d %d %d\n", value, ret, *_rt_errno());
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / , vol % ); ret = rt_device_control(adc_dev, RT_ADC_CMD_DISABLE, (void*)ADC_DEV_CHANNEL); //禁止ADC
改进建议:
读取adc使用 rt_device_read 很不方便,建议取消 rt_device_read 项,读取采用 rt_device_control 来实现;
const static struct rt_device_ops adc_ops =
{
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
RT_NULL,
_adc_control
};
在adc.h中添加对 RT_ADC_CMD_READ 的支持,并添加对于读取数据参数结构体
struct rt_device_adc_value
{
rt_uint32_t channel;
rt_uint32_t value;
}; typedef enum
{
RT_ADC_CMD_ENABLE,
RT_ADC_CMD_DISABLE,
RT_ADC_CMD_READ,
} rt_adc_cmd_t;
在adc.c中的_adc_control 函数添加对 RT_ADC_CMD_READ 的支持
static rt_err_t _adc_control(rt_device_t dev, int cmd, void *args)
{
rt_err_t result = RT_EOK;
rt_adc_device_t adc = (struct rt_adc_device *)dev; if (adc->ops->enabled == RT_NULL)
{
return -RT_ENOSYS;
}
if (cmd == RT_ADC_CMD_ENABLE)
{
result = adc->ops->enabled(adc, (rt_uint32_t)args, RT_TRUE);
}
else if (cmd == RT_ADC_CMD_DISABLE)
{
result = adc->ops->enabled(adc, (rt_uint32_t)args, RT_FALSE);
}
else if (cmd == RT_ADC_CMD_READ) //通过control读取adc指定通道
{
struct rt_device_adc_value *adc_value;
adc_value = (struct rt_device_adc_value *) args;
if (adc_value == RT_NULL) return -RT_ERROR; result = adc->ops->convert(adc, adc_value->channel, &(adc_value->value));
} return result;
}
使用方式如下:
rt_device_t adc_dev = rt_device_find(ADC_DEV_NAME);
rt_device_open(adc_dev, RT_DEVICE_FLAG_RDWR); //记住一定要有打开设备操作,否则后面的rt_device_read无法使用 ret = rt_device_control(adc_dev, RT_ADC_CMD_ENABLE, (void*)ADC_DEV_CHANNEL); //使能ADC struct rt_device_adc_value adc_value;
adc_value.channel = ADC_DEV_CHANNEL;
ret = rt_device_control(adc_dev, RT_ADC_CMD_READ, &adc_value);
value = adc_value.value; rt_kprintf("the value is :%d %d %d\n", value, ret, *_rt_errno());
vol = value * REFER_VOLTAGE / CONVERT_BITS;
rt_kprintf("the voltage is :%d.%02d \n", vol / , vol % ); ret = rt_device_control(adc_dev, RT_ADC_CMD_DISABLE, (void*)ADC_DEV_CHANNEL); //禁止ADC
RT-Thread 设备驱动ADC浅析与改进的更多相关文章
- RT thread 设备驱动组件之USART设备
本文以stm32f4xx平台介绍串口驱动,主要目的是:1.RTT中如何编写中断处理程序:2.如何编写RTT设备驱动接口代码:3.了解串行设备的常见处理机制.所涉及的主要源码文件有:驱动框架文件(usa ...
- linux设备驱动模型-浅析-转
1. typeof typeof并非ISO C的关键字,而是gcc对C的一个扩展.typeof是一个关键字(类似sizeof),用于获取一个表达式的类型. 举个简单的例子: char tt; typ ...
- RT-Thread 设备驱动I2C浅析及使用
由于 I2C 可以控制多从机的属性,设备驱动模型分为 I2C总线设备(类似与Linux里面的I2C适配器) + I2C从设备: 系统I2C设备驱动主要实现 I2C 总线设备驱动,而具体的I2C 从设 ...
- RT-Thread 设备驱动SPI浅析及使用
OS版本:RT-Thread 4.0.0 测试BSP:STM32F407 SPI简介 SPI总线框架其实和I2C差不多,可以说都是总线设备+从设备,但SPI设备的通信时序配置并不固定,也就是说控制特定 ...
- RT-Thread 设备驱动UART浅析
OS版本:RT-Thread 4.0.0 芯片:STM32F407 RT-Thread的串口驱动框架与Linux相识,分成 I/O设备框架 + 设备底层驱动: 1. serial设备初始化及使用 将配 ...
- RT Thread的SPI设备驱动框架的使用以及内部机制分析
注释:这是19年初的博客,写得很一般,理解不到位也不全面.19年末得空时又重新看了RTThread的SPI和GPIO,这次理解得比较深刻.有时间时再整理上传. -------------------- ...
- linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟【转】
本文转载自:http://blog.chinaunix.net/uid-25014876-id-119723.html linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟 xxxxxxxxxx ...
- linux 混杂设备驱动之adc驱动
linux2.6.30.4中,系统已经自带有了ADC通用驱动文件---arch/arm/plat-s3c24xx/adc.c,它是以平台驱动设备模型的架构来编写的,里面是一些比较通用稳定的代码,但是l ...
- 【Linux开发】linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟
linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
随机推荐
- 某考试 T1 arg
题目描述 给出一个长度为 m 的序列 A, 请你求出有多少种 1...n 的排列, 满足 A 是它的一个 LIS. 输入格式 第一行两个整数 n, m. 接下来一行 m 个整数, 表示 A. 输出格式 ...
- IE浏览器不能上传图片
这时将弹出一个“安全设置-Internet选项”对话框,把右侧滚动条慢慢地往下拉. 找到“其他/将文件上载到服务器包含本地目录路径”点击下面的“启用”功能
- 关于MSSQL的decimal(numeric)、money、float的使用以及区别
decimal(numeric).money.float(real) 都是MSSQL中的浮点类型的数据类型. 按存储的范围进行排序 float(real) decimal(numeric) money ...
- httpclient请求去掉返回结果string中的多余转义字符
public String doGet() { String uriAPI = "http://XXXXX?str=I+am+get+String"; String result= ...
- 【Nginx】ngx_event_core_module事件模块
功能:创建连接池,决定使用哪些事件驱动机制,以及初始化将要使用的事件模块 该模块定义了ngx_event_core_commands数组处理其感兴趣的7个配置项 ngx_event_conf_t为该模 ...
- Idea 13 新建maven项目
1.此时生成的maven项目没有web文件夹 file→New Project→Maven→Next→GID.AID (NewDemo)→Next→ProjectName(NewDemo)→Finis ...
- 【Mongodb教程 第五课 】MongoDB 删除集合
drop() 方法 MongoDB 的 db.collection.drop() 是用来从数据库中删除一个集合. 语法: drop() 命令的基本语法如下 db.COLLECTION_NAME.dro ...
- IIS 配置 FTP 网站 H5 音频标签自定义样式修改以及添加播放控制事件
IIS 配置 FTP 网站 在 服务器管理器 的 Web服务器IIS 上安装 FTP 服务 在 IIS管理器 添加FTP网站 配置防火墙规则 说明:服务器环境是Windows Server 200 ...
- 使用7zip压解各种文件的经常使用命令
7zip简单介绍 格式支持 压缩解压缩 仅支持解压缩 安装 Debian Ubuntu ArchLinux 使用 打包 解压 列出文件的信息列表 检查包的完整性 更新压缩包 删除包里的文件 7zip简 ...
- IOS开发基础之—MD5加密算法【转】
原文地址:http://blog.csdn.net/pjk1129/article/details/6855024 #import <CommonCrypto/CommonDigest.h> ...