uCOSIII_消息队列-消息传递实验分析
实验内容:
创建4个任务:
static void AppTaskStart(void *p_arg);
static void main_task(void *p_arg);
static void Keyprocess_task (void *p_arg);
static void msgdis_task (void *p_arg);
两个消息队列:
static OS_Q Key_Msg;
static OS_Q Data_Msg;
一个软件定时器:
static OS_TMR tmr1;
AppTaskStart用于创建其他三个任务。
main_task 负责按键检测,并将测得按键值传入消息队列Key_Msg,同时LED绿灯闪烁和检测消息队列Data_Msg的总容量和剩余容量。
Keyprocess_task 根据不同的按键值做出相应的处理内容,其中KEY1按键BLUE灯翻转,KEY2按键RED灯翻转。
msgdis_task 用于在LCD上显示回调函数执行的次数。回调函数执行的次数会发送到消息队列Data_Msg。
关键代码:
任务优先级:
#define APP_TASK_START_PRIO 3
#define APP_MAIN_TASK_PRIO 4
#define APP_KEYPROCESS_TASK_PRIO 5
#define APP_MSGDIS_TASK_PRIO 6
static void AppTaskStart (void *p_arg)
{
CPU_INT32U cpu_clk_freq;
CPU_INT32U cnts;
OS_ERR err;
CPU_SR_ALLOC();
(void)p_arg;
BSP_Init(); /* Initialize BSP functions */
CPU_Init();
cpu_clk_freq = BSP_CPU_ClkFreq(); /* Determine SysTick reference freq. 72000000Hz */
cnts = cpu_clk_freq / (CPU_INT32U)OSCfg_TickRate_Hz; /* Determine nbr SysTick increments 72000 */
OS_CPU_SysTickInit(cnts); //默认时间节拍100ms /* Init uC/OS periodic time src (SysTick). */
// OSSchedRoundRobinCfg(DEF_ENABLED,10,&err);//设置一个时间片10ms
Mem_Init(); /* Initialize Memory Management Module */
#if OS_CFG_STAT_TASK_EN > 0u
OSStatTaskCPUUsageInit(&err); /* Compute CPU capacity with no task running */
#endif
CPU_IntDisMeasMaxCurReset();
#if (APP_CFG_SERIAL_EN == DEF_ENABLED)
BSP_Ser_Init(115200); /* Enable Serial Interface */
#endif
OS_CRITICAL_ENTER(); //进入临界区
//创建 Key_Msg 消息队列
OSQCreate (&Key_Msg, "Key Msg", KEY_MSG_MAX_SIZE, &err);
//创建 Key_Msg 消息队列
OSQCreate (&Data_Msg, "Data Msg", DATA_MSG_MAX_SIZE, &err);
//创建定时器任务1,周期模式
OSTmrCreate ( (OS_TMR *)&tmr1 ,
(CPU_CHAR *)"tmr1",
(OS_TICK )0,
(OS_TICK )5, /*定时器定时周期50ms*/
(OS_OPT )OS_OPT_TMR_PERIODIC,
(OS_TMR_CALLBACK_PTR )tmr1_callback,
(void *)0,
(OS_ERR *)&err);
//创建main_task
OSTaskCreate((OS_TCB *)&MainTaskTCB, /* Create the start task */
(CPU_CHAR *)"main task",
(OS_TASK_PTR ) main_task,
(void *) 0,
(OS_PRIO ) APP_MAIN_TASK_PRIO,
(CPU_STK *)&MainTaskStk[0],
(CPU_STK_SIZE) APP_MAIN_TASK_STK_SIZE / 10,
(CPU_STK_SIZE) APP_MAIN_TASK_STK_SIZE,
(OS_MSG_QTY ) 0u,
(OS_TICK ) 0u,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP),
(OS_ERR *)&err);
//创建Keyprocess_task
OSTaskCreate((OS_TCB *)&KeyProsessTCB, /* Create the start task */
(CPU_CHAR *)"Keyprocess task",
(OS_TASK_PTR ) Keyprocess_task,
(void *) 0,
(OS_PRIO ) APP_KEYPROCESS_TASK_PRIO,
(CPU_STK *)&KeyProsessStk[0],
(CPU_STK_SIZE) APP_KEYPROCESS_TASK_STK_SIZE / 10,
(CPU_STK_SIZE) APP_KEYPROCESS_TASK_STK_SIZE,
(OS_MSG_QTY ) 0u,
(OS_TICK ) 0u,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP),
(OS_ERR *)&err);
//创建msgdis_task
OSTaskCreate((OS_TCB *)&MsgDisTCB, /* Create the start task */
(CPU_CHAR *)"msgdis task",
(OS_TASK_PTR ) msgdis_task,
(void *) 0,
(OS_PRIO ) APP_MSGDIS_TASK_PRIO,
(CPU_STK *)&MsgDisStk[0],
(CPU_STK_SIZE) APP_MSGDIS_TASK_STK_SIZE / 10,
(CPU_STK_SIZE) APP_MSGDIS_TASK_STK_SIZE,
(OS_MSG_QTY ) 0u,
(OS_TICK ) 0u,
(void *) 0,
(OS_OPT )(OS_OPT_TASK_STK_CHK | OS_OPT_TASK_STK_CLR | OS_OPT_TASK_SAVE_FP),
(OS_ERR *)&err);
OS_CRITICAL_EXIT(); //退出临界区
OSTmrStart (&tmr1, &err); /*开启定时器,开始调试时忘记开启,找了好久*/
OSTaskDel(&AppTaskStartTCB, &err); //删除起始任务自身
}
static void main_task (void *p_arg)
{
uint8_t time0 =0, key_num ;
OS_ERR err;
(void)p_arg;
while(1)
{
key_num = 0; /***此处必须将按键值清零,因为发送到消息队列的值是用指针,不清零总会用上次循环的按键的值***/
if(Key_Scan(KEY1_GPIO_PORT ,KEY1_GPIO_PIN) == KEY_ON) /*检测按键值*/
{
key_num = 1;
printf("\nKEY%d按下\n",key_num);
}
else if(Key_Scan(KEY2_GPIO_PORT ,KEY2_GPIO_PIN) == KEY_ON)
{
key_num = 2;
printf("\nKEY%d按下\n",key_num);
}
if(key_num)
{
OSQPost ( &Key_Msg,(void *) &key_num,(OS_MSG_SIZE)1, OS_OPT_POST_FIFO, &err); /*发送按键值给消息队列*/
}
time0 ++;
if(time0 % 10 == 0)
Check_msg_q();
if(time0 == 100)
{
LED_GRE_TOGGLE;
time0 = 0;
}
OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_HMSM_STRICT,&err); //延时10ms,用来低优先级的任务调度
}
}
/*
*brief按键处理函数
*/
static void Keyprocess_task (void *p_arg)
{
OS_ERR err;
uint8_t *key_val;
OS_MSG_SIZE msg_size;
printf("进入按键处理任务\n");
while(1)
{
key_val = OSQPend (&Key_Msg, 0, OS_OPT_PEND_BLOCKING, &msg_size, 0,&err);
switch (*key_val)
{
case 1:
{
LED_BLU_TOGGLE;
break ;
}
case 2:
{
LED_RED_TOGGLE;
break ;
}
default :
{
printf("进入默认情况%d\n",*key_val);
break;
}
}
OSTimeDlyHMSM(0,0,0,100,OS_OPT_TIME_HMSM_STRICT,&err); //延时10ms
}
}
void tmr1_callback(void *p_tmr, void *p_arg)
{
static uint16_t exu_time; /******************次数必须用静态变量,静态变量申明时自动初始化为0,每再次执行回调函数时仍然可以保存上次的值*******************/
OS_ERR err;
exu_time ++;
printf("进入回调函数\n");
OSQPost (&Data_Msg, (uint16_t *)&exu_time , 2, OS_OPT_POST_FIFO, &err);/*当消息队列慢时则将定时器停止,由于向消息队列发送次数数据与请求消息队列的数据同时在进行,所以应该发送速度大于请求速度,定时器才会停止*/
if(err != OS_ERR_NONE)
{
OSTmrStop ((OS_TMR *)&tmr1,
(OS_OPT ) OS_OPT_TMR_NONE,
(void *)0,
(OS_ERR *)&err);
printf("定时器1停止\n");
}
}
static void msgdis_task (void *p_arg)
{
OS_ERR err;
uint8_t *receive_data;
OS_MSG_SIZE msg_size;
while(1)
{
receive_data = OSQPend (&Data_Msg, 0, OS_OPT_PEND_BLOCKING, &msg_size, 0,&err);
LCD_SetColors(RED,BLACK);
sprintf(dispBuff,"定时器1运行次数%d ",*receive_data);
LCD_ClearLine(LINE(1)); /* 清除单行文字 */
ILI9341_DispStringLine_EN_CH(LINE(1),dispBuff);
OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_HMSM_STRICT,&err); /*延时1s,由于定时器周期50ms这里延时1s才能保证可以消息队列慢来停止定时器*/
}
}
oid Check_msg_q(void) /*检测消息队列剩余容量*/
{
uint8_t max_msg, remain_msg;
CPU_SR_ALLOC();
OS_CRITICAL_ENTER(); //进入临界区
max_msg = Data_Msg.MsgQ.NbrEntriesSize ;
sprintf(dispBuff,"max_msg = %d",max_msg);
LCD_SetColors(RED,BLACK);
LCD_ClearLine(LINE(2)); /* 清除单行文字 */
ILI9341_DispStringLine_EN_CH(LINE(2),dispBuff);
remain_msg = Data_Msg.MsgQ.NbrEntriesSize - Data_Msg.MsgQ.NbrEntries; /* 用总容量减去已经使用的容量 */
sprintf(dispBuff,"remain_msg = %d",remain_msg);
LCD_SetColors(RED,BLACK);
LCD_ClearLine(LINE(3)); /* 清除单行文字 */
ILI9341_DispStringLine_EN_CH(LINE(3),dispBuff);
OS_CRITICAL_EXIT(); //退出临界区
}
uCOSIII_消息队列-消息传递实验分析相关推荐
- Linux进程通信的四种方式——共享内存、信号量、无名管道、消息队列|实验、代码、分析、总结
Linux进程通信的四种方式--共享内存.信号量.无名管道.消息队列|实验.代码.分析.总结 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须 ...
- 消息队列NetMQ 原理分析2-IO线程和完成端口
目录 前言 介绍 目的 IO线程 初始化IO线程 Proactor 启动Procator线程轮询 处理socket IOObject 总结 前言 介绍 [NetMQ](https://github.c ...
- PHP消息队列用法实例分析
这篇文章主要介绍了PHP消息队列用法,结合实例形式分析了PHP消息队列用于Linux下进程间通信的相关技巧,需要的朋友可以参考下 该消息队列用于linux下,进程通信 队列状态信息:具体参考手册 转载 ...
- springboot使用redis实现消息队列功能,redis使用list和stream实现消息队列功能,redis实现消息队列的风险点分析
文章目录 写在前面 基于list的消息队列解决方案 使用list基本实现消息队列 阻塞式消费,避免性能损失 替换while(true) 实现消息幂等 保证消息可靠性 基于stream的消息队列解决方案 ...
- 消息队列通信实验报告总结
实验目的 1.了解什么是消息.消息队列2.掌握消息传送的机理 msgget 作用:创建消息队列 原型:int msgget(key_t key, int msgflag) 参数:key:键值 IPC_ ...
- 消息长度_nsq消息队列源码分析
nsq的源码比较简单,值得一读,特别是golang开发人员,下面重点介绍nsqd,nsqd是nsq的核心,其他的都是辅助工具,看完这篇文章希望你能对消息队列的原理和实现有一定的了解. nsqd是一个守 ...
- win7系统中的消息队列服务器,高手分析win7系统安装消息队列的详细
win7系统是计算机学员最喜欢使用的电脑系统,却有一些学员在操作过程中应该会面临对win7系统安装消息队列进行布置的情景.几乎所有的初学者计算机知识还很薄弱,关于win7系统安装消息队列的情况,仍旧一 ...
- 消息队列篇—详谈ActiveMQ消息队列模式的分析及使用
2019独角兽企业重金招聘Python工程师标准>>> 消息队列(Message Queue)是分布式系统中重要的组件,通用使用场景可以简单地描述为当不需要立即获得结果,但是并发量需 ...
- 高可用、可扩展、稳定和安全的消息队列ActiveMQ特点分析
ActiveMQ是Apache软件基金下的一个开源软件.是目前能力强劲.应用广泛的开源消息总线之一.它为企业消息传递提供高可用.出色性能.可扩展.稳定和安全保障.ActiveMQ的目标是在尽可能多的平 ...
最新文章
- 算法基础知识科普:8大搜索算法之红黑树(中)
- SSRS 2012 仪表 -- 关键绩效指标
- 一些当前 Node.js 中最流行 ES6 特性的 benchmark (V8 / Chakra)
- 移动水政执法通系统 安卓Android客户端
- 这个Python库助你发现网络图的社区结构
- 摄影专业学生,没有摄影棚,怎么练摄影?
- 项目总结一:情感分类项目(emojify)
- 微型计算机的字长不一定是字节的整数倍数,2015江苏省全国计算机等级考试二级VB笔试试卷及参考答案考试技巧重点...
- 密码学加解密实训(墨者学院摩斯密码第2题)
- Linux下安装anaconda及遇到的问题
- 单片机是什么?单片机编程怎么入门?
- 在黑客攻击之前软件安全检测是重点,软件安全检测机构怎么找?
- 大数取模运算Barrett reduction
- 工程项目成本费用明细表_这么简单?成本费用明细表这么填就对了
- LCD液晶屏的通讯模式
- python拨号_Python进行ADSL拨号
- java毕业设计——基于java+Eclipse的扫雷游戏设计与实现(毕业论文+程序源码)——扫雷游戏
- python脚本控制ios手机app_appium 下 python 脚本自动化测试iOS APP 实例
- Ribo-seq的下游分析方法1-ORFquant以及RiboQC
- Creo/ProE自定义零件外观库保存使用
热门文章
- 什么是ring buffer?
- 踏遍青山情未老 —— 九山顶重游记(三)
- 生物信息学入门 根据表达矩阵和差异表达基因列表制作差异表达矩阵
- python字符编码使用的是什么编码_不可不知的Python字符编码使用技巧(上)
- 启发主义——深入神经网络(Inceptionism: Going Deeper into Neural Networks)
- 计算机快捷保护设置,锁屏快捷键电脑,电脑锁屏快捷键设置
- 小米13怎么设置每年自动生日提醒?
- Vue根据word模板导出页面所需文档
- NLP系列——(4)文本表示
- 万能工具箱万能工具箱_角度工作箱简单指南