1. 程式人生 > >UCOSIII 軟體定時器

UCOSIII 軟體定時器

一、相關理論

1、使用定時器需開啟巨集   OS_CFG_TMR_DEL_EN     1u

2、定時器解析度由定義的系統節拍頻率 OS_CFG_TICK_RATE_HZ 決定 

如 OS_CFG_TMR_TASK_RATE_HZ = 100,系統時鐘週期為  10ms  1000/100=10ms

 OS_CFG_TICK_RATE_HZ =200,系統時鐘週期為 5ms,定時器的最小解析度 5ms

二、相關API函式

1、建立定時器函式 OSTmrCreate()

	OSTmrCreate (  (OS_TMR*)	&tmr1,
                   (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,
                   (void*)			0,
                   (OS_ERR*)		&err);

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)               //錯誤碼

OS_OPT opt: OS_OPT_TMR_ONE_SHOT 單次定時器
             OS_OPT_TMR_PERIODIC 週期定時器

2、開啟與關閉定時器 函式

1、開啟定時器
OSTmrStart(&tmr1,&err);

CPU_BOOLEAN  OSTmrStart (OS_TMR  *p_tmr,    //指向定時器
                         OS_ERR  *p_err)    //錯誤碼
2、關閉定時器
OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err);     //關閉定時器 1

CPU_BOOLEAN  OSTmrStop (OS_TMR  *p_tmr,    //指向定時器
                        OS_OPT   opt,      //選項
                        void    *p_callback_arg,    //傳入新的回撥引數
                        OS_ERR  *p_err)

OS_OPT   opt:  OS_OPT_TMR_NONE            //除了停止計時什麼都不做
                OS_OPT_TMR_CALLBACK        //執行回撥引數
                OS_OPT_TMR_CALLBACK_ARG    //

三、模式圖解

        

          

四、程式原始碼

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "bsp_key.h"  
#include "usart.h"
#include "includes.h"

//任務優先順序
#define START_TASK_PRIO		3
//任務堆疊大小	
#define START_STK_SIZE 		512
//任務控制塊
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 Task1TaskTCB;
//任務堆疊	
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
//任務函式
void task1_task(void *p_arg);

//任務優先順序
#define TASK2_TASK_PRIO		5
//任務堆疊大小	
#define TASK2_STK_SIZE 		128
//任務控制塊
OS_TCB Task2TaskTCB;
//任務堆疊	
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
//任務函式
void task2_task(void *p_arg);

//任務優先順序
#define TASK3_TASK_PRIO		6
//任務堆疊大小	
#define TASK3_STK_SIZE 		128
//任務控制塊
OS_TCB Task3TaskTCB;
//任務堆疊	
CPU_STK TASK3_TASK_STK[TASK3_STK_SIZE];
//任務函式
void task3_task(void *p_arg);

OS_MUTEX	TEST_MUTEX;		//定義一個互斥訊號量


int main(void)
{
	OS_ERR err;
	CPU_SR_ALLOC();
	
	delay_init ();
	NVIC_PriorityGroupConfig (NVIC_PriorityGroup_2);  //設定中斷優先順序
	uart_init (115200);				//初始化串列埠
	printf("串列埠初始化完成\r\n");
	LED_Init();
	Key_GPIO_Config();
	
	OSInit(&err);
	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);
	
}

//開始任務函式
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		
	
	OS_CRITICAL_ENTER();	//進入臨界區
	
	OSMutexCreate(	 (OS_MUTEX*)		&TEST_MUTEX,
                   (CPU_CHAR*)	"TEST_MUTEX",
                   (OS_ERR*)		&err);
									 
	OSTaskCreate(	(OS_TCB*)	&Task1TaskTCB,			    //任務控制塊
                    (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);
										
	OSTaskCreate(	(OS_TCB*)		&Task2TaskTCB,		//任務控制塊
                    (CPU_CHAR*)		"task2_task ",		//任務名稱
                    (OS_TASK_PTR)   task2_task,			//任務函式
                    (void*)          0,		    		//引數
                    (OS_PRIO)       TASK2_TASK_PRIO,	//任務優先順序
                    (CPU_STK*)      &TASK2_TASK_STK[0],
                    (CPU_STK_SIZE)  TASK2_STK_SIZE/10,
                    (CPU_STK_SIZE)  TASK2_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);

	OSTaskCreate(	(OS_TCB*)		&Task3TaskTCB,			//任務控制塊
                    (CPU_CHAR*)		"task3_task ",			//任務名稱
                    (OS_TASK_PTR)   task3_task,				//任務函式
                    (void*)          0,						//引數
                    (OS_PRIO)       TASK3_TASK_PRIO,		//任務優先順序
                    (CPU_STK*)      &TASK3_TASK_STK[0],
                    (CPU_STK_SIZE)  TASK3_STK_SIZE/10,
                    (CPU_STK_SIZE)  TASK3_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*)&StartTaskTCB,&err);	//刪除任務自身
}

void task1_task(void *p_arg)
{
	u8 task1_num=0;
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	

	while(1)
	{
				OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延時500MS
				printf("任務1請求訊號量\r\n");
				OSMutexPend(  &TEST_MUTEX, 0, OS_OPT_PEND_BLOCKING , 0,  &err);
				printf("任務1執行\r\n");
				OSMutexPost(  &TEST_MUTEX,OS_ERR_NONE, &err );
				OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延時500MS
	}

}

void task2_task(void *p_arg)
{
	u8 task2_num=0;
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	
	while(1)
	{
		printf("任務2執行\r\n");

		LED1=~LED1;
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); //延時1s
	
	}

}

void task3_task(void *p_arg)
{
	static u32 i;
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	
	while(1)
	{
		
		OSMutexPend(  &TEST_MUTEX, 0, OS_OPT_PEND_BLOCKING , 0,  &err);
		printf("任務3執行中\r\n");
		
		for(i=0;i<5000000;i++)
		{
			OSSched();		
		}

		OSMutexPost(  &TEST_MUTEX,OS_ERR_NONE, &err );
		OSTimeDlyHMSM(0,0,1,0,OS_ERR_NONE,&err); //延時1s
	
	}
}