写在前面:
由于时间的不足与学习的碎片化,写博客变得有些奢侈。
但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。
既然如此
不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录,记录笔者认为最通俗、最有帮助的资料,并尽量总结几句话指明本质,以便于日后搜索起来更加容易。
标题的结构如下:“类型”:“知识点”——“简短的解释”
部分内容由于保密协议无法上传。
点击此处进入学习日记的总目录
2024.04.10:UCOSIII第三十八节:事件实验现象
- 五十二、UCOSIII:事件实验
- 1、实验设计与代码
- 1. 在app.c中修改
- 2. 在app_cfg.c中修改优先级 与 栈空间
- 3. 在bsp_key.c中添加检测按键状态函数源码
- 4. 在bsp_key.h中添加检测按键状态函数声明
- 2、实验现象
五十二、UCOSIII:事件实验
1、实验设计与代码
事件标志组实验是在μC/OS中创建了两个任务,一个是设置事件任务,一个是等待事件任务。
两个任务独立运行, 设置事件任务通过检测按键的按下情况设置不同的事件标志位,等待事件任务则获取这两个事件标志位,并且判断两个事件是否都发生, 如果是则输出相应信息,LED进行翻转。
等待事件任务一直在等待事件的发生,等待到事件之后清除对应的事件标记位,具体如下:
1. 在app.c中修改
#include <includes.h>
OS_FLAG_GRP flag_grp; //声明事件标志组
#define KEY1_EVENT (0x01 << 0)//设置事件掩码的位0
#define KEY2_EVENT (0x01 << 1)//设置事件掩码的位1
static OS_TCB AppTaskStartTCB; //任务控制块
static OS_TCB AppTaskPostTCB;
static OS_TCB AppTaskPendTCB;
static CPU_STK AppTaskStartStk[APP_TASK_START_STK_SIZE]; //任务栈
static CPU_STK AppTaskPostStk [ APP_TASK_POST_STK_SIZE ];
static CPU_STK AppTaskPendStk [ APP_TASK_PEND_STK_SIZE ];
static void AppTaskStart (void *p_arg); //任务函数声明
static void AppTaskPost ( void * p_arg );
static void AppTaskPend ( void * p_arg );
int main (void)
{
OS_ERR err;
OSInit(&err); //初始化 μC/OS-III
/* 创建起始任务 */
OSTaskCreate((OS_TCB *)&AppTaskStartTCB,
//任务控制块地址
(CPU_CHAR *)"App Task Start",
//任务名称
(OS_TASK_PTR ) AppTaskStart,
//任务函数
(void *) 0,
//传递给任务函数(形参p_arg)的实参
(OS_PRIO ) APP_TASK_START_PRIO,
//任务的优先级
(CPU_STK *)&AppTaskStartStk[0],
//任务栈的基地址
(CPU_STK_SIZE) APP_TASK_START_STK_SIZE / 10,
//任务栈空间剩下1/10时限制其增长
(CPU_STK_SIZE) APP_TASK_START_STK_SIZE,
//任务栈空间(单位:sizeof(CPU_STK))
(OS_MSG_QTY ) 5u,
//任务可接收的最大消息数
(OS_TICK ) 0u,
//任务的时间片节拍数(0表默认值OSCfg_TickRate_Hz/10)
(void *) 0,
//任务扩展(0表不扩展)
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
//任务选项
(OS_ERR *)&err);
//返回错误类型
OSStart(&err);
//启动多任务管理(交由μC/OS-III控制)
}
static void AppTaskStart (void *p_arg)
{
CPU_INT32U cpu_clk_freq;
CPU_INT32U cnts;
OS_ERR err;
(void)p_arg;
BSP_Init();
//板级初始化
CPU_Init();
//初始化 CPU组件(时间戳、关中断时间测量和主机名)
cpu_clk_freq = BSP_CPU_ClkFreq();
//获取 CPU内核时钟频率(SysTick 工作时钟)
cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz;
//根据用户设定的时钟节拍频率计算 SysTick定时器的计数值
OS_CPU_SysTickInit(cnts);
//调用 SysTick初始化函数,设置定时器计数值和启动定时器
Mem_Init();
//初始化内存管理组件(堆内存池和内存池表)
#if OS_CFG_STAT_TASK_EN > 0u
//如果启用(默认启用)了统计任务
OSStatTaskCPUUsageInit(&err);
#endif
CPU_IntDisMeasMaxCurReset();
//复位(清零)当前最大关中断时间
/* 创建事件标志组 flag_grp */
OSFlagCreate ((OS_FLAG_GRP *)&flag_grp, //指向事件标志组的指针
(CPU_CHAR *)"FLAG For Test", //事件标志组的名字
(OS_FLAGS )0, //事件标志组的初始值
(OS_ERR *)&err); //返回错误类型
/* 创建 AppTaskPost 任务 */
OSTaskCreate((OS_TCB *)&AppTaskPostTCB,
//任务控制块地址
(CPU_CHAR *)"App Task Post",
//任务名称
(OS_TASK_PTR ) AppTaskPost,
//任务函数
(void *) 0,
//传递给任务函数(形参p_arg)的实参
(OS_PRIO ) APP_TASK_POST_PRIO,
//任务的优先级
(CPU_STK *)&AppTaskPostStk[0],
//任务栈的基地址
(CPU_STK_SIZE) APP_TASK_POST_STK_SIZE / 10,
//任务栈空间剩下1/10时限制其增长
(CPU_STK_SIZE) APP_TASK_POST_STK_SIZE,
//任务栈空间(单位:sizeof(CPU_STK))
(OS_MSG_QTY ) 5u,
//任务可接收的最大消息数
(OS_TICK ) 0u,
//任务的时间片节拍数(0表默认值OSCfg_TickRate_Hz/10)
(void *) 0,
//任务扩展(0表不扩展)
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
//任务选项
(OS_ERR *)&err);
//返回错误类型
/* 创建 AppTaskPend 任务 */
OSTaskCreate((OS_TCB *)&AppTaskPendTCB,
//任务控制块地址
(CPU_CHAR *)"App Task Pend",
//任务名称
(OS_TASK_PTR ) AppTaskPend,
//任务函数
(void *) 0,
//传递给任务函数(形参p_arg)的实参
(OS_PRIO ) APP_TASK_PEND_PRIO,
//任务的优先级
(CPU_STK *)&AppTaskPendStk[0],
//任务栈的基地址
(CPU_STK_SIZE) APP_TASK_PEND_STK_SIZE / 10,
//任务栈空间剩下1/10时限制其增长
(CPU_STK_SIZE) APP_TASK_PEND_STK_SIZE,
//任务栈空间(单位:sizeof(CPU_STK))
(OS_MSG_QTY ) 5u,
//任务可接收的最大消息数
(OS_TICK ) 0u,
//任务的时间片节拍数(0表默认值OSCfg_TickRate_Hz/10)
(void *) 0,
//任务扩展(0表不扩展)
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR),
//任务选项
(OS_ERR *)&err);
//返回错误类型
OSTaskDel ( & AppTaskStartTCB, & err );
//删除起始任务本身,该任务不再运行
}
static void AppTaskPost ( void * p_arg )
{
OS_ERR err;
(void)p_arg;
while (DEF_TRUE) //任务体
{
if ( Key_ReadStatus ( macKEY1_GPIO_PORT, macKEY1_GPIO_PIN, 1 ) == 1 )
//如果KEY1被按下
{
//点亮LED1
printf("KEY1被按下\n");
OSFlagPost ((OS_FLAG_GRP *)&flag_grp,
//将标志组的BIT0置1
(OS_FLAGS )KEY1_EVENT,
(OS_OPT )OS_OPT_POST_FLAG_SET,
(OS_ERR *)&err);
}
if ( Key_ReadStatus ( macKEY2_GPIO_PORT, macKEY2_GPIO_PIN, 1 ) == 1 )
//如果KEY2被按下
{
//点亮LED2
printf("KEY2被按下\n");
OSFlagPost ((OS_FLAG_GRP *)&flag_grp,
//将标志组的BIT1置1
(OS_FLAGS )KEY2_EVENT,
(OS_OPT )OS_OPT_POST_FLAG_SET,
(OS_ERR *)&err);
}
OSTimeDlyHMSM ( 0, 0, 0, 20, OS_OPT_TIME_DLY, & err );
}
}
static void AppTaskPend ( void * p_arg )
{
OS_ERR err;
OS_FLAGS flags_rdy;
(void)p_arg;
while (DEF_TRUE) //任务体
{
//等待标志组的的BIT0和BIT1均被置1
flags_rdy = OSFlagPend ((OS_FLAG_GRP *)&flag_grp,
(OS_FLAGS )( KEY1_EVENT | KEY2_EVENT ),
(OS_TICK )0,
(OS_OPT)OS_OPT_PEND_FLAG_SET_ALL |
OS_OPT_PEND_BLOCKING |
OS_OPT_PEND_FLAG_CONSUME,
(CPU_TS *)0,
(OS_ERR *)&err);
if ((flags_rdy & (KEY1_EVENT|KEY2_EVENT)) == (KEY1_EVENT|KEY2_EVENT))
{
/* 如果接收完成并且正确 */
printf ( "KEY1与KEY2都按下\n");
macLED1_TOGGLE(); //LED1 翻转
}
}
}
2. 在app_cfg.c中修改优先级 与 栈空间
/*
*********************************************************************************************************
* TASK PRIORITIES
*********************************************************************************************************
*/
#define APP_TASK_START_PRIO 2 //任务优先级
#define APP_TASK_POST_PRIO 3
#define APP_TASK_PEND_PRIO 3
/*
*********************************************************************************************************
* TASK STACK SIZES
* Size of the task stacks (# of OS_STK entries)
*********************************************************************************************************
*/
#define APP_TASK_START_STK_SIZE 128 //任务堆栈空间(单位:sizeof(CPU_STK))
#define APP_TASK_POST_STK_SIZE 512
#define APP_TASK_PEND_STK_SIZE 512
3. 在bsp_key.c中添加检测按键状态函数源码
/**
* @brief 检测按键的状态
* @param GPIOx :按键所在的端口
* @param GPIO_Pin :按键所在的管脚
* @param ucPushState :按键被按下时的电平极性
* 该参数为以下值之一:
* @arg 1 :高电平
* @arg 0 :低电平
* @retval 按键的当前状态
* 该返回值为以下值之一:
* @arg 1 :按键被按下
* @arg 0 :按键被释放
*/
uint8_t Key_ReadStatus ( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, uint8_t ucPushState )
{
uint8_t ucKeyState;
ucKeyState = GPIO_ReadInputDataBit ( GPIOx, GPIO_Pin );
if ( ucKeyState == ucPushState )
return 1;
else
return 0;
}
4. 在bsp_key.h中添加检测按键状态函数声明
uint8_t Key_ReadStatus ( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, uint8_t ucPushState );