首先先创建两个tmr的结构体`
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);//定时器1回调函数
进入主函数以后配置各种外设
为了避免滴答定时器的影响设置了
INTX_DISABLE();
INTX_ENABLE();
[上述这步不是必要的]
INTX_DISABLE(); //关中断,防止滴答定时器对外设初始化骚扰
LED_Init(); //LED初始化
LCD_Init(); //LCD初始化
KEY_Init();
POINT_COLOR = RED;
LCD_ShowString(30,10,200,16,16,"Soft Timer");
LCD_ShowString(30,30,200,16,16,"KEY_UP TMR1 OPEN");
LCD_ShowString(30,50,200,16,16,"KEY0 TRM2 OPEN ");
LCD_ShowString(30,70,200,16,16,"KEY1 ALL TMR STOP");
LCD_DrawRectangle(5,100,60,200);
LCD_DrawRectangle(80,100,135,200);
LCD_DrawLine(5,120,60,120);
LCD_DrawLine(80,120,135,120);
INTX_ENABLE();//开启中断
然后初始化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); //开启UCOSIII
使用临界区的时候必须在int main()的开头加上
CPU_SR_ALLOC();
否则代码错误
最后进行开始任务函数的编写
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
OSTmrCreate(
( OS_TMR*) &tmr1,
(CPU_CHAR*) "tmr1",
(OS_TICK) 20, //20*10=200MS
(OS_TICK) 100, //1000
(OS_OPT) OS_OPT_TMR_PERIODIC,
(OS_TMR_CALLBACK_PTR) tmr1_callback,
(void*) 0,
(OS_ERR*) &err);
OSTmrCreate(
( OS_TMR*) &tmr2,
(CPU_CHAR*) "tmr2",
(OS_TICK) 200,
(OS_TICK) 0,//不设置period
(OS_OPT) OS_OPT_TMR_ONE_SHOT,
(OS_TMR_CALLBACK_PTR) tmr2_callback,
(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任务自身
}
这里有一个易错点(已经犯错过):
对于OSTmrCreate();是不用进入临界区里面
只需要对另一个任务才需要在临界区
还有一个就是另一个任务在执行的时候必须要加上
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);
来跳出循环,不然会卡在这里一直不动。
成果图: