FreeRTOS软件定时器

软件定时器允许设置一段时间,当设置的时间达到后就执行指定的功能函数,被软件定时器调用的功能函数叫做定时器的回调函数。软件定时器的回调函数是在定时器服务任务中执行的,所以一定不能在回调函数中调用任何阻塞任务的API函数,比如VTaskDelay。
软件定时器分为两种,单次定时器和周期定时器,单次定时器就执行一次,然后停止运行,不能自动重启,但我们可以手动重新启动,周期定时器就是执行完回调函数以后自动的重新启动,这样回调函数就会周期性的执行。

0x01 定时器相关配置

定时器的配置在FreeRTOSConfig.h中

  1. configUSE_TIMES
    如果要使用软件定时器,configUSE_TIMES要设置为1。

  2. configTIMER_TASK_PRIORITY
    设置软件定时器服务任务的任务优先级

  3. configTIMER_QUEUE_LENGTH
    设置定时器命令队列的队列长度

  4. configTIMER_TASK_STACK_DEPTH
    设置定时器任务的任务堆栈大小,单位为字,对于STM32来说一个字是4字节

0x02 创建定时器

使用软件定时器首先要创建,创建定时器分为动态和静态两种创建方法。

  • xTimerCreate():使用动态方法创建软件定时器
  • xTimerCreateStatic():使用静态方法创建软件定时器
	TimerHandle_t xTimerCreate(	const char * const pcTimerName,
								const TickType_t xTimerPeriodInTicks,
								const UBaseType_t uxAutoReload,
								void * const pvTimerID,
								TimerCallbackFunction_t pxCallbackFunction ) 
  • const char * const pcTimerName:软件定时器名字
  • const TickType_t xTimerPeriodInTicks:软件定时器的定时周期,单位是时钟节拍数,可以借助portTICK_PERIOD_MS将ms单位转换为时钟节拍数,比如定时器的周期为100个时钟节拍的话,那么xTimerPeriodInTicks=100,当定时器周期为500ms的时候,xTimerPeriodInTicks =(500/portTICK_PERIOD_MS)
  • const UBaseType_t uxAutoReload:设置定时器模式,但是定时器还是周期定时器,当uxAutoReload=pdTRUE的时候创建的是周期定时器,uxAutoReload=pdFALSE是单次定时器。
  • void * const pvTimerID:定时器ID号。
  • TimerCallbackFunction_t pxCallbackFunction :定时器回调函数,当定时器周期到了以后就会调用这个函数。
	TimerHandle_t xTimerCreateStatic(	const char * const pcTimerName,
										const TickType_t xTimerPeriodInTicks,
										const UBaseType_t uxAutoReload,
										void * const pvTimerID,
										TimerCallbackFunction_t pxCallbackFunction,
										StaticTimer_t *pxTimerBuffer )
  • const char * const pcTimerName:软件定时器名字
  • const TickType_t xTimerPeriodInTicks:软件定时器的定时周期,单位是时钟节拍数,可以借助portTICK_PERIOD_MS将ms单位转换为时钟节拍数,比如定时器的周期为100个时钟节拍的话,那么xTimerPeriodInTicks=100,当定时器周期为500ms的时候,xTimerPeriodInTicks =(500/portTICK_PERIOD_MS)
  • const UBaseType_t uxAutoReload:设置定时器模式,但是定时器还是周期定时器,当uxAutoReload=pdTRUE的时候创建的是周期定时器,uxAutoReload=pdFALSE是单次定时器。
  • void * const pvTimerID:定时器ID号。
  • TimerCallbackFunction_t pxCallbackFunction :定时器回调函数,当定时器周期到了以后就会调用这个函数。
  • StaticTimer_t *pxTimerBuffer:参数指向一个StaticTimer_t类型的变量,用来保存定时器结构体
0x03 开启软件定时器

如果软件定时器停止运行的话可以使用FreeRTOS提供的两个开启函数来重新启动软件定时器

  • xTimerStart():开启软件定时器,用于任务中
  • xTimerStartFromISR():开启软件定时器,用于中断中
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait )
  • TimerHandle_t xTimer:要开启的软件定时器的句柄
  • TickType_t xTicksToWait :设置阻塞时间
BaseType_t xTimerStartFromISR( 	TimerHandle_t xTimer,
								BaseType_t *pxHigherPriorityTaskWoken );
  • TimerHandle_t xTimer:开启的软件定时器的句柄
  • BaseType_t *pxHigherPriorityTaskWoken :标记退出此函数以后是否进行任务切换,这个变量的值函数会自动设置的,用户不用进行设置,当此值为pdTURE的时候,在退出中断服务函数之前一定要进行一次任务切换。
0x04 复位软件定时器

复位一个软件定时器会重新计算定时周期达到的时间点,这个新的时间点是相对于复位定时器的那个时刻开始的,比如说,我们有个timer1单次定时器,定时周期是5s,从0s到5s,如果没有干预的话,timer1在5s会停止运行,如果我们在3s时刻进行复位,则timer1会从3s开始,中间如果没有干预的话,会到8s停止运行,有复位的话,会从复位时刻继续运行5s。复位相关函数如下:

  • xTimerReset:复位软件定时器,用在任务中
  • xTimerResetFromISR:复位软件定时器,用在中断服务函数中
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait )
  • TimerHandle_t xTimer:要复位的软件定时器句柄
  • TickType_t xTicksToWait:设置阻塞时间
BaseType_t xTimerResetFromISR( 	TimerHandle_t xTimer,
								BaseType_t *pxHigherPriorityTaskWoken );
  • TimerHandle_t xTimer:要复位的软件定时器句柄
  • BaseType_t *pxHigherPriorityTaskWoken:设置退出此函数是否进行任务切换
0x05 停止软件定时器

停止软件定时器相关中断如下:

  • xTimerStop():停止软件定时器,用于任务中
  • xTimerStopFromISR():停止软件定时器,用在中断服务函数中
BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait )
  • TimerHandle_t xTimer:要停止的软件定时器句柄
  • TickType_t xTicksToWait:设置阻塞时间
BaseType_t xTimerStopFromISR( 	TimerHandle_t xTimer,
							BaseType_t *pxHigherPriorityTaskWoken )
  • TimerHandle_t xTimer:要停止的软件定时器句柄
  • BaseType_t *pxHigherPriorityTaskWoken :标志退出此函数是否要进行任务切换
实验

设计两个任务:

  1. start_task:用来创建timercontrol_task和两个软件定时器,这两个定时器分别为周期定时器和单次定时器,定时周期一个为1s,另一个为2s
  2. timercontrol_task:控制两个软件定时器的开启和停止

main函数中创建start_task任务

int main(void)
{
    HAL_Init();                     //初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   //设置时钟,180Mhz
    delay_init(180);                //初始化延时函数
    uart_init(115200);              //初始化串口
    LED_Init();                     //初始化LED 
    KEY_Init();                     //初始化按键
    BEEP_Init();                 	//初始化蜂鸣器
    SDRAM_Init();                   //初始化SDRAM
    LCD_Init();                     //初始化LCD
    my_mem_init(SRAMIN);            //初始化内部内存池
	
    POINT_COLOR = RED;
	LCD_ShowString(30,10,200,16,16,"Apollo STM32F4/F7");	
	LCD_ShowString(30,30,200,16,16,"FreeRTOS Examp 15-1");
	LCD_ShowString(30,50,200,16,16,"KEY_UP:Start Tmr1");
	LCD_ShowString(30,70,200,16,16,"KEY0:Start Tmr2");
	LCD_ShowString(30,90,200,16,16,"KEY1:Stop Tmr1 and Tmr2");

	LCD_DrawLine(0,108,239,108);		//画线
	LCD_DrawLine(119,108,119,319);		//画线
	
	POINT_COLOR = BLACK;
	LCD_DrawRectangle(5,110,115,314); 	//画一个矩形	
	LCD_DrawLine(5,130,115,130);		//画线
	
	LCD_DrawRectangle(125,110,234,314); //画一个矩形	
	LCD_DrawLine(125,130,234,130);		//画线
	POINT_COLOR = BLUE;
	LCD_ShowString(6,111,110,16,16,	 "AutoTim:000");
	LCD_ShowString(126,111,110,16,16,"OneTim: 000");
	
    //创建开始任务
    xTaskCreate(start_task,"start_task",256,NULL,1,&StartTask_Handler);
	//启动任务调度器
	vTaskStartScheduler();
}

start_task来创建timercontrol_task和两个软件定时器

void start_task(void *pvParameters)
{
	taskENTER_CRITICAL();
	//创建软件周期定时器,周期定时器,周期为1s(1000个时钟节拍)
	AutoReloadTimer_Handler=xTimerCreate("AutoReloadTimer",1000,pdTRUE,(void *)1,AutoReloadCallback);
	//创建单词定时器
	OneShotTimer_Handler = xTimerCreate("OneShotTimer",2000,pdFALSE,(void*)2,OneShotCallback);
	xTaskCreate(timercontrol_task,"timercontrol_task",256,NULL,2,&TimerControlTask_Handler);
	taskEXIT_CRITICAL();
	vTaskDelete(StartTask_Handler);
}

AutoReloadCallback和OneShotCallback是两个定时器的回调函数,内容为:

void AutoReloadCallback(TimerHandle_t xTYimer)
{
	static u8 tmr1_num=0;
	tmr1_num++;
	LCD_ShowxNum(70,111,tmr1_num,3,16,0x80);	//显示执行次数
	LCD_Fill(6,131,114,313,lcd_discolor[tmr1_num%14]);
}
void OneShotCallback(TimerHandle_t xTYimer)
{
	static u8 tmr2_num =0;
	tmr2_num++;
	LCD_ShowxNum(190,111,tmr2_num,3,16,0x80);
	LCD_Fill(126,131,233,313,lcd_discolor[tmr2_num%14]);
	LED1 = !LED1;
	printf("定时器2运行结束\r\n");
}

timercontrol_task内容

void timercontrol_task(void *pvParameter)
{
	u8 key,num;
	while(1)
	{
		if((AutoReloadTimer_Handler!=NULL)&&(OneShotTimer_Handler!=NULL))
		{
			key = KEY_Scan(0);
			switch(key)
			{
				case WKUP_PRES:
					xTimerStart(AutoReloadTimer_Handler,0);
					printf("开启定时器1\r\n");
					break;
				case KEY0_PRES:
					xTimerStart(OneShotTimer_Handler,0);
					printf("开始定时器2\r\n");
					break;
				case KEY1_PRES:
					xTimerStop(AutoReloadTimer_Handler,0);
					xTimerStop(OneShotTimer_Handler,0);
					printf("关闭定时器1和2\r\n");
					break;
			}
		}
		num++;
		if(num==50)
		{
			num =0;
			LED0 = !LED0;
		}
		vTaskDelay(10);//延时10ms
		
	}
}

start_task只是创建了定时器,并没有开启,在timercontrol_task中,如果按下KEY_UP按键,就会开启AutoReloadTimer_Handler定时器,按下KEY0就会启动OneShotTimer_Handler定时器,按下KEY1停止两个定时器

串口输出内容
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值