UCOS操作系统——软件定时器(八)

UCOS操作系统

一、软件定时器简介

定时器本质是递减计数器,当计数器减到零时可以触发某种动作的执行,这个动作通过回调函数来实现。当定时器计时完成时,定义的回调函数就会被立即调用,应用程序可以有任意数量的定时器,UCOSIII中定时器的时间分辨率由一个宏OS_CFG_TMR_TASK_RATE_HZ,单位为HZ,默认为100Hz。
注意!一定要避免在回调函数中使用阻塞调用或者可以阻塞或删除定时器任务的函数。

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方法直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

二、创建定时器

在这里插入图片描述

1.OSTmrCreate()函数

如果我们要使用定时器,肯定需要先创建一个定时器,使用 OSTmrCreate()函数来创建一个定时器,这个函数也用来确定定时器的运行模式,OSTmrCreate()函数原型如下:

void OSTmrCreate (OS_TMR *p_tmr,
 CPU_CHAR *p_name,
 OS_TICK dly,
 OS_TICK period,
 OS_OPT opt,
 OS_TMR_CALLBACK_PTR p_callback,
 void *p_callback_arg,
 OS_ERR *p_err)

p_tmr: 指向定时器的指针,宏 OS_TMR 是一个结构体。
p_name: 定时器名称。
dly: 初始化定时器的延迟值。
period: 重复周期。
opt: 定时器运行选项,这里有两个模式可以选择。
OS_OPT_TMR_ONE_SHOT 单次定时器
OS_OPT_TMR_PERIODIC 周期定时器
p_callback: 指向回调函数的名字。
p_callback_arg: 回调函数的参数。
p_err: 调用此函数以后返回的错误码。

2.单次定时器

创建一个单次定时器以后,我们一旦调用 OSTmrStart()函数定时器就会
从创建时定义的 dly 开始倒计数,直到减为 0 调用回调函数。单次定时器只执行一次

在这里插入图片描述
在UCOS中单次定时器的执行是从创建是定义的的dly初始延时时间开始倒计时,直到减到0时停止运行,与FreeRTOS的单次定时器不一样的是,在FreeRTOS中单次定时器只会执行一次,不会用时间来计算,就是你触发单次定时器回调函数,不管函数里面有多少内容,一定会执行完毕后在停止,UCOS不一样,UCOS是用时间来决定函数运行的时间,一样的是都只执行一次。

2.周期定时器

1.无初始延迟

使用 OSTmrCreate()函数创建定时器时把参数 opt 设置为 OS_OPT_TMR_PERIODIC,就是创建的周期定时器。 当定时器倒计数完成后,定时器就会调用回调函数,并且重置计数器开始下一轮的定时,就这样一直循环下去。如果使用 OSTmrCreate()函数创建定时器的时候,参数dly 为 0 的话,那么定时器在每个周期开始时计数器的初值就为 period
在这里插入图片描述

2.有初始化延迟

在创建定时器的时候也可以创建带有初始化延时的,初始化延时就是 OSTmrCreate()函数中的参数 dly 就是初始化延迟,定时器的第一个周期就是 dly。当第一个周期完成后就是用参数period 作为周期值,调用 OSTmrStart()函数开启有初始化延时的定时器。
有初始化延迟就是你给dly一个值,第一次按照这个周期执行,执行完毕后,按照period周期执行。
在这里插入图片描述
同样和FreeRTOS做对比,在FreeRTOS中,没有延迟与不延迟这回事,周期定时器就是周期执行,没有时间这一说。

3.OSTmrStart开启定时器

在这里插入图片描述
使用OSTmrStart函数参数是指向定时器的指针和错误码。

4.OSTmrStop关闭定时器

在这里插入图片描述
使用OSTmrStop函数,第一个参数是指向定时器的指针,其余的参数都是固定的。

四、完整代码

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
#include "includes.h"

//ÈÎÎñÓÅÏȼ¶
#define START_TASK_PRIO		3
//ÈÎÎñ¶ÑÕ»´óС	
#define START_STK_SIZE 		128
//ÈÎÎñ¿ØÖÆ¿é
OS_TCB StartTaskTCB;
//ÈÎÎñ¶ÑÕ»	
CPU_STK START_TASK_STK[START_STK_SIZE];
//ÈÎÎñº¯Êý
void start_task(void *p_arg);

//ÈÎÎñÓÅÏȼ¶
#define TASK1_TASK_PRIO		4
//ÈÎÎñ¶ÑÕ»´óС	
#define TASK1_STK_SIZE 		128
//ÈÎÎñ¿ØÖÆ¿é
OS_TCB Task1_TaskTCB;
//ÈÎÎñ¶ÑÕ»	
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
void task1_task(void *p_arg);




OS_TMR 	tmr1;		//¶¨Ê±Æ÷1
OS_TMR	tmr2;		//¶¨Ê±Æ÷2
void tmr1_callback(void *p_tmr, void *p_arg); 	//¶¨Ê±Æ÷1»Øµ÷º¯Êý
void tmr2_callback(void *p_tmr, void *p_arg);	//¶¨Ê±Æ÷2»Øµ÷º¯Êý

//LCDË¢ÆÁʱʹÓõÄÑÕÉ«
int lcd_discolor[14]={
    
    	WHITE, RED,   BLUE,  BRED,      
						GRED,  GBLUE, BLACK,   MAGENTA,       	 
						GREEN, CYAN,  YELLOW,BROWN, 			
						BRRED, GRAY };

//Ö÷º¯Êý
int main(void)
{
    
    
	OS_ERR err;
	CPU_SR_ALLOC();
	
	delay_init();  //ʱÖÓ³õʼ»¯
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//ÖжϷÖ×éÅäÖÃ
	uart_init(115200);   //´®¿Ú³õʼ»¯
	LED_Init();         //LED³õʼ»¯	
	LCD_Init();			//LCD³õʼ»¯	
	KEY_Init();			//°´¼ü³õʼ»¯
	
	POINT_COLOR = RED;
	LCD_ShowString(30,10,200,16,16,"ALIENTEK STM32F1");	
	LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 9-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,	 "TIMER1:000");
	LCD_ShowString(126,111,110,16,16,"TIMER2:000");
	
	OSInit(&err);		    	//³õʼ»¯UCOSIII
	OS_CRITICAL_ENTER();	//½øÈëÁÙ½çÇø			 
	//´´½¨¿ªÊ¼ÈÎÎñ
	OSTaskCreate((OS_TCB 	* )&StartTaskTCB,		//ÈÎÎñ¿ØÖÆ¿é
				 (CPU_CHAR	* )"start task", 		//ÈÎÎñÃû×Ö
                 (OS_TASK_PTR )start_task, 			//ÈÎÎñº¯Êý
                 (void		* )0,					//´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
                 (OS_PRIO	  )START_TASK_PRIO,     //ÈÎÎñÓÅÏȼ¶
                 (CPU_STK   * )&START_TASK_STK[0],	//ÈÎÎñ¶ÑÕ»»ùµØÖ·
                 (CPU_STK_SIZE)START_STK_SIZE/10,	//ÈÎÎñ¶ÑÕ»Éî¶ÈÏÞλ
                 (CPU_STK_SIZE)START_STK_SIZE,		//ÈÎÎñ¶ÑÕ»´óС
                 (OS_MSG_QTY  )0,					//ÈÎÎñÄÚ²¿ÏûÏ¢¶ÓÁÐÄܹ»½ÓÊÕµÄ×î´óÏûÏ¢ÊýÄ¿,Ϊ0ʱ½ûÖ¹½ÓÊÕÏûÏ¢
                 (OS_TICK	  )0,					//µ±Ê¹ÄÜʱ¼äƬÂÖתʱµÄʱ¼äƬ³¤¶È£¬Îª0ʱΪĬÈϳ¤¶È£¬
                 (void   	* )0,					//Óû§²¹³äµÄ´æ´¢Çø
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //ÈÎÎñÑ¡Ïî
                 (OS_ERR 	* )&err);				//´æ·Å¸Ãº¯Êý´íÎóʱµÄ·µ»ØÖµ
	OS_CRITICAL_EXIT();	//Í˳öÁÙ½çÇø	 
	OSStart(&err);      //¿ªÆôUCOSIII
}


//¿ªÊ¼ÈÎÎñº¯Êý
void start_task(void *p_arg)
{
    
    
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	
	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);  	//ͳ¼ÆÈÎÎñ                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//Èç¹ûʹÄÜÁ˲âÁ¿ÖжϹرÕʱ¼ä
    CPU_IntDisMeasMaxCurReset();	
#endif
	
#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //µ±Ê¹ÓÃʱ¼äƬÂÖתµÄʱºò
	 //ʹÄÜʱ¼äƬÂÖתµ÷¶È¹¦ÄÜ,ʱ¼äƬ³¤¶ÈΪ1¸öϵͳʱÖÓ½ÚÅÄ£¬¼È1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif	
	
	//´´½¨¶¨Ê±Æ÷1
	OSTmrCreate((OS_TMR		*)&tmr1,		//¶¨Ê±Æ÷1
                (CPU_CHAR	*)"tmr1",		//¶¨Ê±Æ÷Ãû×Ö
                (OS_TICK	 )20,			//20*10=200ms
                (OS_TICK	 )100,          //100*10=1000ms
                (OS_OPT		 )OS_OPT_TMR_PERIODIC, //ÖÜÆÚģʽ
                (OS_TMR_CALLBACK_PTR)tmr1_callback,//¶¨Ê±Æ÷1»Øµ÷º¯Êý
                (void	    *)0,			//²ÎÊýΪ0
                (OS_ERR	    *)&err);		//·µ»ØµÄ´íÎóÂë
				
				
	//´´½¨¶¨Ê±Æ÷2
	OSTmrCreate((OS_TMR		*)&tmr2,		
                (CPU_CHAR	*)"tmr2",		
                (OS_TICK	 )200,			//200*10=2000ms	
                (OS_TICK	 )0,   					
                (OS_OPT		 )OS_OPT_TMR_ONE_SHOT, 	//µ¥´Î¶¨Ê±Æ÷
                (OS_TMR_CALLBACK_PTR)tmr2_callback,	//¶¨Ê±Æ÷2»Øµ÷º¯Êý
                (void	    *)0,			
                (OS_ERR	    *)&err);	
				
	
	OS_CRITICAL_ENTER();	//½øÈëÁÙ½çÇø
	//´´½¨TASK1ÈÎÎñ
	OSTaskCreate((OS_TCB 	* )&Task1_TaskTCB,		
				 (CPU_CHAR	* )"Task1 task", 		
                 (OS_TASK_PTR )task1_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )TASK1_TASK_PRIO,     
                 (CPU_STK   * )&TASK1_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK1_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK1_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,  					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);				 
	OS_CRITICAL_EXIT();	//Í˳öÁÙ½çÇø
	OSTaskDel((OS_TCB*)0,&err);	//ɾ³ýstart_taskÈÎÎñ×ÔÉí
}

//ÈÎÎñ1µÄÈÎÎñº¯Êý
void task1_task(void *p_arg)
{
    
    
	u8 key,num;
	OS_ERR err;
	while(1)
	{
    
    
		key = KEY_Scan(0);
		switch(key)
		{
    
    
			case WKUP_PRES:     //µ±key_up°´ÏµĻ°´ò¿ª¶¨Ê±Æ÷1
				OSTmrStart(&tmr1,&err);	//¿ªÆô¶¨Ê±Æ÷1
				printf("¿ªÆô¶¨Ê±Æ÷1\r\n");
				break;
			case KEY0_PRES:		//µ±key0°´ÏµĻ°´ò¿ª¶¨Ê±Æ÷2
				OSTmrStart(&tmr2,&err);	//¿ªÆô¶¨Ê±Æ÷2
				printf("¿ªÆô¶¨Ê±Æ÷2\r\n");
				break;
			case KEY1_PRES:		//µ±key1°´Ï»°¾Í¹Ø±Õ¶¨Ê±Æ÷
				OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err);	//¹Ø±Õ¶¨Ê±Æ÷1
				OSTmrStop(&tmr2,OS_OPT_TMR_NONE,0,&err);	//¹Ø±Õ¶¨Ê±Æ÷2
				printf("¹Ø±Õ¶¨Ê±Æ÷1ºÍ2\r\n");
				break;	
		}
		num++;
		if(num==50) //ÿ500msLED0ÉÁ˸һ´Î
		{
    
    
			num = 0;
			LED0 = ~LED0;	
		}
		OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);   //ÑÓʱ10ms
	}
}

//¶¨Ê±Æ÷1µÄ»Øµ÷º¯Êý
void tmr1_callback(void *p_tmr, void *p_arg)
{
    
    
	static u8 tmr1_num=0;
	LCD_ShowxNum(62,111,tmr1_num,3,16,0x80); //ÏÔʾ¶¨Ê±Æ÷1µÄÖ´ÐдÎÊý
	LCD_Fill(6,131,114,313,lcd_discolor[tmr1_num%14]);//Ìî³äÇøÓò
	tmr1_num++;		//¶¨Ê±Æ÷1Ö´ÐдÎÊý¼Ó1
}

//¶¨Ê±Æ÷2µÄ»Øµ÷º¯Êý
void tmr2_callback(void *p_tmr,void *p_arg)
{
    
    
	static u8 tmr2_num = 0;
	tmr2_num++;		//¶¨Ê±Æ÷2Ö´ÐдÎÊý¼Ó1
	LCD_ShowxNum(182,111,tmr2_num,3,16,0x80);  //ÏÔʾ¶¨Ê±Æ÷1Ö´ÐдÎÊý
	LCD_Fill(126,131,233,313,lcd_discolor[tmr2_num%14]); //Ìî³äÇøÓò
	LED1 = ~LED1;
	printf("¶¨Ê±Æ÷2ÔËÐнáÊø\r\n");
}


猜你喜欢

转载自blog.csdn.net/qq_51963216/article/details/123911127