摘 要:本文总结了五种基于嵌入式实时操作系统(RTOS)的信号采样任务的软件设计方法,讨论了每种方法有其特定的应用场合,并为采样任务的设计提供了基本的设计思路,也提供较为结构化的软件设计流程图。
关键词:信号采样;采样任务;实时操作系统(RTOS);节拍函数;中断;快速中断
对外部信号进行采样是嵌入式系统获取外部信息的主要手段,采样对象可分为模拟信号和数字信号两大类。由于数字信号采样比模拟信号采样相对简单,所以这里只讨论对模拟信号的采样。
如果采样信号是动态的持续信号,则系统可按一个预定的频率对其进行连续采样,只要采样频率高于信号高频上限频率的两倍,就可以将该模拟信号包含的信息完全采集到(奈奎斯特采样定律)。
系统以固定频率对信号进行采样时,采样的主动权在系统,称为主动采样。由于实时操作系统的介入,主动采样的实现方式与采样频率(采样周期)有很大的关系,就此分成四种情况分别进行讨论。
当采样对象是一个随即信号时,只有在采样对象出现时刻进行采样才有意义,系统只能被动地等待采样对象的出现,这种采样方式称为被动采样。
1. 使用延时函数控制采样周期
当采样对象是一个低频信号时,采样频率就可以设置得比较低,即采样周期比系统节拍周期长得多,我们可以将采样周期设置为系统节拍周期(RTOS time tick)的整数倍,就可以用系统提供的延时函数来控制采样周期。这时,采样功能就可以由一个独立的采样任务来完成,而不需要中断服务(ISR)配合。
2. 使用定时中断(Timer ISR)控制采样周期
但采样周期与系统节拍在同一个数量级时,如果仍然沿用延时函数来控制采样周期,其采样周期的时间抖动将比较明显(相邻两次采样的时间间隔误差不能忽略),从而严重影响采样结果的质量。这时,我们可以另外使用一个定时器,由定时中断产生稳定的采样周期。
这时,采样功能由一个定时中断服务程序和一个关联任务共同完成。定时中断服务程序按稳定的周期对信号采样,然后将采样结果保存到共享数组(或内存数据块)中,也可以通过通信手段发送给关联任务,有关联任务进行后续处理。下面就是采用定时中断的程序流程图。
3. 使用节拍钩子函数(Hook)进行采样
系统节拍周期是操作系统时间管理的最小单位,节拍周期越短,时间管理就越精细,但操作系统占用CPU资源就越多,通常系统节拍周期在10~100 ms为宜。
当某种功能的运行周期与系统节拍周期同时,使用系统节拍函数的钩子函数来完成此功能是非常有利的。由于系统节拍函数是安排在定时中断的ISR中,所以周期是非常稳定的。而系统节拍钩子函数安排在系统节拍函数的最前面,这样两次钩子函数的执行间隔就是两次系统节拍函数的执行间隔,它们的稳定性相同。如果用延时为一个时钟节拍的独立任务来完成相同功能,那么周期的稳定性就较差(相邻两次执行的时间间隔受到任务调度情况变化的影响)。
系统节拍钩子函数是系统节拍函数的一部分,具有ISR的性质,应当尽可能简洁,不允许调用任何可能使自己挂起来的系统函数。
系统节拍钩子函数的一个用途是进行数据采集(采样周期为系统节拍周期),这时,采样功能由系统节拍函数的钩子函数和一个关联任务共同完成。系统节拍函数的钩子函数按稳定的节拍对信号进行采样,然后将采样数据通过通信手段发送给关联任务。
要使用系统节拍函数的钩子函数,必须将系统配置常量OS_CPU_HOOKS_EN设置为1,系统节拍函数调用的钩子函数就可以被编译到目标代码中。为了避免函数重定义,应该将os_cpu_c.c文件中的函数“void OSTimerTickHook(void)”注释掉(或删掉)。
使用系统节拍函数的钩子函数和使用单独的定时器中断的最大区别是控制方式不同,定时器中断的控制是通过使能/禁止中断源来实现的,而系统节拍不能禁止,其钩子函数也不能单独禁止。
下面是使用系统节拍钩子函数进行采样的程序流程图。在其中,是用一个全局变量来控制钩子函数是否执行功能代码。
4. 使用快速定时中断(Timer FIQ)进行采样
在前面三种情况中,每次对信号进行采样后,关联任务都可以对采集结果及时进行处理。随时采样对象的上限频率提高,采用周期必然缩短,以至于系统再也不能对采样结果进行及时处理。解决这个问题的硬件措施是使用专用芯片或提高CPU档次;解决这个问题的软件措施是离线处理,即先进行连续高速采样,采样结束后再集中处理。 就是使用快速中断进行高速采样的示例。
5. 被动采样
这种由外部信号启动采样过程的方式称为被动采样。在被动采样中,启动采样的时刻是随机的,故没有采样周期的概念。
下面是一个模拟被动采样程序流程图。在实验中,用按键代表外部信号,操作者可以随机进行按键操作,由按键操作启动一次采样,再通过消息队列把采样结果发送给显示任务,显示任务进行数据处理后动态显示当前的采样结果。