现代传感器的接口:中断驱动的ADC驱动程序
现代传感器的接口:中断驱动的ADC驱动程序
Interfacing with modern sensors: Interrupt driven ADC drivers
研究了如何编写一个阻塞的模数转换器(ADC)驱动程序和一个使用轮询技术不阻塞应用程序流的驱动程序。轮询外围设备的驱动程序效率低下,如果系统处于低功耗状态,可能会浪费宝贵的时钟周期,否则会浪费能量。开发人员实现ADC驱动程序的一种有效方法是使用中断来通知应用程序转换周期已经完成。在本文中,将研究如何做到这一点。
更新ADC驱动程序示例函数
有几种不同的方法可以编写ADC驱动程序来使用中断。在本文中,将介绍如何修改上一篇文章中介绍的非阻塞ADC驱动程序。应用程序可以通过调用函数ADC_Sample来启动ADC转换。
这是一个很好的例子,为什么有一个好的硬件抽象层(HAL)可以派上用场。无论是阻塞,还是阻塞、轮询或中断,都会调用完全相同的函数,其行为只是根据驱动程序的配置设置而改变,或者可能会根据应用程序的需要链接到不同版本的Adc_Sample函数中。
非阻塞系统的Adc_Sample函数如下所示:
bool Adc_Sample(void)
{
AdcPin_t AdcPin = AdcChannel0;
static bool SampleInProgress = false;
bool SampleComplete = false;
if(SampleInProgress == false)
{
if(Adc_SampleIndex == ADC_SAMPLE_SIZE)
{
Adc_SampleIndex = 0;
}
SampleInProgress = true;
Adc_StartConversion();
}
else
{
if(Adc_ConversionComplete == true)
{
for(AdcPin = AdcChannel0; AdcPin < NUM_ANALOG_PINS; AdcPin++)
{
Adc_SampleBuffer[i][Adc_SampleIndex] = *AD1BufPtr++;
}
Adc_SampleIndex++;
SampleComplete = true;
}
return SampleComplete;
}
新版本中,Adc_Sample函数可能实现如下所示:
bool Adc_Sample(void)
{
Adc_StartConversion();
return true;
}
非阻塞驱动程序有各种各样的检查和对缓冲区的访问等。对于基于中断的驱动程序,所要做的就是启动基于外围设备的ADC通道转换,这是在初始化期间配置的。因此,例如,如果要对通道0、1和3进行采样,这些通道将是在初始化过程中启用的通道。这个驱动程序是一次采样所有指定的通道,而不是只采样一个或两个。正如所提到的,有很多方法可以做到这一点,并帮助澄清概念,正在使用最简单的解决方案。
此时,如果调用Adc_StartConversion,希望Adc外围设备对通道进行采样,但是当中断触发时,此时不会发生任何事情。需要填充ADC中断处理程序,但是在驱动程序中这样做是有问题的。相反,如果可以的话,希望尝试抽象中断处理程序代码。
中断的抽象化
开发人员在编写驱动程序时经常遇到的一个问题是,当开发一个中断驱动的解决方案时,常常将中断与应用程序代码紧密耦合。最佳情况下,中断将驻留在驱动程序层中的驱动程序代码中,而不是位于体系结构中最高层的应用程序代码中。将中断与应用程序代码紧密耦合会使移植代码变得困难,甚至在某些情况下甚至会对其进行缩放。
开发人员可以使用一个解决方案,将中断保留在驱动程序层中,并仍然为应用程序自定义,这就是使用回调。回调函数是对可执行代码的引用,该代码作为参数传递给其代码,后者允许较低级别的软件层调用在高级层中定义的函数[1]。回调函数最简单的就是作为参数传递给另一个函数的函数指针。在大多数情况下,回调将包含三个部分:
回调函数
回调注册
回调执行
在典型的回调实现中,这三个部分是如何协同工作的,如下图所示:

Figure: Typical callback architecture.
ADC驱动程序HAL包含以下功能:
void Adc_CallbackRegister(AdcCallback_t const Function, void (*CallbackFunction)(void));
如果仔细看一下,这个函数被设计成从应用程序代码向ADC驱动程序注册一个回调函数。第一个参数指定回调将分配给哪个中断,而第二个参数通过向函数传递函数指针来指定要调用的函数。
此时的低级驱动程序会将函数指针分配给指定的中断。这是非常灵活的,因为开发人员可以轻松地更新和更改中断执行的函数,而不必返回、修改和重新编译adc驱动程序。这有助于将应用程序代码从驱动程序代码中分离出来,从而创建一个可伸缩和灵活的解决方案。
有了这些知识,可以实现ADC中断处理程序,如下所示:
void ADC_IRQHandler(void)
{
(*ADC_Interrupt1)();
}
中断只不过是取消对通过Adc_CallbackRegister()函数分配的指针的引用。
编写中断处理程序
对于使用这种方法的开发人员来说,中断处理程序将被写在应用程序层中,并且可以有喜欢的几乎任何函数名。把命名为Adc_InterruptCallback,该回调的实现可能因应用程序而异。例如,在一个应用程序中,回调可能如下所示:
void Adc_CallbackRegister(void)
{
tx_semaphore_put(&Adc1Semaphore);
}
在本例中,回调只是简单地放置一个信号量来通知任务ADC数据可用。另一个示例可能如下所示:
void Adc_CallbackRegister(void)
{
AdcPin = AdcChannel0;
// Loop through and store the buffer data
for(AdcPin = AdcChannel0; AdcPin < NUM_ANALOG_PINS; AdcPin++)
{
Adc_SampleBuffer[i][Adc_SampleIndex] = *AD1BufPtr++;
}
Adc_SampleIndex++;
if(Adc_SampleIndex == ADC_SAMPLE_SIZE)
{
Adc_SampleIndex = 0;
}
}
如所见,由开发人员决定如何在中断处理程序中处理模拟数据,并且根据应用程序及其需要,会有很大的不同。
需要注意的是,对于这些真正是中断处理程序的回调函数,遵循中断处理程序的最佳实践是很重要的。这意味着最小化代码,并使其尽可能快地减少对系统其余性能的影响。
结论
正如在本文中看到的,使用中断驱动驱动程序设计模式可以显著提高驱动程序的效率。使用回调可以将中断实现保留在应用程序代码中,并通过驱动程序的回调机制分配给中断。这使得解决方案和代码具有高度可重用性、灵活性和可伸缩性。
现代传感器的接口:中断驱动的ADC驱动程序的更多相关文章
- 与现代传感器的接口:轮询ADC驱动程序
与现代传感器的接口:轮询ADC驱动程序 Interfacing with modern sensors: Polled ADC drivers 我们研究了在现代嵌入式应用程序中,开发人员应该如何创建一 ...
- JZ2440 裸机驱动 第14章 ADC和触摸屏接口
本章目标: 了解S3C2410/S3C2440和触摸屏的结构: 了解电阻触摸屏的工作原理和等效电路图: 了解S3C2410/S3C2440触摸屏控制器的多种工作模式: ...
- Linux驱动程序接口
§1. Linux驱动程序接口 系统调用是操作系统内核与应用程序之间的接口,设备驱动程序则是操作系统内核与机器硬件的接口.几乎所有的系统操作最终映射到物理设备,除了CPU.内存和少数其它设备,所有的设 ...
- 关于esp32的ADC采集
对于ADC采集 程序源码如下: /* ADC1 Example This example code is in the Public Domain (or CC0 licensed, at your ...
- 玩转X-CTR100 l STM32F4 l ADC 模拟数字转换
我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器 AD转换接 ...
- 第44章 MPU6050传感器—姿态检测—零死角玩转STM32-F429系列
第44章 MPU6050传感器—姿态检测 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.co ...
- jdbc java数据库连接 2)jdbc接口核心的API
JDBC接口核心的API java.sql.* 和 javax.sql.*(java2.0以后更新的扩展) |- Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接 ...
- sja1000芯片can驱动程序
应用层使用socketCan的方法:http://pan.baidu.com/s/1ntsvbb7#path=%252Floongson1%252Ftools%252Fcan 功能:对can驱动程序的 ...
- 基于WDF的PCI/PCIe接口卡Windows驱动程序(4)- 驱动程序代码(源文件)
原文出处:http://www.cnblogs.com/jacklu/p/4687325.html 本篇文章将对PCIe驱动程序的源文件代码作详细解释与说明.整个WDF驱动程序工程共包含4个头文件(已 ...
随机推荐
- The 2014 ACM-ICPC Asia Mudanjiang Regional First Round J
题意: 是个模拟题,就是给你一个字符串,问你他是不是"ABABA" 或者"ABABCAB"的模式,ABC是三个长度不为0且不同的串. 思路: ...
- 【JavaScript】Leetcode每日一题-平方数之和
[JavaScript]Leetcode每日一题-平方数之和 [题目描述] 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c . 示例1: 输入:c = 5 ...
- 【python】Leetcode每日一题-笨阶乘
[python]Leetcode每日一题-笨阶乘 [题目描述] 通常,正整数 n 的阶乘是所有小于或等于 n 的正整数的乘积.例如,factorial(10) = 10 * 9 * 8 * 7 * 6 ...
- HellowWorld详解
1.随便新建一个文件夹,存放代码 2.在文件夹中新建一个Java文件 新建一个.txt文本文档-->将扩展名.txt修改为.java 注:如果创建的文本文档没有显示扩展名,则有如下方法: 方法一 ...
- git修改远端仓库地址
git remote set-url origin 远端地址
- nginx 配置后页面访问是报500错
该问题是html文件权限问题. 用jenkins 并远程服务器上传到另一台服务器的html ,在配置好nginx 的location root 绝对位置后还是报错500 手工用root上传时访问正常 ...
- 前端Node的实用方法
Node 一.什么是Node Node是以基于Chrome V8引擎的JavaScript运行环境,使用了一个事件驱动.非阻塞式I/O模型(I/O是 input/output的缩写,即输入输出端口,在 ...
- 理解RESTful架构——Restful API设计指南
理解RESTful架构 Restful API设计指南 理解RESTful架构 越来越多的人开始意识到,网站即软件,而且是一种新型的软件. 这种"互联网软件"采用客户端/服务器模式 ...
- Vim安装记录
Vim安装记录 参考链接 安装命令 1. 安装依赖库 2. 下载最新vim源码 3. 删除旧版vim 4. 配置configure.编译.安装 5. 设置vim为默认编辑器 6. 必要的配置 Vim安 ...
- Linux如何设置用户登录超时(闲置时间)vi /etc/profile ... export TMOUT=900
Linux如何设置用户登录超时(闲置时间) 转载莫负寒夏ai 最后发布于2019-08-08 15:04:22 阅读数 1897 收藏 展开 1. 针对所有用户 # vi /etc/profile ...