浅析μC/OS-Ⅱ设备驱动的设计与实现
4.1 μC/OS-II实时内核下的A/D读取方法
实时内核下,驱动程序采用什么方法读取A/D采样数据是首先考虑的问题。许多因素将影响读取A/D,如A/D的转换时间、模拟值的转换频率、输入通道数等,但最主要的是取决于A/D的转换时间。典型的A/D转换电路由模拟多路复用器(M U X)、放大器和模数转换器(ADC)三部分组成。下面描述读取A/D的三种方法。
图1所示的是第1种读取方法。假设A/D 转换器的转换时间较慢(5ms以上),应用程序调用图1所示的驱动程序,并传递要读取的通道。驱动程序通过M U X选择要读取的模拟通道(①)开始读。转换前,延时几μs以便使信号通过M U X传递,并使之稳定下来。接着,ADC被触发开始转换(②)。然后驱动程序延时一段时间以完成转换(③)。延时时间必须比ADC转换时间长。最后驱动程序读取ADC转换结果(④),并将转换结果返回到应用程序(⑤)。
图2所示的是第2种读取方法。当模拟转换完成后,ADC产生的一个中断信号。若ADC转换完成,ISR给信号量发一个信号(⑤),通知驱动程序,ADC已经完成转换。如果ADC在规定的时限内没有完成转换,信号量超时(③),则驱动程序不再等待下去。驱动程序和中断服务子程序(ISR)的伪代码如下:
ADRd(ChannelNumber)
{
选择要读取的模拟输入通道;
等待A M U X 输出稳定;
启动A D C 转换;
等待来自ADC 转换结束中断产生的信号量;
if (超时){
*err=信号错误;
return;
} else {
读取ADC转换结果并将其返回到应用程序 ;
}
}
ADCoversion Complete ISR{
保存全部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/D转换时间小于处理中断时间与等待信号所需的时间之和,则可以用第三种方法。如图3所示,前两步(①②同以上两种方法)结束后,驱动程序接着在一个软件循环中等待(③)ADC直到完成转换。在循环等待时,驱动程序检测ADC的状态(BUSY)信号。如果等待时间超过设定的定时值(软件定时),则结束等待循环(循环等待超时)。如果在循环等待中,检测到ADC发出转换结束的信号(BUSY)时,驱动程序读取ADC转换结果(④)并将结果返回到应用程序(⑤)。
驱动程序伪代码如下:
ADRd(ChannelNumber){
选择要读取的模拟输入通道;
等待A M U X 输出稳定;
启动A 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一次转换完成要用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 所示的方法显然适合于C8051F015 单片机。其优点是:可以获得快速的转换时间;不需要增加一个复杂的ISR;转换时信号改变时间更短;C P U 的开销小;循环检测程序可被中断,为中断信号服务。
4.3 A/D驱动程序的编写
外设驱动程序是实时内核和硬件之间的接口,是连接底层硬件和内核的纽带。编写驱动程序模块应满足以下主要功能:① 对设备初始化;② 把数据从内核传送到硬件和从硬件读取数据;③ 读取应用程序传送给设备的数据和回送应用程序请求的数据;④ 监测和处理设备出现的异常。
A/D转换电路作为一个模拟输入模块,μC/OS-II内核应把它作为一个独立的任务(以下称为ADTask())来调用。A/D驱动程序模块流程如图4所示。ADInit()初始化所有的模拟输入通道、硬件ADC以及应用程序调用A/D模块的参量,并且ADInit()创建任务ADTask()。ADTb1 [ ]是一个模拟输入
- 3DES算法的FPGA高速实现(06-21)
- 基于DSP的Max-Log-MAP算法实现与优化(05-27)
- DSP中DMA操作的无阻塞请求实现(06-18)
- 二维DCT编码的DSP实现与优化(09-08)
- 基于DSP处理器上并行实现ATR算法(01-29)
- 基于DSP的H.324终端设计(05-27)