使用情况
当任务需要与多个事件的发生同步,可以使用事件标志组。有两种情况:
- 或同步——等待多个事件发生,任何一个事件发生,任务就发生(同步)
- 与同步——等待多个事件发生,当所有事件都发生,任务就发生(同步)
使用方法
事件标志组服务函数的实现代码在os_flag.c文件中,在编译时,将os_cfg.h文件中的配置常数OS_CFG_FLAG+EN设为1就可启用这些服务函数。
常用的事件标志组的服务函数有:
- OSFlagCreate() 创建事件标志组
- OSFlagPend() 等待事件标志
- OSFlagPost() 向事件标志组发布标志
void OSFlagCreate(OS_FLAG_GRP *p_grp, 指向事件标志组的指针
CPU_CHAR *p_name, 字符串——事件标志组的名字
OS_FLAGS flags, 事件标志组的初始值
OS_ERR err) 该函数返回的错误码
OS_FLAGS OSFlagPend(OS_FLAG_GRP *p_grp, 指向事件标志组的指针
OS_FLAGS flags, 等待事件标志组的哪一位
OS_TICK timeout, 指定等待事件标志组的超时时间(时钟节拍数)
OS_OPT opt,
CPU_TS *p_ts, 指向时间戳
OS_ERR *p_err) 该函数返回的错误码
opt 决定任务等待的条件
OS_OPT_PEND_FLAG_CLR_ALL 等待标志组所有的标志清零
OS_OPT_PEND_FLAG_CLR_ANY 等待标志组任意一个标志清零
OS_OPT_PEND_FLAG_SET_ALL 等待标志组所有的标志置位
OS_OPT_PEND_FLAG_SET_ANY 等待标志组任意一个标志置位
辅助选项
+OS_OPT_PEND_FLAG_CONSUME 等待条件满足后将对应的标志清零
+OS_OPT_PEND_BLOCKING (OS_OPT_PEND_NON_BLOCKING)
在标志组不满足条件时,任务选择挂起(不挂起)
OS_FLAGS OSFlagPost(OS_FLAG_GRP *p_grp, 指向事件标志组的指针
OS_FLAGS flags, 决定对哪些标志位进行置位或清零
OS_OPT opt,
OS_ERR *p_err) 函数返回错误码
opt OS_OPT_POST_FLAG_SET 置位 OS_OPT_POST_FLAG_CLR 清零
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 14 //UCOSIII中以下优先级用户程序不能使用,ALIENTEK 15 //将这些优先级分配给了UCOSIII的5个系统内部任务 16 //优先级0:中断服务服务管理任务 OS_IntQTask() 17 //优先级1:时钟节拍任务 OS_TickTask() 18 //优先级2:定时任务 OS_TmrTask() 19 //优先级OS_CFG_PRIO_MAX-2:统计任务 OS_StatTask() 20 //优先级OS_CFG_PRIO_MAX-1:空闲任务 OS_IdleTask() 21 / 22 23 //任务优先级 24 #define START_TASK_PRIO 3 25 //任务堆栈大小 26 #define START_STK_SIZE 128 27 //任务控制块 28 OS_TCB StartTaskTCB; 29 //任务堆栈 30 CPU_STK START_TASK_STK[START_STK_SIZE]; 31 //任务函数 32 void start_task(void *p_arg); 33 34 //任务优先级 35 #define MAIN_TASK_PRIO 4 36 //任务堆栈大小 37 #define MAIN_STK_SIZE 128 38 //任务控制块 39 OS_TCB Main_TaskTCB; 40 //任务堆栈 41 CPU_STK MAIN_TASK_STK[MAIN_STK_SIZE]; 42 void main_task(void *p_arg); 43 44 //任务优先级 45 #define FLAGSPROCESS_TASK_PRIO 5 46 //任务堆栈大小 47 #define FLAGSPROCESS_STK_SIZE 128 48 //任务控制块 49 OS_TCB Flagsprocess_TaskTCB; 50 //任务堆栈 51 CPU_STK FLAGSPROCESS_TASK_STK[FLAGSPROCESS_STK_SIZE]; 52 //任务函数 53 void flagsprocess_task(void *p_arg); 54 55 56 //LCD刷屏时使用的颜色 57 int lcd_discolor[14]={ WHITE, BLACK, BLUE, BRED, 58 GRED, GBLUE, RED, MAGENTA, 59 GREEN, CYAN, YELLOW,BROWN, 60 BRRED, GRAY }; 61 62 ////////////////////////事件标志组////////////////////////////// 63 #define KEY0_FLAG 0x01 64 #define KEY1_FLAG 0x02 65 #define KEYFLAGS_VALUE 0X00 66 OS_FLAG_GRP EventFlags; //定义一个事件标志组 67 68 69 //加载主界面 70 void ucos_load_main_ui(void) 71 { 72 POINT_COLOR = RED; 73 LCD_ShowString(30,10,200,16,16,"Apollo STM32F4/F7"); 74 LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 12-1"); 75 LCD_ShowString(30,50,200,16,16,"Event Flags"); 76 LCD_ShowString(30,70,200,16,16,"ATOM@ALIENTEK"); 77 LCD_ShowString(30,90,200,16,16,"2016/1/21"); 78 POINT_COLOR = BLACK; 79 LCD_DrawRectangle(5,130,234,314); //画矩形 80 POINT_COLOR = BLUE; 81 LCD_ShowString(30,110,220,16,16,"Event Flags Value:0"); 82 } 83 84 int main(void) 85 { 86 OS_ERR err; 87 CPU_SR_ALLOC(); 88 89 Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz 90 HAL_Init(); //初始化HAL库 91 delay_init(180); //初始化延时函数 92 uart_init(115200); //初始化USART 93 LED_Init(); //初始化LED 94 KEY_Init(); //初始化按键 95 PCF8574_Init(); //初始化PCF8974 96 SDRAM_Init(); //初始化SDRAM 97 LCD_Init(); //初始化LCD 98 my_mem_init(SRAMIN); //初始化内部内存池 99 ucos_load_main_ui(); //加载主UI 100 101 OSInit(&err); //初始化UCOSIII 102 OS_CRITICAL_ENTER(); //进入临界区 103 //创建开始任务 104 OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块 105 (CPU_CHAR * )"start task", //任务名字 106 (OS_TASK_PTR )start_task, //任务函数 107 (void * )0, //传递给任务函数的参数 108 (OS_PRIO )START_TASK_PRIO, //任务优先级 109 (CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址 110 (CPU_STK_SIZE)START_STK_SIZE/10, //任务堆栈深度限位 111 (CPU_STK_SIZE)START_STK_SIZE, //任务堆栈大小 112 (OS_MSG_QTY )0, //任务内部消息队列能够接收的最大消息数目,为0时禁止接收消息 113 (OS_TICK )0, //当使能时间片轮转时的时间片长度,为0时为默认长度, 114 (void * )0, //用户补充的存储区 115 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, //任务选项,为了保险起见,所有任务都保存浮点寄存器的值 116 (OS_ERR * )&err); //存放该函数错误时的返回值 117 OS_CRITICAL_EXIT(); //退出临界区 118 OSStart(&err); //开启UCOSIII 119 while(1) 120 { 121 } 122 } 123 124 //开始任务函数 125 void start_task(void *p_arg) 126 { 127 OS_ERR err; 128 CPU_SR_ALLOC(); 129 p_arg = p_arg; 130 131 CPU_Init(); 132 #if OS_CFG_STAT_TASK_EN > 0u 133 OSStatTaskCPUUsageInit(&err); //统计任务 134 #endif 135 136 #ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间 137 CPU_IntDisMeasMaxCurReset(); 138 #endif 139 140 #if OS_CFG_SCHED_ROUND_ROBIN_EN //当使用时间片轮转的时候 141 //使能时间片轮转调度功能,设置默认的时间片长度 142 OSSchedRoundRobinCfg(DEF_ENABLED,1,&err); 143 #endif 144 145 OS_CRITICAL_ENTER(); //进入临界区 146 //创建一个事件标志组 147 OSFlagCreate((OS_FLAG_GRP*)&EventFlags, //指向事件标志组 148 (CPU_CHAR* )"Event Flags", //名字 149 (OS_FLAGS )KEYFLAGS_VALUE, //事件标志组初始值 150 (OS_ERR* )&err); //错误码 151 //创建主任务 152 OSTaskCreate((OS_TCB* )&Main_TaskTCB, 153 (CPU_CHAR* )"Main task", 154 (OS_TASK_PTR )main_task, 155 (void* )0, 156 (OS_PRIO )MAIN_TASK_PRIO, 157 (CPU_STK* )&MAIN_TASK_STK[0], 158 (CPU_STK_SIZE)MAIN_STK_SIZE/10, 159 (CPU_STK_SIZE)MAIN_STK_SIZE, 160 (OS_MSG_QTY )0, 161 (OS_TICK )0, 162 (void* )0, 163 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, 164 (OS_ERR* )&err); 165 //创建MSGDIS任务 166 OSTaskCreate((OS_TCB* )&Flagsprocess_TaskTCB, 167 (CPU_CHAR* )"Flagsprocess task", 168 (OS_TASK_PTR )flagsprocess_task, 169 (void* )0, 170 (OS_PRIO )FLAGSPROCESS_TASK_PRIO, 171 (CPU_STK* )&FLAGSPROCESS_TASK_STK[0], 172 (CPU_STK_SIZE)FLAGSPROCESS_STK_SIZE/10, 173 (CPU_STK_SIZE)FLAGSPROCESS_STK_SIZE, 174 (OS_MSG_QTY )0, 175 (OS_TICK )0, 176 (void* )0, 177 (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP, 178 (OS_ERR* )&err); 179 OS_CRITICAL_EXIT(); //退出临界区 180 OSTaskDel((OS_TCB*)0,&err); //删除start_task任务自身 181 } 182 183 //主任务的任务函数 184 void main_task(void *p_arg) 185 { 186 u8 key,num; 187 OS_FLAGS flags_num; 188 OS_ERR err; 189 while(1) 190 { 191 key = KEY_Scan(0); //扫描按键 192 if(key == KEY0_PRES) 193 { 194 //向事件标志组EventFlags发送标志 195 flags_num=OSFlagPost((OS_FLAG_GRP*)&EventFlags, 196 (OS_FLAGS )KEY0_FLAG, 197 (OS_OPT )OS_OPT_POST_FLAG_SET, 198 (OS_ERR* )&err); 199 LCD_ShowxNum(174,110,flags_num,1,16,0); 200 printf("事件标志组EventFlags的值:%d ",flags_num); 201 } 202 else if(key == KEY1_PRES) 203 { 204 //向事件标志组EventFlags发送标志 205 flags_num=OSFlagPost((OS_FLAG_GRP*)&EventFlags, 206 (OS_FLAGS )KEY1_FLAG, 207 (OS_OPT )OS_OPT_POST_FLAG_SET, 208 (OS_ERR* )&err); 209 LCD_ShowxNum(174,110,flags_num,1,16,0); 210 printf("事件标志组EventFlags的值:%d ",flags_num); 211 } 212 num++; 213 if(num==50) 214 { 215 num=0; 216 LED0=!LED0; 217 } 218 OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err); //延时10ms 219 } 220 } 221 222 //事件标志组处理任务 223 void flagsprocess_task(void *p_arg) 224 { 225 u8 num; 226 OS_ERR err; 227 while(1) 228 { 229 //等待事件标志组 230 OSFlagPend((OS_FLAG_GRP*)&EventFlags, 231 (OS_FLAGS )KEY0_FLAG+KEY1_FLAG, 232 (OS_TICK )0, 233 (OS_OPT )OS_OPT_PEND_FLAG_SET_ALL+OS_OPT_PEND_FLAG_CONSUME, // 收到 k1和k0 的消息 并清零标志位 234 (CPU_TS* )0, 235 (OS_ERR* )&err); 236 num++; 237 LED1=!LED1; 238 LCD_Fill(6,131,233,313,lcd_discolor[num%14]); 239 printf("事件标志组EventFlags的值:%d ",EventFlags.Flags); 240 LCD_ShowxNum(174,110,EventFlags.Flags,1,16,0); 241 } 242 }