您的位置:首页 > 其它

CMSIS-RTOS 时间管理之虚拟定时器Virtual Timers

2016-11-20 14:26 316 查看

虚拟定时器Virtual Timers

CMSIS-RTOS API里有几个向下计数的虚拟定时器,它们实现计数完成时用户的回调功能。每个定时器都可以配置成单次计数或重复计数模式,它们可以在定义定时器结构体的时候被创建:

osTimerDef(timer0, led_function);


在上面的代码中给定时器定义了一个名字timer0,并同时定义了回调函数led_function,紧接着必须对这个定时器进行实例化:

osTimerId timer0_handle = osTimerCreate(timer(timer0), osTimerPeriodic,(void*)0);


上面的代码创建了这个定时器,并把它定义成周期性定时器(还可以定义成单次定时器–osTimerOnce),最后一个参数0是传递给回调函数的实参,当定时器定时结束时会用的用到。

osTimerStart(timer0_handle, 0x100);


定时器可以在线程的任意位置启动,从上面的代码中可以看到,定时器启动函数使用的是timer0的句柄,并定义了0x100ms的周期定时。

练习:虚拟定时器

在这个练习里,我们将配置一些虚拟定时器以不同的频率来触发回调函数。

打开Pack Installer,并选择“Ex 6 Virtual Timers”,然后把它安装到自定义路径

代码依旧是原来的LED闪烁程序,在代码中添加四个虚拟定时器来触发回调函数。当某个定时器定时完成时,这个回调函数就会执行翻转LED的程序。

定时器在启动代码中定义:

osTimerDef(timer0_handle, callback);
osTimerDef(timer1_handle, callback);
osTimerDef(timer2_handle, callback);
osTimerDef(timer3_handle, callback);


在main函数中初始化:

osTimerId timer0 = osTimerCreate(osTimer(timer0_handle), osTimerPeriodic, (void*)0);
osTimerId timer0 = osTimerCreate(osTimer(timer0_handle), osTimerPeriodic, (void*)1);
osTimerId timer0 = osTimerCreate(osTimer(timer0_handle), osTimerPeriodic, (void*)2);
osTimerId timer0 = osTimerCreate(osTimer(timer0_handle), osTimerPeriodic, (void*)3);


每个定时器都有不同的句柄和ID号,并且给回调函数传递不同的参数:

void callback(void const *param){
switch((uint32_t)param) {
case 0: GPIOB->ODR ^=0x02; break;
case 1: GPIOB->ODR ^=0x04; break;
case 2: GPIOB->ODR ^=0x08; break;
case 3: GPIOB->ODR ^= 0x10;break;
}
}


当触发发生时,回调函数就会通过传递过来的参数来控制相应的LED翻转。

另外,在程序中配置虚拟定时器前,需要在RTX配置文件中使能定时器线程。

打开RTX_Conf_CM.c 文件,并切换到配置向导标签页



展开System Configuration,勾选User Timers。

编译工程,并打开debugger仿真。

全速运行!打开GPIOB仿真窗口。



从上图可以看到这几个管脚的设置是按照周期变化的。

打开System and Thread Viewer window



需要注意的是,osDelay()产生相对延时,而虚拟定时器产生绝对延时,利用这一点,你可以加入固定时间间隔的代码。

亚毫秒延时

前面介绍的各种CMSIS-RTOS时间管理函数时间精度都是以ms为单位的,如果想产生微秒级别的延时,可以使用系统节拍计数SysTick。这种延时并不产生任务的调度,它只是暂停执行一段时间。

首先,我们需要获取SysTick计数:

int32_t tick, delayPeriod;
tick = osKernelSysTick();//获取内核系统节拍起始值


然后,获取系统节拍微秒值的标定值:

delayPeriod = osKernelTickMicroSec(100);


最后,根据需要创建时间延时:

do{
//100us延时
}wile((osKernelSysTick())-tick < delayPeriod);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: