13.FreeRTOS_定时器

定时器概述

定时器运行过程

定时器就像一个闹钟,它有超时时间、函数、是否为周期性这三个部分。

  • 超时时间:什么时候到时间,就像闹钟响起
  • 函数:闹钟响起,要干什么
  • 是否为周期性:这个闹钟只响一次(单次触发)还是每天都响(周期性触发) 

定时器的简化运行过程如下图:

  • (t1)使用定时器,需要先创建一个定时器,创建时会规定以上的三个部分,但这时定时器并不会开始计时。
  • (t2)之后需要开启定时器,并基于该时刻进行计时。
  • (t2->t3过程)FreeRTOS有一个tick中断,每次进入中断,都会在中断中判断是否有定时器超时,如果超时就进行定时器的触发。
  • (t3)当定时器触发之后,会唤醒一个任务(守护任务)来去执行创建定时器时传入的函数。至此一次定时完成,如果设置为了周期性触发,之后就会重复上述过程,如果设置为单次触发,之后将不会再触发。

定时器的状态转换

定时器只有两种状态:Dormant(休眠态)、Running(运行态),下面是定时器的状态转换过程

  • 当创建定时器时,定时器进入的是休眠态,这时定时器不进行计时。
  • 当开启定时器、复位定时器、重置定时器周期时,定时器从休眠态转换到了运行态,这时定时器开始计时。
  • 当计时完成之后,如果是单次触发,定时器就会进入休眠态,不再计时;如果是周期性触发,定时器保持运行态,继续计时、触发。
  • 除此之外,在定时器运行态时,也可以调用关闭定时器函数,来让定时器从运行态转为休眠态

定时器相关函数的实质

在上述的状态转换过程中,调用了很多的定时器相关的函数。这些函数实质是将一些命令发送给定时器命令队列,之后守护任务不再阻塞并读取定时器命令队列,根据这些命令执行相应的操作。具体的交互模型如下:

相关配置

在使用定时器相关函数之前,需要打开红开关,具体操作如下:

相关函数

创建定时器

函数声明如下:

TimerHandle_t xTimerCreate( const char * const pcTimerName, 
                            const TickType_t xTimerPeriodInTicks,
                            const BaseType_t xAutoReload,
                            void * const pvTimerID,
                            TimerCallbackFunction_t pxCallbackFunction )

返回值:定时器句柄

pcTimerName:名字

xTimerPeriodInTicks:周期

xAutoReload:单次触发(pdFALSE)、周期性触发(pdTRUE)

pvTimerID:可写NULL

pxCallbackFunction:回调函数 

启动定时器

/* 这是一个宏,开启定时器 */
xTimerStart( xTimer, xTicksToWait )

/* 宏定义 */
#define xTimerStart( xTimer, xTicksToWait )               \
        xTimerGenericCommand( ( xTimer ),                 \
                              tmrCOMMAND_START,           \
                              ( xTaskGetTickCount() ),    \ 
                              NULL,                       \
                              ( xTicksToWait ) )          \

/* 实际调用函数 */
BaseType_t xTimerGenericCommand( TimerHandle_t xTimer,
                                 const BaseType_t xCommandID,
                                 const TickType_t xOptionalValue,
                                 BaseType_t * const pxHigherPriorityTaskWoken,
                                 const TickType_t xTicksToWait )

xTimer:定时器句柄

xTicksToWait:超时,有超时是因为函数实质是发送指令给队列

验证实验

实验内容为:开启定时器,每0.1s翻转一次变量值,用逻辑分析仪来查看变量状态。

具体代码实现如下:

/* 定时器回调函数 */
/* 这里面不用在while(1)中跑 */
char i;
void TimFun( TimerHandle_t xTimer ){
    i = !i;
}

int main( void )
{
	TimerHandle_t xTimeHandle_Test;/* 定时器句柄 */
	
	prvSetupHardware();
	SerialPortInit();
	printf("UART TEST\r\n");
	
	/* 创建定时器,周期为100*1ms = 0.1s */
	xTimeHandle_Test = xTimerCreate("time",100,pdTRUE,NULL,TimFun);
	/* 开启定时器 */
	xTimerStart(xTimeHandle_Test,0);

	xTaskCreate(TaskAFunction,"TaskA",100,(void*)NULL,2,NULL);/* taskA空跑while(1) */
	
	vTaskStartScheduler();
	
	//xTimerStart
	return 0;
}

运行结果如下:

可以看到,变量i每隔0.1s进行了一次翻转,由于taskA空跑while(1),说明守护任务与TaskA是相互独立的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值