浅析嵌入式μC设备驱动的设计与实现_第1页
浅析嵌入式μC设备驱动的设计与实现_第2页
浅析嵌入式μC设备驱动的设计与实现_第3页
浅析嵌入式μC设备驱动的设计与实现_第4页
浅析嵌入式μC设备驱动的设计与实现_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、浅析嵌入式 C/OS- 设备驱动的设计与实现设备驱动程序是任何操作系统的必不可少的、 最保密的一个组成部分, 它们实现了计算 机系统所有附属设备的一个标准接口, 它包含与硬件直接相关的设备驱动。 从广义上说,“驱 动程序” 是指一些函数的集合, 这些函数都能对硬件设备进行操作。 本文简单分析了 C/OS- 下设备驱动的设计与实现。设备驱动程序是任何操作系统的必不可少的、 最保密的一个组成部分, 它们实现了计算 机系统所有附属设备的一个标准接口, 它包含与硬件直接相关的设备驱动。 从广义上说,“驱 动程序” 是指一些函数的集合, 这些函数都能对硬件设备进行操作。 驱动程序的概念在没有 固定的操作

2、系统的时候, 是一个比较模糊的定义。 简单地理解就是提供了一个软件到硬件 (也 可以是虚拟硬件)操作的函数。通常主要应该包括:设备初始化、设备的读写(输入输出) 、 设备的控制等信息。在 C/OS-下没有统一的设备驱动接口不像windows 或者 linux下通过设备文件的定义模式, 所以,把一些对硬件操作是通过一般的函数来完成的, 叫成“驱 动程序”也不为过。1 简介 外设驱动程序是实时内核和硬件之间的接口, 是连接底层硬件和内核的纽带。编写驱动程序模块应满足以下主要功能: 对设备初始化; 把数据从内核传送到硬件和从硬件读取数据; 读取应用程序传送给设备的数据和回送应用程序请求的数据; 监测

3、和处理设备出现的异常。 由于在 C/OS-下没有统一的设备驱动接口, 在该操 作系统中设备驱动的设计和实现主要是通过一些对硬件操作的函数来完成。2 C/OS- 操作系统启动过程中的硬件初始化基于 的应用系统工作时, 首先把初始化; 接着进行操作系统初 始化,主要完成任务控制块()初始化、优先级表初始化、空任务的创建等; 然后开始创建新任务, 并可在新创建的任务中再创建其他的新任务; 最后调用 ()函数启动多任务调度。当C/OS-实际移植到具体的硬件平台中时,系统初始化时还要进行硬件的初始化。 主函数是系统启动首先执行的一个函数,在启动C/OS 之前,要屏蔽所有中断,并对全局变量初始化,防止运行

4、出错。硬件初始化主要包括中断初始化,串口、键盘、显示等设备初始化。 C/OS的初始化通过调用 OSInit() 函数,为 OS 分配任务队列、优先级状态 表和准备状态表,初始化全局变量,并且创建一个空循环任务。接下来,在启动 C/OS前调用 OSTaskCreate()创建所有用户任务,并置准备态,创建任务时,要指定每个任务的 优先级、堆栈大小和位置、任务函数入口。调用OS2Start()启动 C/OS。从就绪队列中找到优先级最高的任务,作为当前任务执行。流程如图所示。3 C/OS- 操作系统对硬件的操作和控制3.1 函数控制硬件前面已经提到过,不像其他的操作系统,在 C/OS中没有统一的设备

5、驱动接口,因此对硬件的操作和控制可以通过函数来完成。 在启动过程中完成硬件初始化后, 系统创建 一个空循环任务,然后就可以调用OSTaskCreate()创建用户任务,在任务用户任务中选择要控制的硬件,选择最佳的控制方法,调用用户自己编写的函数来完成。3.2 BSPBSP(板级支持包)是介于底层硬件和操作系统之间的软件层次,它完成系统上电后最 初的硬件和软件初始化,并对底层硬件进行封装,使得操作系统不再面对具体的操作。为 C/OS-编写一个简单的 BSP。它首先设置 CPU 内部寄存器和系统堆栈,并初始化堆 栈指针,建立程序的运行和调用环境;然后可以方便地使用 C 语言设置硬件的配置环境, 并

6、编制相应的操作函数,为操作系统调用提供统一的接口;在 CPU、板级和程序自身初始 化完成后,就可以把 CPU 的控制权交给操作系统了。4 实际应用举例既然在 C/OS-下没有统一的设备驱动接口,系统对硬件的控制是通过一些对硬件操 作的函数来完成的。下面以在 C/OS- 实时内核下驱动程序读取 A/D 的三种方法,分析在 实际的工程实践中 C/OS- 设备驱动的设计和实现, 以及在设计过程中应注意的一些问题。以一个单片机数据采集系统为例,硬件环境基于 C8051F015 单片机。 A/D 转换是单片机数 据采集系统的重要组成部分,实时内核下 A/D 驱动程序的实现过程主要取决于 A/D 转换器

7、的转换时间。我们首先比较和分析 C/OS- 下 A/D 采样数据的三种方法;其次介绍C8051F015 单片机 A/D 模数转换器的配置及特点;最后,在 C/OS-II 内核移植到 8 位单片 机 C8051F015 的基础上,介绍编写 A/D 驱动程序的一般思路和方法。4.1 C/OS-II 实时内核下的 A/D 读取方法实时内核下,驱动程序采用什么方法读取 A/D 采样数据是首先考虑的问题。许多因素 将影响读取 A/D ,如 A/D 的转换时间、模拟值的转换频率、输入通道数等,但最主要的是 取决于 A/D 的转换时间。典型的 A/D 转换电路由模拟多路复用器( M U X )、放大器和模数

8、 转换器( ADC )三部分组成。下面描述读取 A/D 的三种方法。图 1 所示的是第 1 种读取方法。假设 A/D 转换器的转换时间较慢( 5ms 以上),应用程 序调用图 1 所示的驱动程序,并传递要读取的通道。驱动程序通过M U X 选择要读取的模拟通道()开始读。转换前,延时几 s以便使信号通过 M U X 传递,并使之稳定下来。 接着, ADC 被触发开始转换() 。然后驱动程序延时一段时间以完成转换() 。延时时 间必须比 ADC 转换时间长。最后驱动程序读取 ADC 转换结果() ,并将转换结果返回到 应用程序() 。图 2 所示的是第 2 种读取方法。 当模拟转换完成后, AD

9、C 产生的一个中断信号。 若 ADC 转换完成, ISR 给信号量发一个信号() ,通知驱动程序, ADC 已经完成转换。如果 ADC 在规定的时限内没有完成转换,信号量超时() ,则驱动程序不再等待下去。驱动程序和 中断服务子程序( ISR)的伪代码如下:ADRd ( ChannelNumber ) 选择要读取的模拟输入通道; 等待 A M U X 输出稳定; 启动 A D C 转换; 等待来自 ADC 转换结束中断产生的信号量; if (超时) *err= 信号错误; return; else 读取 ADC 转换结果并将其返回到应用程序 ;ADCoversion Complete ISR

10、保存全部 CPU 寄存器; /* 将 CPU 的 PSW、ACC 、 B、DPL、DPH及 Rn入栈*/ 通知内核进入 ISR(调用 OSIntEnter() 或 OSIntNesting 直接加 1); 发送 A D C 转换完成信号; /* 利用 C/OS-II 内核的OSSemPost()*/ 通知内核退出 ISR( 调用 OSIntExit() ; 恢复所有 CPU 寄存器; /* 将 CPU 的 PSW、ACC 、B、DPL 、DPH 及 Rn 出栈*/执行中断返回指令 (即 RETI) ; 在这种方法里,要求 ISR 执行时间与调用等待信号的时间之和为 A/D 转换时间。如果 A/

11、D 转换时间小于处理中断时间与等待信号所需的时间之和,则可以用第三种方 法。如图 3 所示,前两步(同以上两种方法)结束后,驱动程序接着在一个软件循环中 等待() ADC 直到完成转换。在循环等待时,驱动程序检测ADC 的状态( BUSY )信号。如果等待时间超过设定的定时值(软件定时) ,则结束等待循环(循环等待超时) 。如果在循 环等待中,检测到 ADC 发出转换结束的信号 (BUSY )时,驱动程序读取 ADC 转换结果() 并将结果返回到应用程序() 。驱动程序伪代码如下:ADRd (ChannelNumber ) 选择要读取的模拟输入通道; 等待 A M U X 输出稳定; 启动 A

12、 D C 转换; 启动超时定时器; while ( ADC Busy & Counter?0 ); /* 循环检测 */ if ( Counter=0 ) *err= 信号错误; return ; else 读取 ADC 转换结果并将其返回到应用程序 ;A/D 转换速度快,这种驱动程序的实现是最好的。4.2 C8051F015单片机 A/D 模数转换器再来简单介绍一下 C8051F015 单片机 A/D 模数转换器的配置及特点。在 C8051F015 单片机中, ADC 的转换时钟周期至少在 400ns,转换时钟应不大于 2MHz 。 一般在启动 ADC 之前都要处于跟踪方式, 而ADC 一次

13、转换完成要用 16个系统时钟。 另外, 在转换之前还要加上 3 个系统时钟的跟踪 /保持捕获时间,所以完成一次转换需19 个 ADC转换时钟( 9.5 s)。图 1中的方法简单,转换时间在 ms 级以上,一般用于变化慢的模拟输 入信号,不适用于 C8051F015 。图 2 中的方法,为了减少 C/OS-II 内核调用 ISR 所用时间, ISR 一般都用汇编语言编 写。从程序 1中 ISR 伪代码可以看出,尽管 ISR 用汇编语言编写,代码效率高,但 C/OSII 调用ISR的时间与调用等待信号时间之和大于 A/D的转换时间,所以 C P U用于ISR 和循 环检测的开销大。图 3 所示的方

14、法显然适合于 C8051F015 单片机。其优点是:可以获得快 速的转换时间;不需要增加一个复杂的 ISR;转换时信号改变时间更短; C P U 的开销小; 循环检测程序可被中断,为中断信号服务。4.3 A/D 驱动程序的编写外设驱动程序是实时内核和硬件之间的接口, 是连接底层硬件和内核的纽带。 编写驱动 程序模块应满足以下主要功能: 对设备初始化; 把数据从内核传送到硬件和从硬件读 取数据; 读取应用程序传送给设备的数据和回送应用程序请求的数据; 监测和处理设 备出现的异常。A/D 转换电路作为一个模拟输入模块, C/OS-II 内核应把它作为一个独立的任务(以 下称为 ADTask()来调

15、用。 A/D 驱动程序模块流程如图 4所示。 ADInit ()初始化所有的模拟输入通道、硬件 ADC 以及应用程序调用 A/D 模块的参量,并且 ADInit ()创建任务 ADTask ()。 ADTb1 是一个模拟输入通道信息、 ADC 硬件状态等参数配置以及转换结果 存储表。 ADUpdate ()负责读取所有模拟输入通道,访问ADRd ()并传递给它一个通道数。 ADRd ()负责通过多路复用器选择合适的模拟输入,启动并等待 ADC 转换,以及返 回 ADC 转换结果到 ADUpdate ()。在 C/OS-II 实时内核下各原型函数、数据结构和常量的定义如下。INT16S ADRd

16、 ( INT8U ch );/* 定义如何读取 A/D , A/D 必须通过 AIRd ()来驱动 */ void ADUpdate ( void ) ;/* 一定时间内更新输入通道 */void ADInit (void );/* A/D 模块初始化代码,包括初始化所有内部变量(通过 ADInit ()初始化 ADTb ),初 始化硬件 A/D (通过 ADInitI ()及创建任务 ADTask () */void ADTask ( void data) ;/* 由 ADInit ()创建,负责更新输入通道(调用 ADUpdate () */ void ADInitI ( void ) ;/* 初始化硬件 A/D */AD_TaskPrio :设置任务 ADTask ()的优先级。AD_TaskStkSize :设置分配给任务 ADTask ()的堆栈大小。AD_MaxNummber :AMUX 的输入通道数。AD_TaskDly :设定更新通道的间隔时间。AD ADTb1AD_MaxNummber : AD 类型的数组( AD 是定义的数据结构) 。4.4 总结对于 A/D 转换器接口电路驱动程序的编写归纳出以下几点: 在决定采用具体的驱动方案之前,分析设备接口电路的特点,尤其是了解设备的配 置和特点; 对于处理速度快的设备, 可能出现 CPU 的处理速度与设备处理速度不

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论