基于ucos操作系统的LED闪烁、串口通信简单例程
扫描二维码
随时随地手机看文章
* 内容简述:
本例程操作系统采用ucos2.86a版本, 建立了5个任务
任务名 优先级
APP_TASK_START_PRIO 2 主任务
Task_Com1_PRIO 4 COM1通信任务
Task_Led1_PRIO 7 LED1 闪烁任务
Task_Led2_PRIO 8 LED2 闪烁任务
Task_Led3_PRIO 9 LED3 闪烁任务
当然还包含了系统任务:
OS_TaskIdle 空闲任务-----------------优先级最低
OS_TaskStat 统计运行时间的任务-------优先级次低
1、主任务建立:
1 //建立主任务, 优先级最高 建立这个任务另外一个用途是为了以后使用统计任务
2 os_err = OSTaskCreate((void (*) (void *)) App_TaskStart, //指向任务代码的指针
3 (void *) 0, //任务开始执行时,传递给任务的参数的指针
4 (OS_STK *) &App_TaskStartStk[APP_TASK_START_STK_SIZE - 1], //分配给任务的堆栈的栈顶指针 从顶向下递减
5 (INT8U) APP_TASK_START_PRIO); //分配给任务的优先级
这个采用老版本的任务建立函数,第一个参数通俗的说法就是该任务对应的函数,如下:
1 static void App_TaskStart(void* p_arg)
2 {
3 (void) p_arg;
4 //初始化ucos时钟节拍
5 OS_CPU_SysTickInit(); /* Initialize the SysTick. */
6
7 //使能ucos 的统计任务
8 #if (OS_TASK_STAT_EN > 0)
9 //----统计任务初始化函数
10 OSStatInit(); /* Determine CPU capacity. */
11 #endif
12 //建立其他的任务
13 App_TaskCreate();
14
15 while (1)
16 {
17 //1秒一次循环
18 OSTimeDlyHMSM(0, 0,1, 0);
19 }
20 }
当主任务建立之后,程序就转到该函数处,调用 App_TaskCreate();建立其他任务,然后进入死循环,我们会发现:这里的主任务在建立其他任务后就没啥作用的,这时可以调用相应的函数将主任务给杀死,这里没有这样做,只是让主任务进入循环。
2、其他任务建立:
1 static void App_TaskCreate(void)
2 {
3 //CPU_INT08U os_err;
4
5 //Com1_SEM=OSSemCreate(1); //建立串口1中断的信号量
6 Com1_MBOX=OSMboxCreate((void *) 0); //建立串口1中断的消息邮箱
7
8 //串口1接收及发送任务---------------------------------------------------------
9 OSTaskCreateExt(Task_Com1, //指向任务代码的指针
10 (void *)0, //任务开始执行时,传递给任务的参数的指针
11 (OS_STK *)&Task_Com1Stk[Task_Com1_STK_SIZE-1],//分配给任务的堆栈的栈顶指针 从顶向下递减
12 Task_Com1_PRIO, //分配给任务的优先级
13 Task_Com1_PRIO, //预备给以后版本的特殊标识符,在现行版本同任务优先级
14 (OS_STK *)&Task_Com1Stk[0], //指向任务堆栈栈底的指针,用于堆栈的检验
15 Task_Com1_STK_SIZE, //指定堆栈的容量,用于堆栈的检验
16 (void *)0, //指向用户附加的数据域的指针,用来扩展任务的任务控制块
17 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR); //选项,指定是否允许堆栈检验,是否将堆栈清0,任务是否要进行浮点运算等等。
18 //LED1 闪烁任务------------------------------------------------------
19 OSTaskCreateExt(Task_Led1,(void *)0,(OS_STK *)&Task_Led1Stk[Task_Led1_STK_SIZE-1],Task_Led1_PRIO,Task_Led1_PRIO,(OS_STK *)&Task_Led1Stk[0],
20 Task_Led1_STK_SIZE,
21 (void *)0,
22 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);
23
24 //LED2 闪烁任务------------------------------------------------------
25 OSTaskCreateExt(Task_Led2,(void *)0,(OS_STK *)&Task_Led2Stk[Task_Led2_STK_SIZE-1],Task_Led2_PRIO,Task_Led2_PRIO,(OS_STK *)&Task_Led2Stk[0],
26 Task_Led2_STK_SIZE,
27 (void *)0,
28 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);
29
30 //LED3 闪烁任务------------------------------------------------------
31 OSTaskCreateExt(Task_Led3,(void *)0,(OS_STK *)&Task_Led3Stk[Task_Led3_STK_SIZE-1],Task_Led3_PRIO,Task_Led3_PRIO,(OS_STK *)&Task_Led3Stk[0],
32 Task_Led3_STK_SIZE,
33 (void *)0,
34 OS_TASK_OPT_STK_CHK|OS_TASK_OPT_STK_CLR);
35 }
这里是建立四个子任务第一个是串口通信的任务,一会再说,下面三个是LED闪烁任务,这里举Task_Led1说明:
1 //LED1闪烁任务----------------------------------------
2 static void Task_Led1(void* p_arg)
3 {
4 (void) p_arg;
5 while (1)
6 {
7 LED_LED1_ON();
8 OSTimeDlyHMSM(0, 0, 0, milsec1);
9
10 LED_LED1_OFF();
11 OSTimeDlyHMSM(0, 0, 0, milsec1);
12 }
13 }
可见LED闪烁任务其实就是一个无限循环,让灯的电平每隔一定时间高、每隔一定时间低来呈现闪烁的效果。那么,他是怎样实现任务切换的呢?这就是操作系统的功能了,操作系统根据每个任务的优先级,在每个子任务执行到一定时期查询当前挂起任务的优先级来选择优先级最高的进行