一、任务的创建 任务创建函数:OSTaskCreate()
void OSTaskCreate ( OS_TCB *p_tcb,//指向任务的任务控制块
CPU_CHAR *p_name,//任务名字
OS_TASK_PTR p_task,//任务函数名字
void *p_arg,//传递给任务的参数
OS_PRIO prio,//任务优先级
CPU_STK *p_stk_base,//任务堆栈基地址
CPU_STK_SIZE stk_limit,//任务堆栈深度
CPU_STK_SIZE stk_size,//任务堆栈大小
OS_MSG_QTY q_size,//可选消息队列
OS_TICK time_quanta,//使能时间片轮转调度,默认时钟节拍除以10
void *p_ext,//指向用户补充的存储区
OS_OPT opt,//任务的特定选项
OS_ERR *p_err)//保存错误码
①首先要定义每个任务的优先级、栈大小、任务控制块及堆栈
//任务优先级
#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);
②编写主函数
首先是外部功能函数的初始化,然后初始化UCOSIII,再创建开始任务(在创建开始任务之前必须调用进入临界区函数,创建完后还要退出临界区,然后开启UCOIII),创建开始任务的传参既是自己宏定义的一些参数。
int main(void)
{
OS_ERR err;//错误值:都是宏定义,根据对应数值找到返回错误值代表的意思
CPU_SR_ALLOC();
delay_init(168); //时钟初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组配置
uart_init(115200); //串口初始化
LED_Init(); //LED初始化
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
while(1);
}
③主函数调用
创建开始任务函数后就应编写开始任务函数的功能函数,开始任务函数内同样是调用功能函数,原理同上,接着写功能函数所要实现的功能。
//开始任务函数
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(); //进入临界区
//创建LED0任务
OSTaskCreate((OS_TCB * )&Led0TaskTCB,
(CPU_CHAR * )"led0 task",
(OS_TASK_PTR )led0_task,
(void * )0,
(OS_PRIO )LED0_TASK_PRIO,
(CPU_STK * )&LED0_TASK_STK[0],
(CPU_STK_SIZE)LED0_STK_SIZE/10,
(CPU_STK_SIZE)LED0_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);
//创建LED1任务
OSTaskCreate((OS_TCB * )&Led1TaskTCB,
(CPU_CHAR * )"led1 task",
(OS_TASK_PTR )led1_task,
(void * )0,
(OS_PRIO )LED1_TASK_PRIO,
(CPU_STK * )&LED1_TASK_STK[0],
(CPU_STK_SIZE)LED1_STK_SIZE/10,
(CPU_STK_SIZE)LED1_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 * )&FloatTaskTCB,
(CPU_CHAR * )"float test task",
(OS_TASK_PTR )float_task,
(void * )0,
(OS_PRIO )FLOAT_TASK_PRIO,
(CPU_STK * )&FLOAT_TASK_STK[0],
(CPU_STK_SIZE)FLOAT_STK_SIZE/10,
(CPU_STK_SIZE)FLOAT_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_TaskSuspend((OS_TCB*)&StartTaskTCB,&err); //挂起开始任务
OS_CRITICAL_EXIT(); //进入临界区
}
//led0任务函数
void led0_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
LED0=0;
OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err); //延时200ms
LED0=1;
OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
//led1任务函数
void led1_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
LED1=~LED1;
OSTimeDlyHMSM(0,0,0,500,OS_OPT_TIME_HMSM_STRICT,&err); //延时500ms
}
}
//浮点测试任务
void float_task(void *p_arg)
{
CPU_SR_ALLOC();
static float float_num=0.01;
while(1)
{
float_num+=0.01f;
OS_CRITICAL_ENTER(); //进入临界区
printf("float_num的值为: %.4f\r\n",float_num);
OS_CRITICAL_EXIT(); //退出临界区
delay_ms(500); //延时500ms
}
}
二、任务的删除
如果我们不想使用某个任务了就可将其删除,删除任务使用函数OSTaskDel(),函数原型如下:
void OSTaskDel (OS_TCB *p_tcb,
OS_ERR *p_err)
1、删除某个任务以后,它占用的OS_TCB和堆栈就可以再次利用来创建其他的任务。
2、尽管UCOSIII允许在系统运行中删除任务,但是应该尽量避免这种操作,如果这个任务可能占有与其他任务共享的资源,在删除此任务之前这个被占有的资源没有被释放就有可能导致奇怪的结果。
//led0任务函数
void led0_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
task1_num++; //任务执1行次数加1 注意task1_num1加到255的时候会清零!
LED0=~LED0;
OSTimeDlyHMSM(0,0,0,200,OS_OPT_TIME_HMSM_STRICT,&err); //延时200ms
printf("任务1已经执行:%d次\r\n",task1_num);
if(task1_num==5)
{
OSTaskDel((OS_TCB*)&Task2_TaskTCB,&err); //任务1执行5此后删除掉任务2
printf("任务1删除了任务2!\r\n");
}
}
}
三、任务的挂起和恢复
当我们想暂停某个任务,但是又不想删除掉这个任务的时候就可以使用函数OSTaskSuspend()来将这个任务挂起,函数原型如下:
void OSTaskSuspend ( OS_TCB *p_tcb,OS_ERR *p_err)
当我们想要恢复某个被挂起的任务的时候可以调用函数OSTaskResume(),函数原型如下
void OSTaskResume (OS_TCB *p_tcb, OS_ERR *p_err)
//led0任务函数
void led0_task(void *p_arg)
{
OS_ERR err;
p_arg = p_arg;
while(1)
{
task1_num++; //任务1执行次数加1 注意task1_num1加到255的时候会清零!
!
LED0= ~LED0;
printf("任务1已经执行:%d次\r\n",task1_num);
if(task1_num==5)
{
OSTaskSuspend((OS_TCB*)&Task2_TaskTCB,&err);//任务1执行5次后挂起任务2
printf("任务1挂起了任务2!\r\n");
}
if(task1_num==10)
{
OSTaskResume((OS_TCB*)&Task2_TaskTCB,&err); //任务1运行10次后恢复任务2
printf("任务1恢复了任务2!\r\n");
}
}
}
