UCOSIII 任务间通信 消息队列 和task 内建消息队列
使用情况
一个任务或者中断服务程序与另一个任务交流信息
使用方法
消息队列服务函数的实现代码在os_q.c文件中,在编译时,将os_cfg.h文件中的配置常数OS_CFG_Q_EN设为1就可启用这些服务函数。
常用消息队列的服务函数有:
- OSQCreate() 创建消息队列
- OSQPend() 等待消息队列中的信息
- OSQPost() 向消息队列中发送消息
void OSQCreate (OS_Q *p_q, 指向消息队列控制块的指针
CPU_CHAR *p_name, 指向字符串的指针——消息队列的名字
OS_MSG_QTY max_qty, 指定消息队列的最大长度(必须为非零)
OS_ERR *p_err) 该函数返回的错误码
void *OSQPend (OS_Q *p_q, 指向消息队列控制块的指针
OS_TICK timeout, 指定等待消息的超时时间(时钟节拍数)
OS_OPT opt,
OS_MSG_SIZE *p_msg_size, 接受的消息的大小(字节数,可用sizeof获取)
CPU_TS *p_ts, 指向一个时间戳的指针
OS_ERR *p_err) 该函数返回的错误码
opt OS_OPT_PEND_BLOCKING 阻塞模式(任务挂起等待该对象)
OS_OPT_PEND_NON_BLOCKING 非阻塞模式(没有任何消息存在时,任务直接返回)
void OSQPost (OS_Q *p_q, 指向消息队列控制块的指针
void *p_void, 实际发送的消息内容
OS_MSG_SIZE msg_size, 设定消息的大小(字节数)
OS_OPT opt,
OS_ERR *p_err) 该函数返回的错误码
opt OS_OPT_POST_FIFO 待发送的消息保存在消息队列的末尾(FIFO)
OS_OPT_POST_LIFO 待发送的消息保存在消息队列的开头(LIFO)
+OS_OPT_POST_ALL 向所有等待该消息队列的任务发送消息(否则只发送到最高级)
+OS_OPT_POST_NO_SCHED 禁止在本函数内执行任务调度操作
#define KEYMSG_Q_NUM 1 //按键消息队列的数量
#define DATAMSG_Q_NUM 4 //发送数据的消息队列的数量
OS_Q KEY_Msg; //定义一个消息队列,用于按键消息传递,模拟消息邮箱
OS_Q DATA_Msg; //定义一个消息队列,用于发送数据
1 #include "sys.h" 2 #include "delay.h" 3 #include "usart.h" 4 #include "led.h" 5 #include "lcd.h" 6 #include "key.h" 7 #include "pcf8574.h" 8 #include "ltdc.h" 9 #include "sdram.h" 10 #include "malloc.h" 11 #include "includes.h" 12 //ALIENTEK 探索者STM32F429开发板 UCOSIII实验 13 //例11-1 UCOSIII 消息传递 14 15 //UCOSIII中以下优先级用户程序不能使用,ALIENTEK 16 //将这些优先级分配给了UCOSIII的5个系统内部任务 17 //优先级0:中断服务服务管理任务 OS_IntQTask() 18 //优先级1:时钟节拍任务 OS_TickTask() 19 //优先级2:定时任务 OS_TmrTask() 20 //优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask() 21 //优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask() 22 //技术支持:www.openedv.com 23 //淘宝店铺:http://eboard.taobao.com 24 //广州市星翼电子科技有限公司 25 //作者:正点原子 @ALIENTEK/ 26 27 //任务优先级 28 #define START_TASK_PRIO 3 29 //任务堆栈大小 30 #define START_STK_SIZE 128 31 //任务控制块 32 OS_TCB StartTaskTCB; 33 //任务堆栈 34 CPU_STK START_TASK_STK[START_STK_SIZE]; 35 //任务函数 36 void start_task(void *p_arg); 37 38 //任务优先级 39 #define MAIN_TASK_PRIO 4 40 //任务堆栈大小 41 #define MAIN_STK_SIZE 128 42 //任务控制块 43 OS_TCB Main_TaskTCB; 44 //任务堆栈 45 CPU_STK MAIN_TASK_STK[MAIN_STK_SIZE]; 46 void main_task(void *p_arg); 47 48 49 //任务优先级 50 #define KEYPROCESS_TASK_PRIO 5 51 //任务堆栈大小 52 #define KEYPROCESS_STK_SIZE 128 53 //任务控制块 54 OS_TCB Keyprocess_TaskTCB; 55 //任务堆栈 56 CPU_STK KEYPROCESS_TASK_STK[KEYPROCESS_STK_SIZE]; 57 //任务函数 58 void Keyprocess_task(void *p_arg); 59 60 //任务优先级 61 #define MSGDIS_TASK_PRIO 6 62 //任务堆栈 63 #define MSGDIS_STK_SIZE 128 64 //任务控制块 65 OS_TCB Msgdis_TaskTCB; 66 //任务堆栈 67 CPU_STK MSGDIS_TASK_STK[MSGDIS_STK_SIZE]; 68 //任务函数 69 void msgdis_task(void *p_arg); 70 71 //LCD刷屏时使用的颜色 72 int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED, 73 GRED, GBLUE, RED, MAGENTA, 74 GREEN, CYAN, YELLOW,BROWN, 75 BRRED, GRAY }; 76 ////////////////////////消息队列////////////////////////////// 77 #define KEYMSG_Q_NUM 1 //按键消息队列的数量 78 #define DATAMSG_Q_NUM 4 //发送数据的消息队列的数量 79 OS_Q KEY_Msg; //定义一个消息队列,用于按键消息传递,模拟消息邮箱 80 OS_Q DATA_Msg; //定义一个消息队列,用于发送数据 81 82 ////////////////////////定时器//////////////////////////////// 83 u8 tmr1sta=0; //标记定时器的工作状态 84 OS_TMR tmr1; //定义一个定时器 85 void tmr1_callback(void *p_tmr,void *p_arg); //定时器1回调函数 86 87 //加载主界面 88 void ucos_load_main_ui(void) 89 { 90 POINT_COLOR = RED; 91 LCD_ShowString(10,10,200,16,16,"Apollo STM32F4/F7"); 92 LCD_ShowString(10,30,200,16,16,"UCOSIII Examp 11-1"); 93 LCD_ShowString(10,50,200,16,16,"Message Queue"); 94 LCD_ShowString(10,70,220,16,16,"KEY_UP:LED1 KEY0:Refresh LCD"); 95 LCD_ShowString(10,90,200,16,16,"KEY1:Tmr1 KEY2:BEEP"); 96 97 POINT_COLOR = BLACK; 98 LCD_DrawLine(0,107,239,107); //画线 99 LCD_DrawLine(119,107,119,319); //画线 100 LCD_DrawRectangle(125,110,234,314); //画矩形 101 POINT_COLOR = RED; 102 LCD_ShowString(0,130,100,16,16,"tmr1 state:"); 103 LCD_ShowString(0,170,120,16,16,"DATA_Msg Size:"); 104 LCD_ShowString(0,210,120,16,16,"DATA_Msg rema:"); 105 LCD_ShowString(0,250,100,16,16,"DATA_Msg:"); 106 POINT_COLOR = BLUE; 107 LCD_ShowString(10,150,100,16,16,"TMR1 STOP! "); 108 } 109 110 //查询DATA_Msg消息队列中的总队列数量和剩余队列数量 111 void check_msg_queue(u8 *p) 112 { 113 CPU_SR_ALLOC(); 114 u8 msgq_remain_size; //消息队列剩余大小 115 OS_CRITICAL_ENTER(); //进入临界段 116 msgq_remain_size = DATA_Msg.MsgQ.NbrEntriesSize-DATA_Msg.MsgQ.NbrEntries; 117 p = mymalloc(SRAMIN,20); //申请内存 118 sprintf((char*)p,"Total Size:%d",DATA_Msg.MsgQ.NbrEntriesSize); //显示DATA_Msg消息队列总的大小 119 LCD_ShowString(10,190,100,16,16,p); 120 sprintf((char*)p,"Remain Size:%d",msgq_remain_size); //显示DATA_Msg剩余大小 121 LCD_ShowString(10,230,100,16,16,p); 122 myfree(SRAMIN,p); //释放内存 123 OS_CRITICAL_EXIT(); //退出临界段 124 } 125 126 int main(void) 127 { 128 OS_ERR err; 129 CPU_SR_ALLOC(); 130 131 Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz 132 HAL_Init(); //初始化HAL库 133 delay_init(180); //初始化延时函数 134 uart_init(115200); //初始化USART 135 LED_Init(); //初始化LED 136 KEY_Init(); //初始化按键 137 PCF8574_Init(); //初始化PCF8974 138 SDRAM_Init(); //初始化SDRAM 139 LCD_Init(); //初始化LCD 140 my_mem_init(SRAMIN); //初始化内部内存池 141 ucos_load_main_ui(); //加载主UI 142 143 OSInit(&err); //初始化UCOSIII 144 OS_CRITICAL_ENTER(); //进入临界区 145 //创建开始任务 146 OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块 147 (CPU_CHAR * )"start task", //任务名字 148 (OS_TASK_PTR )start_task, //任务函数 149 (void * )0, //传递给任务函数的参数 150 (OS_PRIO )START_TASK_PRIO, //任务优先级 151 (CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址 152 (CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位 153 (CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小 154 (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息 155 (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度, 156 (void * )0, //用户补充的存储区 157 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, //任务选项,为了保险起见,所有任务都保存浮点寄存器的值 158 (OS_ERR * )&err); //存放该函数错误时的返回值 159 OS_CRITICAL_EXIT(); //退出临界区 160 OSStart(&err); //开启UCOSIII 161 while(1) 162 { 163 } 164 } 165 166 //开始任务函数 167 void start_task(void *p_arg) 168 { 169 OS_ERR err; 170 CPU_SR_ALLOC(); 171 p_arg = p_arg; 172 173 CPU_Init(); 174 #if OS_CFG_STAT_TASK_EN > 0u 175 OSStatTaskCPUUsageInit(&err); //统计任务 176 #endif 177 178 #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间 179 CPU_IntDisMeasMaxCurReset(); 180 #endif 181 182 #if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 183 //使能时间片轮转调度功能,设置默认的时间片长度 184 OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); 185 #endif 186 187 OS_CRITICAL_ENTER(); //进入临界区 188 //创建消息队列KEY_Msg 189 OSQCreate ((OS_Q* )&KEY_Msg, //消息队列 190 (CPU_CHAR* )"KEY Msg", //消息队列名称 191 (OS_MSG_QTY )KEYMSG_Q_NUM, //消息队列长度,这里设置为1 192 (OS_ERR* )&err); //错误码 193 //创建消息队列DATA_Msg 194 OSQCreate ((OS_Q* )&DATA_Msg, 195 (CPU_CHAR* )"DATA Msg", 196 (OS_MSG_QTY )DATAMSG_Q_NUM, 197 (OS_ERR* )&err); 198 //创建定时器1 199 OSTmrCreate((OS_TMR *)&tmr1, //定时器1 200 (CPU_CHAR *)"tmr1", //定时器名字 201 (OS_TICK )0, //0ms 202 (OS_TICK )50, //50*10=500ms 203 (OS_OPT )OS_OPT_TMR_PERIODIC, //周期模式 204 (OS_TMR_CALLBACK_PTR)tmr1_callback,//定时器1回调函数 205 (void *)0, //参数为0 206 (OS_ERR *)&err); //返回的错误码 207 //创建主任务 208 OSTaskCreate((OS_TCB * )&Main_TaskTCB, 209 (CPU_CHAR * )"Main task", 210 (OS_TASK_PTR )main_task, 211 (void * )0, 212 (OS_PRIO )MAIN_TASK_PRIO, 213 (CPU_STK * )&MAIN_TASK_STK[0], 214 (CPU_STK_SIZE)MAIN_STK_SIZE/10, 215 (CPU_STK_SIZE)MAIN_STK_SIZE, 216 (OS_MSG_QTY )0, 217 (OS_TICK )0, 218 (void * )0, 219 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, 220 (OS_ERR * )&err); 221 //创建按键任务 222 OSTaskCreate((OS_TCB * )&Keyprocess_TaskTCB, 223 (CPU_CHAR * )"Keyprocess task", 224 (OS_TASK_PTR )Keyprocess_task, 225 (void * )0, 226 (OS_PRIO )KEYPROCESS_TASK_PRIO, 227 (CPU_STK * )&KEYPROCESS_TASK_STK[0], 228 (CPU_STK_SIZE)KEYPROCESS_STK_SIZE/10, 229 (CPU_STK_SIZE)KEYPROCESS_STK_SIZE, 230 (OS_MSG_QTY )0, 231 (OS_TICK )0, 232 (void * )0, 233 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, 234 (OS_ERR * )&err); 235 //创建MSGDIS任务 236 OSTaskCreate((OS_TCB * )&Msgdis_TaskTCB, 237 (CPU_CHAR * )"Msgdis task", 238 (OS_TASK_PTR )msgdis_task, 239 (void * )0, 240 (OS_PRIO )MSGDIS_TASK_PRIO, 241 (CPU_STK * )&MSGDIS_TASK_STK[0], 242 (CPU_STK_SIZE)MSGDIS_STK_SIZE/10, 243 (CPU_STK_SIZE)MSGDIS_STK_SIZE, 244 (OS_MSG_QTY )0, 245 (OS_TICK )0, 246 (void * )0, 247 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, 248 (OS_ERR * )&err); 249 OS_CRITICAL_EXIT(); //退出临界区 250 OSTaskDel((OS_TCB*)0,&err); //删除start_task任务自身 251 } 252 253 //定时器1的回调函数 254 void tmr1_callback(void *p_tmr,void *p_arg) 255 { 256 u8 *pbuf; 257 static u8 msg_num; 258 OS_ERR err; 259 pbuf = mymalloc(SRAMIN,10); //申请10个字节 260 if(pbuf) //申请内存成功 261 { 262 msg_num++; 263 sprintf((char*)pbuf,"ALIENTEK %d",msg_num); 264 //发送消息 265 OSQPost((OS_Q* )&DATA_Msg, 266 (void* )pbuf, 267 (OS_MSG_SIZE)10, 268 (OS_OPT )OS_OPT_POST_FIFO, 269 (OS_ERR* )&err); 270 if(err != OS_ERR_NONE) 271 { 272 myfree(SRAMIN,pbuf); //释放内存 273 OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1 274 tmr1sta = !tmr1sta; 275 LCD_ShowString(10,150,100,16,16,"TMR1 STOP! "); 276 } 277 } 278 } 279 280 //主任务的任务函数 281 void main_task(void *p_arg) 282 { 283 u8 key,num; 284 OS_ERR err; 285 u8 *p; 286 while(1) 287 { 288 key = KEY_Scan(0); //扫描按键 289 if(key) 290 { 291 //发送消息 292 OSQPost((OS_Q* )&KEY_Msg, 293 (void* )&key, 294 (OS_MSG_SIZE)1, 295 (OS_OPT )OS_OPT_POST_FIFO, 296 (OS_ERR* )&err); 297 } 298 num++; 299 if(num%10==0) check_msg_queue(p);//检查DATA_Msg消息队列的容量 300 if(num==50) 301 { 302 num=0; 303 LED0=!LED0; 304 } 305 OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err); //延时10ms 306 } 307 } 308 309 //按键处理任务的任务函数 310 void Keyprocess_task(void *p_arg) 311 { 312 u8 num,beepsta=1; 313 u8 *key; 314 OS_MSG_SIZE size; 315 OS_ERR err; 316 while(1) 317 { 318 //请求消息KEY_Msg 319 key=OSQPend((OS_Q* )&KEY_Msg, 320 (OS_TICK )0, 321 (OS_OPT )OS_OPT_PEND_BLOCKING, 322 (OS_MSG_SIZE* )&size, 323 (CPU_TS* )0, 324 (OS_ERR* )&err); 325 switch(*key) 326 { 327 case WKUP_PRES: //KEY_UP控制LED1 328 LED1=!LED1; 329 break; 330 case KEY2_PRES: //KEY2控制蜂鸣器 331 beepsta=!beepsta; 332 PCF8574_WriteBit(BEEP_IO,beepsta); 333 break; 334 case KEY0_PRES: //KEY0刷新LCD背景 335 num++; 336 LCD_Fill(126,111,233,313,lcd_discolor[num%14]); 337 break; 338 case KEY1_PRES: //KEY1控制定时器1 339 tmr1sta = !tmr1sta; 340 if(tmr1sta) 341 { 342 OSTmrStart(&tmr1,&err); 343 LCD_ShowString(10,150,100,16,16,"TMR1 START!"); 344 } 345 else 346 { 347 OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1 348 LCD_ShowString(10,150,100,16,16,"TMR1 STOP! "); 349 } 350 break; 351 } 352 } 353 } 354 355 //显示消息队列中的消息 356 void msgdis_task(void *p_arg) 357 { 358 u8 *p; 359 OS_MSG_SIZE size; 360 OS_ERR err; 361 while(1) 362 { 363 //请求消息 364 p=OSQPend((OS_Q* )&DATA_Msg, 365 (OS_TICK )0, 366 (OS_OPT )OS_OPT_PEND_BLOCKING, 367 (OS_MSG_SIZE* )&size, 368 (CPU_TS* )0, 369 (OS_ERR* )&err); 370 LCD_ShowString(5,270,100,16,16,p); 371 myfree(SRAMIN,p); //释放内存 372 OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s 373 } 374 }
//创建消息队列KEY_Msg
OSQCreate ((OS_Q* )&KEY_Msg, //消息队列
(CPU_CHAR* )"KEY Msg", //消息队列名称
(OS_MSG_QTY )KEYMSG_Q_NUM, //消息队列长度,这里设置为1
(OS_ERR* )&err); //错误码
//创建消息队列DATA_Msg
OSQCreate ((OS_Q* )&DATA_Msg,
(CPU_CHAR* )"DATA Msg",
(OS_MSG_QTY )DATAMSG_Q_NUM,
(OS_ERR* )&err);
//创建定时器1
OSTmrCreate((OS_TMR *)&tmr1, //定时器1
(CPU_CHAR *)"tmr1", //定时器名字
(OS_TICK )0, //0ms
(OS_TICK )50, //50*10=500ms
(OS_OPT )OS_OPT_TMR_PERIODIC, //周期模式
(OS_TMR_CALLBACK_PTR)tmr1_callback,//定时器1回调函数
(void *)0, //参数为0
(OS_ERR *)&err); //返回的错误码
//定时器1的回调函数
void tmr1_callback(void *p_tmr,void *p_arg)
{
u8 *pbuf;
static u8 msg_num;
OS_ERR err;
pbuf = mymalloc(SRAMIN,10); //申请10个字节
if(pbuf) //申请内存成功
{
msg_num++;
sprintf((char*)pbuf,"ALIENTEK %d",msg_num);
//发送消息
OSQPost((OS_Q* )&DATA_Msg,
(void* )pbuf,
(OS_MSG_SIZE)10,
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
if(err != OS_ERR_NONE)
{
myfree(SRAMIN,pbuf); //释放内存
OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1
tmr1sta = !tmr1sta;
LCD_ShowString(10,150,100,16,16,"TMR1 STOP! ");
}
}
}
//发送消息
OSQPost((OS_Q* )&KEY_Msg,
(void* )&key,
(OS_MSG_SIZE)1,
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
//请求消息KEY_Msg
key=OSQPend((OS_Q* )&KEY_Msg,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(OS_MSG_SIZE* )&size,
(CPU_TS* )0,
(OS_ERR* )&err);
//请求消息
p=OSQPend((OS_Q* )&DATA_Msg,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(OS_MSG_SIZE* )&size,
(CPU_TS* )0,
(OS_ERR* )&err);
内建消息
//创建MSGDIS任务
OSTaskCreate((OS_TCB * )&Msgdis_TaskTCB,
(CPU_CHAR * )"Msgdis task",
(OS_TASK_PTR )msgdis_task,
(void * )0,
(OS_PRIO )MSGDIS_TASK_PRIO,
(CPU_STK * )&MSGDIS_TASK_STK[0],
(CPU_STK_SIZE)MSGDIS_STK_SIZE/10,
(CPU_STK_SIZE)MSGDIS_STK_SIZE,
(OS_MSG_QTY )TASK_Q_NUM, //任务Msgdis_task需要使用内建消息队列,消息队列长度为4
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
(OS_ERR * )&err);
发送
//发送消息
OSTaskQPost((OS_TCB* )&Msgdis_TaskTCB, //向任务Msgdis发送消息
(void* )pbuf,
(OS_MSG_SIZE)10,
(OS_OPT )OS_OPT_POST_FIFO,
(OS_ERR* )&err);
if(err != OS_ERR_NONE)
{
myfree(SRAMIN,pbuf); //释放内存
OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1
tmr1sta = !tmr1sta;
LCD_ShowString(40,150,100,16,16,"TMR1 STOP! ");
}
//请求消息
p=OSTaskQPend((OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(OS_MSG_SIZE* )&size,
(CPU_TS* )0,
(OS_ERR* )&err );
1 #include "sys.h" 2 #include "delay.h" 3 #include "usart.h" 4 #include "led.h" 5 #include "lcd.h" 6 #include "key.h" 7 #include "pcf8574.h" 8 #include "ltdc.h" 9 #include "sdram.h" 10 #include "malloc.h" 11 #include "includes.h" 12 13 //UCOSIII中以下优先级用户程序不能使用,ALIENTEK 14 //将这些优先级分配给了UCOSIII的5个系统内部任务 15 //优先级0:中断服务服务管理任务 OS_IntQTask() 16 //优先级1:时钟节拍任务 OS_TickTask() 17 //优先级2:定时任务 OS_TmrTask() 18 //优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask() 19 //优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask() 20 21 22 //任务优先级 23 #define START_TASK_PRIO 3 24 //任务堆栈大小 25 #define START_STK_SIZE 128 26 //任务控制块 27 OS_TCB StartTaskTCB; 28 //任务堆栈 29 CPU_STK START_TASK_STK[START_STK_SIZE]; 30 //任务函数 31 void start_task(void *p_arg); 32 33 //任务优先级 34 #define MAIN_TASK_PRIO 4 35 //任务堆栈大小 36 #define MAIN_STK_SIZE 128 37 //任务控制块 38 OS_TCB Main_TaskTCB; 39 //任务堆栈 40 CPU_STK MAIN_TASK_STK[MAIN_STK_SIZE]; 41 void main_task(void *p_arg); 42 43 //任务优先级 44 #define MSGDIS_TASK_PRIO 6 45 //任务堆栈 46 #define MSGDIS_STK_SIZE 128 47 //任务控制块 48 OS_TCB Msgdis_TaskTCB; 49 //任务堆栈 50 CPU_STK MSGDIS_TASK_STK[MSGDIS_STK_SIZE]; 51 //任务函数 52 void msgdis_task(void *p_arg); 53 54 //LCD刷屏时使用的颜色 55 int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED, 56 GRED, GBLUE, RED, MAGENTA, 57 GREEN, CYAN, YELLOW,BROWN, 58 BRRED, GRAY }; 59 60 #define TASK_Q_NUM 4 //发任务内建消息队列的长度 61 62 ////////////////////////定时器//////////////////////////////// 63 u8 tmr1sta=0; //标记定时器的工作状态 64 OS_TMR tmr1; //定义一个定时器 65 void tmr1_callback(void *p_tmr,void *p_arg); //定时器1回调函数 66 67 68 //加载主界面 69 void ucos_load_main_ui(void) 70 { 71 POINT_COLOR = RED; 72 LCD_ShowString(10,10,200,16,16,"Apollo STM32F4/F7"); 73 LCD_ShowString(10,30,200,16,16,"UCOSIII Examp 11-2"); 74 LCD_ShowString(10,50,200,16,16,"Task Queue"); 75 LCD_ShowString(10,70,220,16,16,"KEY_UP:Tmr1"); 76 LCD_ShowString(10,90,200,16,16,"2016/1/21"); 77 78 POINT_COLOR = BLACK; 79 LCD_DrawLine(0,107,239,107); //画线 80 POINT_COLOR = RED; 81 LCD_ShowString(30,130,100,16,16,"tmr1 state:"); 82 LCD_ShowString(30,170,120,16,16,"Task_QMsg Size:"); 83 LCD_ShowString(30,210,120,16,16,"Task_QMsg rema:"); 84 LCD_ShowString(30,250,100,16,16,"Task_QMsg:"); 85 POINT_COLOR = BLUE; 86 LCD_ShowString(40,150,100,16,16,"TMR1 STOP! "); 87 } 88 89 //查询DATA_Msg消息队列中的总队列数量和剩余队列数量 90 void check_msg_queue(u8 *p) 91 { 92 CPU_SR_ALLOC(); 93 u8 msgq_remain_size; //消息队列剩余大小 94 OS_CRITICAL_ENTER(); //进入临界段 95 msgq_remain_size =Msgdis_TaskTCB.MsgQ.NbrEntriesSize-Msgdis_TaskTCB.MsgQ.NbrEntries; 96 p = mymalloc(SRAMIN,20); //申请内存 97 sprintf((char*)p,"Total Size:%d",Msgdis_TaskTCB.MsgQ.NbrEntriesSize); //显示DATA_Msg消息队列总的大小 98 LCD_ShowString(40,190,100,16,16,p); 99 sprintf((char*)p,"Remain Size:%d",msgq_remain_size); //显示DATA_Msg剩余大小 100 LCD_ShowString(40,230,100,16,16,p); 101 myfree(SRAMIN,p); //释放内存 102 OS_CRITICAL_EXIT(); //退出临界段 103 } 104 105 int main(void) 106 { 107 OS_ERR err; 108 CPU_SR_ALLOC(); 109 110 Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz 111 HAL_Init(); //初始化HAL库 112 delay_init(180); //初始化延时函数 113 uart_init(115200); //初始化USART 114 LED_Init(); //初始化LED 115 KEY_Init(); //初始化按键 116 PCF8574_Init(); //初始化PCF8974 117 SDRAM_Init(); //初始化SDRAM 118 LCD_Init(); //初始化LCD 119 my_mem_init(SRAMIN); //初始化内部内存池 120 ucos_load_main_ui(); //加载主UI 121 122 OSInit(&err); //初始化UCOSIII 123 OS_CRITICAL_ENTER(); //进入临界区 124 //创建开始任务 125 OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块 126 (CPU_CHAR * )"start task", //任务名字 127 (OS_TASK_PTR )start_task, //任务函数 128 (void * )0, //传递给任务函数的参数 129 (OS_PRIO )START_TASK_PRIO, //任务优先级 130 (CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址 131 (CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位 132 (CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小 133 (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息 134 (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度, 135 (void * )0, //用户补充的存储区 136 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, //任务选项,为了保险起见,所有任务都保存浮点寄存器的值 137 (OS_ERR * )&err); //存放该函数错误时的返回值 138 OS_CRITICAL_EXIT(); //退出临界区 139 OSStart(&err); //开启UCOSIII 140 while(1) 141 { 142 } 143 } 144 145 //开始任务函数 146 void start_task(void *p_arg) 147 { 148 OS_ERR err; 149 CPU_SR_ALLOC(); 150 p_arg = p_arg; 151 152 CPU_Init(); 153 #if OS_CFG_STAT_TASK_EN > 0u 154 OSStatTaskCPUUsageInit(&err); //统计任务 155 #endif 156 157 #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间 158 CPU_IntDisMeasMaxCurReset(); 159 #endif 160 161 #if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 162 //使能时间片轮转调度功能,设置默认的时间片长度 163 OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); 164 #endif 165 166 OS_CRITICAL_ENTER(); //进入临界区 167 //创建定时器1 168 OSTmrCreate((OS_TMR *)&tmr1, //定时器1 169 (CPU_CHAR *)"tmr1", //定时器名字 170 (OS_TICK )0, //0ms 171 (OS_TICK )50, //50*10=500ms 172 (OS_OPT )OS_OPT_TMR_PERIODIC, //周期模式 173 (OS_TMR_CALLBACK_PTR)tmr1_callback,//定时器1回调函数 174 (void *)0, //参数为0 175 (OS_ERR *)&err); //返回的错误码 176 //创建主任务 177 OSTaskCreate((OS_TCB * )&Main_TaskTCB, 178 (CPU_CHAR * )"Main task", 179 (OS_TASK_PTR )main_task, 180 (void * )0, 181 (OS_PRIO )MAIN_TASK_PRIO, 182 (CPU_STK * )&MAIN_TASK_STK[0], 183 (CPU_STK_SIZE)MAIN_STK_SIZE/10, 184 (CPU_STK_SIZE)MAIN_STK_SIZE, 185 (OS_MSG_QTY )0, 186 (OS_TICK )0, 187 (void * )0, 188 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, 189 (OS_ERR * )&err); 190 //创建MSGDIS任务 191 OSTaskCreate((OS_TCB * )&Msgdis_TaskTCB, 192 (CPU_CHAR * )"Msgdis task", 193 (OS_TASK_PTR )msgdis_task, 194 (void * )0, 195 (OS_PRIO )MSGDIS_TASK_PRIO, 196 (CPU_STK * )&MSGDIS_TASK_STK[0], 197 (CPU_STK_SIZE)MSGDIS_STK_SIZE/10, 198 (CPU_STK_SIZE)MSGDIS_STK_SIZE, 199 (OS_MSG_QTY )TASK_Q_NUM, //任务Msgdis_task需要使用内建消息队列,消息队列长度为4 200 (OS_TICK )0, 201 (void * )0, 202 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, 203 (OS_ERR * )&err); 204 OS_CRITICAL_EXIT(); //退出临界区 205 OSTaskDel((OS_TCB*)0,&err); //删除start_task任务自身 206 } 207 208 //定时器1的回调函数 209 void tmr1_callback(void *p_tmr,void *p_arg) 210 { 211 u8 *pbuf; 212 static u8 msg_num; 213 OS_ERR err; 214 pbuf = mymalloc(SRAMIN,10); //申请10个字节 215 if(pbuf) //申请内存成功 216 { 217 msg_num++; 218 sprintf((char*)pbuf,"ALIENTEK %d",msg_num); 219 //发送消息 220 OSTaskQPost((OS_TCB* )&Msgdis_TaskTCB, //向任务Msgdis发送消息 221 (void* )pbuf, 222 (OS_MSG_SIZE)10, 223 (OS_OPT )OS_OPT_POST_FIFO, 224 (OS_ERR* )&err); 225 if(err != OS_ERR_NONE) 226 { 227 myfree(SRAMIN,pbuf); //释放内存 228 OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1 229 tmr1sta = !tmr1sta; 230 LCD_ShowString(40,150,100,16,16,"TMR1 STOP! "); 231 } 232 } 233 } 234 235 //主任务的任务函数 236 void main_task(void *p_arg) 237 { 238 u8 key,num; 239 OS_ERR err; 240 u8 *p; 241 while(1) 242 { 243 key = KEY_Scan(0); //扫描按键 244 if(key==WKUP_PRES) 245 { 246 tmr1sta = !tmr1sta; 247 if(tmr1sta) 248 { 249 OSTmrStart(&tmr1,&err); 250 LCD_ShowString(40,150,100,16,16,"TMR1 START!"); 251 } 252 else 253 { 254 OSTmrStop(&tmr1,OS_OPT_TMR_NONE,0,&err); //停止定时器1 255 LCD_ShowString(40,150,100,16,16,"TMR1 STOP! "); 256 } 257 } 258 num++; 259 if(num%10==0) check_msg_queue(p);//检查DATA_Msg消息队列的容量 260 if(num==50) 261 { 262 num=0; 263 LED0=!LED0; 264 } 265 OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err); //延时10ms 266 } 267 } 268 269 //显示消息队列中的消息 270 void msgdis_task(void *p_arg) 271 { 272 u8 *p; 273 OS_MSG_SIZE size; 274 OS_ERR err; 275 while(1) 276 { 277 //请求消息 278 p=OSTaskQPend((OS_TICK )0, 279 (OS_OPT )OS_OPT_PEND_BLOCKING, 280 (OS_MSG_SIZE* )&size, 281 (CPU_TS* )0, 282 (OS_ERR* )&err ); 283 LCD_ShowString(40,270,100,16,16,p); 284 myfree(SRAMIN,p); //释放内存 285 OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err); //延时1s 286 } 287 }