UCOS operating system - software timer (8)

UCOS operating system

1. Introduction to software timer

A timer is essentially a decrementing counter. When the counter reaches zero, it can trigger the execution of an action. This action is implemented through a callback function. When the timer is finished, the defined callback function will be called immediately. The application can have any number of timers. The time resolution of the timer in UCOSIII is determined by a macro OS_CFG_TMR_TASK_RATE_HZ, the unit is HZ, and the default is 100Hz.
Notice! Be sure to avoid using blocking calls in callback functions or functions that can block or delete timer tasks.

A callback function is a function called through a function pointer. If you pass a pointer (address) of a function as a parameter to another function, when this pointer is used to call the function it points to, we say this is a callback function. The callback function is not called directly by the implementation method of the function, but is called by another party when a specific event or condition occurs to respond to the event or condition.

2. Create a timer

insert image description here

1. OSTmrCreate() function

If we want to use a timer, we must create a timer first, and use the OSTmrCreate() function to create a timer. This function is also used to determine the running mode of the timer. The prototype of the OSTmrCreate() function is as follows:

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: Pointer to the timer, the macro OS_TMR is a structure.
p_name: Timer name.
dly: The delay value to initialize the timer.
period: the repetition period.
opt: Timer running options, there are two modes to choose from.
OS_OPT_TMR_ONE_SHOT One-shot timer
OS_OPT_TMR_PERIODIC Periodic timer
p_callback: Points to the name of the callback function.
p_callback_arg: The parameter of the callback function.
p_err: The error code returned after calling this function.

2. One-shot timer

After creating a one-shot timer, once we call the OSTmrStart() function, the timer will
count down from the dly defined at the time of creation, until it is reduced to 0 and the callback function is called. One-shot timer executes only once

insert image description here
The execution of the one-shot timer in UCOS starts counting down from the dly initial delay time defined by the creation, and stops running when it is reduced to 0. Unlike the one-shot timer of FreeRTOS, the one-shot timer in FreeRTOS The timer will only be executed once and will not be calculated by time. That is, if you trigger a single timer callback function, no matter how much content there is in the function, it will definitely stop after execution. UCOS is different. UCOS uses time to determine the operation of the function. time, the same is only executed once.

2. Periodic timer

1. No initial delay

When using the OSTmrCreate() function to create a timer, set the parameter opt to OS_OPT_TMR_PERIODIC, which is the created periodic timer. When the timer counts down, the timer will call the callback function, and reset the counter to start the next round of timing, and so on. If the OSTmrCreate() function is used to create a timer and the parameter dly is 0, then the initial value of the timer counter at the beginning of each cycle is period
insert image description here

2. There is an initialization delay

When creating a timer, you can also create a timer with an initialization delay. The initialization delay is the parameter dly in the OSTmrCreate() function. The parameter dly is the initialization delay, and the first cycle of the timer is dly. When the first cycle is completed, the parameter period is used as the cycle value, and the OSTmrStart() function is called to start the timer with the initialization delay.
There is an initialization delay that you give dly a value, the first time it is executed according to this cycle, and after the execution is completed, it is executed according to the period cycle.
insert image description here
Also compared with FreeRTOS, in FreeRTOS, there is no delay or no delay. The periodic timer is executed periodically, and there is no time.

3. OSTmrStart starts the timer

insert image description here
Using the OSTmrStart function parameters are a pointer to the timer and an error code.

4. OSTmrStop closes the timer

insert image description here
Using the OSTmrStop function, the first parameter is a pointer to the timer, and the rest of the parameters are fixed.

4. Complete code

#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");
}


Guess you like

Origin blog.csdn.net/qq_51963216/article/details/123911127