μC/OS-II实时内核下的A/D驱动程序设计
扫描二维码
随时随地手机看文章
关键词:μC/OS-II A/D 驱动程序 C8051F015
A/D转换是单片机数据采集系统的重要组成部分,实时内核下A/D驱动程序的实现过程主取决于A/D转换器的转换时间。本文首先比较和分析μC/OS-II下A/D采样数据的三种方法;其次介绍C8051F015单片机A/D模数转换器配置及特点;最后,在μC/OS-II内核移植到8位单片机C8051F015的基础上,介绍编写A/D驱动程序的一般思想和方法。
1 μC/OS-II实时内核下的A/D读方法
实时内核下,驱动程序采用什么方法读取A/D采样数据是首先考虑的问题。许多因素将影响读取A/D,如A/D的转换时间、模拟值的转换频率、输入通道数等,但最主要的取决于A/D的转换时间。典型的A/D转换典型的A/D转换电路由模拟多路复用器(MUX)、放大器和模数转换器(ADC)三部分组成。下面描述读取A/D的三种方法。
图1所示的是第1种读取方法。假设A/D转换器的转换时间较慢(5ms以上)。应用程序调用图1所示的驱动程序,并传递要读取的通道。驱动程序通过MUX选择要读取的模拟通道(①)开始读。有,延时几μs以便使信号通过MUX传递,并之稳定下来。接着,ADC被触发开始转换(②)。然后驱动程序延时一段时间以完成转换(③_。延时时间必须比ADC转换时间长。最后驱动程序读取ADC转换结果(④)。并将转换结果返回到应用程序(⑤)。
图2所示的是第2种读取方法。当模拟转换完成后,ADC产生的个中断信号。若ADC转换完成,ISR给信号量发一个信号(⑤),通知驱动程序,ADC已经完成转换。如果ADC在规定的时限内没有完成转换。信号量超过(③),则驱动程序不再等待下去。驱动程序和中断服务子程序(ISR)的伪代码如下:
ADRd(ChannelNumber)
{
选择要读取的模拟输入通道;
等待AMUX输出稳定;
启动ADC转换;
等待来自ADC转换结束中断产生的信号量;
if(超时){
*eer=信号错误;
return;
}else{
读取ADC转换结果并将其返回到应用程序;
}
}
ADCoversion Complete ISR {
保存全部CPU寄存器; /*将CPU的PSW、ACC、B、DPL、DPH及Rn入栈*/
通知内核进入ISR(调用OSIntEnter()或OSIntNesting直接加1);
发送ADC转换完成信号; /*利用μ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){
选择要读取的模拟输入通道;
等待AMUX输出稳定;
启动ADC转换;
启动超时定时器;
while(ADC Busy & Counter 0);/*循环检测*/
if(Counter==0){
*err=信号错误;
return;
}else{
读取ADC转换结果并将其返回到应用程序;
}
}
A、D转换速度快,这种驱动程序的实现是最好的。
2 C8051F015单片机的A/D转换器
2.1 C8051C015单片机
C8051C015的美国Cygnal公司新推出的高速SOC型C8051Fxxx系列单片机。它的内核CIP-51与MCS-51的指令集完全兼容,CIP-51的系统时钟频率在0~25MHz。C8051Fxxx系列单片机采用流水线结构,与标准的8051相比,指令执行速度有很大的提高。CIP-51内核的指令执行时间是以系统时钟为单位,70%的指令执行时间为1个或2个系统时钟周期。C8051F015具有32KB的内存、2304B的RAM(片内256B、片外2048B)。CIP-51内核具有标准8052的所有外设部件,片上还集成有9通道10位A/D转换接口电路、SMBus/I2C、SPI串行接口。
2.2 C8051F015的A/D转换电路
C8051F015的A/D转换电路包括1个9通道可配置模拟多路开关AMUX(8路用于外部模拟输入、1路用于芯片环境温度的测量)、1个可编程增益放大器PGA和1个100ksps 10位分辨率的逐次逼近型ADC。A/D中还集成了跟踪保持电路和可编程窗口检测器。
ADC有4种启动方式:软件命令、定时器2溢出、定时器3溢出及外部信号输入。寄存器ADC0CN是配置启动和跟踪方式的控制寄存器。每次转换结束时,ADC0CH的ADBUSY(忙标志)的下降沿触发中断,也可用软件查询这个状态位。
2.3 ADC转换速度
C8051Fxxx系列单片机中ADC的速率都是可编程设置的。表1给出了所需最小分频系数与SYSCLK(系统时钟)的关系(ADC0CF为ADC配置寄存器)。
表1 ADC时钟分频系数与SYSCLK频率的关系
SYSCLK频率/MHz | ADC时钟分频系数 | ADC0CF的ADCSC2~1 |
时钟频率<2.5 | 1 | 000 |
2.5~5 | 2 | 001 |
5~10 | 4 | 010 |
10~20 | 8(复位值) | 011 |
时钟频率>20 | 16 | 1xx |
在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/OS-II调用ISR的时间与调用等待信号时间之和大于A/D的转换时间,所以CPU用于ISR和循环检测的开销大。
图3所示的方法显然适合于C8051F015单片机,其优点是:可以获得快速的转换时间;不需要增加一个复杂的ISR;转换时信号改变时间更短;CPU的开销小;循环检测程序可被中断,为中断信号服务。
图4 A/D驱动程序模块流程图
3 A/D驱动程序的编写
外设驱动程序是实时内核和硬件之间的接口,是连接底层硬件和内核的纽带。编写驱动程序模块应满足以下主要功能:①对设备初始化;②把数据从内核传送到硬件从硬件读取数据;③读取应用程序传送给设备的数据和回送应用程序请求的数据;④监测和处理设备出现的异常。
A/D转换电路作为一个模拟输入模块,μC/OS-II内核应把它作为一个独立的任务(以下称为ADTask())来调用。A/D驱动程序模块流程如图4所示。ADInit()初始化所有的模拟输入通道、硬件ADC以及应用程序调用A/D模块的参量,并且ADInit()创建任务ADTask()。ADTb1[]是一个模拟输入通道信息、ADC硬件状态等参数配置以及转换结果存储表。ADUpdate()负责读取所有模拟输入通道,访问ADRd()并传递给它一个通道数。ADRd()负责通过多路复用器选择合适的模拟输入,启动并等待ADC转换,以及返回ADC转换结果到ADUpdate()。
在μC/OS-II这时内核下各原型函数、数据结构和常量的定义如下:
INT16S ADRd(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 ADTbl[AD_MaxNummber]:AD类型的数组(AD是定义的数据结构)。
4 结论
对于A/D转换器接口电路驱动程序的编写归纳出以下几点:
①在决定采用具体的驱动方案之前,分析接口电路的特点,尤其是了解A/D的转换速度;
②对于转换速度快的A/D转换器,可能出现CPU的处理速度与A/D转换速度不匹配,一般的A/D中不带有FIFO缓冲区,须有内存中开辟缓冲区;
③在应用程序读取设备之前,一定要初始化硬件(调用初始化函数),合理定义硬件的信息和状态变量;
④不同的输入通道采集到不同类型数据,环境、转换精度都会影响到转换结果,要对各个模拟输入通道进行校准和补偿(通常在应用程序中编写通道补偿函数)。