基本流程:
共5个自己的任务(不计入系统任务)
1. start_task:用来创建其他任务,创建完其他任务就把自己挂起,并且把其他功能任务也挂起,仅执行一次,且他的优先级在个人任务中是最高的
2. task:用来串口接收数据,并且判断来的数据,该执行什么任务,因为在start任务中已经把功能任务挂起了,这里只要通过比对来的数据来恢复对应任务就可以了
3.led0_task,led1_task,led2_task: 三个功能任务,在task任务把自己恢复以后,执行完一次就立即把自己挂起,等待task的下一次恢复任务。
做了一个流程图,应该比较清楚,
代码:
五个任务的定义:
#define START_TASK_PRIO 3 //define priority #define START_TASK_STK_SIZE 128 //define the task stack size OS_TCB START_TASK_TCB; //define task control block CPU_STK START_TASK_STK[START_TASK_STK_SIZE];//define task stack void start_task(void *p_arg);//(void *p_arg ) is necessary #define TASK_PRIO 4 //define priority #define TASK_STK_SIZE 128 //define the task stack size OS_TCB TASK_TCB; //define task control block CPU_STK TASK_STK[TASK_STK_SIZE];//define task stack void task(void *p_arg);//(void *p_arg ) is necessary #define LED0_TASK_PRIO 5 //define priority #define LED0_TASK_STK_SIZE 128 //define the task stack size OS_TCB LED0_TASK_TCB; //define task control block CPU_STK LED0_TASK_STK[LED0_TASK_STK_SIZE];//define task stack void led0_task(void *p_arg);//(void *p_arg ) is necessary #define LED1_TASK_PRIO 6 //define priority #define LED1_TASK_STK_SIZE 128 //define the task stack size OS_TCB LED1_TASK_TCB; //define task control block CPU_STK LED1_TASK_STK[LED0_TASK_STK_SIZE];//define task stack void led1_task(void *p_arg);//(void *p_arg ) is necessary #define LED2_TASK_PRIO 7 //define priority #define LED2_TASK_STK_SIZE 128 //define the task stack size OS_TCB LED2_TASK_TCB; //define task control block CPU_STK LED2_TASK_STK[LED2_TASK_STK_SIZE];//define task stack void led2_task(void *p_arg);//(void *p_arg ) is necessary
主函数:
int main(void) { OS_ERR err; CPU_SR_ALLOC(); Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz HAL_Init(); //初始化HAL库 delay_init(180); //初始化延时函数 uart_init(115200); //初始化USART LED_Init(); //初始化LED OSInit(&err); OS_CRITICAL_ENTER();//进入代码临界保护区 OSTaskCreate (&START_TASK_TCB, (CPU_CHAR *)"start_task",start_task,0,START_TASK_PRIO,START_TASK_STK,START_TASK_STK_SIZE/10,START_TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err); OS_CRITICAL_EXIT();//退出代码临界保护区 OSStart(&err); //开启UCOSIII while(1); }
开始任务函数(start_task):
void start_task(void *p_arg) { OS_ERR err; CPU_SR_ALLOC(); CPU_Init(); OS_CRITICAL_ENTER();//进入代码临界保护区 //创建其余四个任务 OSTaskCreate (&TASK_TCB, (CPU_CHAR *)"task",task,0,TASK_PRIO,TASK_STK,TASK_STK_SIZE/10,TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err); OSTaskCreate (&LED0_TASK_TCB, (CPU_CHAR *)"led0_task",led0_task,0,LED0_TASK_PRIO,LED0_TASK_STK,LED0_TASK_STK_SIZE/10,LED0_TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err); OSTaskCreate (&LED1_TASK_TCB, (CPU_CHAR *)"led1_task",led1_task,0,LED1_TASK_PRIO,LED1_TASK_STK,LED1_TASK_STK_SIZE/10,LED1_TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err); OSTaskCreate (&LED2_TASK_TCB, (CPU_CHAR *)"led2_task",led2_task,0,LED2_TASK_PRIO,LED2_TASK_STK,LED2_TASK_STK_SIZE/10,LED2_TASK_STK_SIZE,0, 0,0,OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,&err); OS_CRITICAL_EXIT();//退出代码临界保护区 //挂起三个功能任务和自身 OS_TaskSuspend((OS_TCB*)&LED0_TASK_TCB,&err); OS_TaskSuspend((OS_TCB*)&LED1_TASK_TCB,&err); OS_TaskSuspend((OS_TCB*)&LED2_TASK_TCB,&err); OS_TaskSuspend((OS_TCB*)&START_TASK_TCB,&err); //挂起自身开始任务 }
选择功能函数(task):
void task(void *p_arg) { OS_ERR err; p_arg = p_arg; while(1) { if(USART_RX_STA&0x8000)//用串口来接收数据,来执行相应任务 { len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度 left((char *)temp,(char *)USART_RX_BUF, len); if(strcmp((const char *)temp,"任务1")==0) { OSTaskResume((OS_TCB*)&LED0_TASK_TCB,&err); } else if(strcmp((const char *)temp,"任务2")==0) { OSTaskResume((OS_TCB*)&LED1_TASK_TCB,&err); } else if(strcmp((const char *)temp,"任务3")==0) { OSTaskResume((OS_TCB*)&LED2_TASK_TCB,&err); } USART_RX_STA=0; OSTimeDlyHMSM(0,0,0,1,OS_OPT_TIME_HMSM_STRICT,&err); } } }
功能任务1(led0_task):
void led0_task(void *p_arg) { OS_ERR err; p_arg = p_arg; while(1) { printf(" 0 "); OS_TaskSuspend((OS_TCB*)&LED0_TASK_TCB,&err); } }
功能任务2(led1_task):
void led1_task(void *p_arg) { OS_ERR err; p_arg = p_arg; while(1) { printf(" 1 "); OS_TaskSuspend((OS_TCB*)&LED1_TASK_TCB,&err); } }
功能任务3(led2_task):
void led2_task(void *p_arg) { OS_ERR err; p_arg = p_arg; while(1) { printf(" 2 "); OS_TaskSuspend((OS_TCB*)&LED2_TASK_TCB,&err); } }
注意事项:
1. 在task任务中,最后一定加函数 OSTimeDlyHMSM(0,0,0,1,OS_OPT_TIME_HMSM_STRICT,&err); 这是个延时函数,但是它还有跳出这个任务执行下一个任务的功能,如果不加这个函数,mcu将一直执行task这个任务,跳不出来。
2. 在功能任务中一定要加 while(1) 循环,否则这个任务执行一次就不再执行了,就算task中恢复任务,他也不执行,因为函数已经执行完了,没什么可以执行的了,所以想要连续的执行这个任务,就得加循环
3. 任务挂起有一个不好的地方,就是等待,在正点原子的书中写到 “ OSTaskResume()函数用来恢复被OSTaskSuspend()函数挂起的任务, OSTaskResume()函数是唯一能恢复被挂起任务的函数。如果被挂起的任务还在等待别的内核对象,比如事件标志组、信号量、互斥信号量、消息队列等,即使使用OSTaskResume()函数恢复了被挂起的任务,该任务也不一定能立即运行,该任务还是要等相应的内核对象,只有等到内核对象后才可以继续运行 “.所以他不能很快的做出响应,这一点一定要注意,快相应的场合这个不适用。(谨慎使用)