当前位置: 首页 > news >正文

(学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验

写在前面:
由于时间的不足与学习的碎片化,写博客变得有些奢侈。
但是对于记录学习(忘了以后能快速复习)的渴望一天天变得强烈。
既然如此
不如以天为单位,以时间为顺序,仅仅将博客当做一个知识学习的目录,记录笔者认为最通俗、最有帮助的资料,并尽量总结几句话指明本质,以便于日后搜索起来更加容易。


标题的结构如下:“类型”:“知识点”——“简短的解释”
部分内容由于保密协议无法上传。


点击此处进入学习日记的总目录

2024.04.04:UCOSIII第三十二节:计数信号量实验

  • 四十六、UCOSIII:计数信号量实验
    • 1、实验设计
    • 2、信号量实验现象

四十六、UCOSIII:计数信号量实验

1、实验设计

计数型信号量实验是模拟停车场工作运行。在创建信号量的时候初始化5个可用的信号量,并且创建了两个任务:一个是获取信号量任务, 一个是释放信号量任务,两个任务独立运行,获取信号量任务是通过按下KEY1按键进行信号量的获取,模拟停车场停车操作, 其等待时间是0,在串口调试助手输出相应信息。

释放信号量任务则是信号量的释放,释放信号量任务也是通过按下KEY2按键进行信号量的释放,模拟停车场取车操作, 在串口调试助手输出相应信息,实验源码具体如下:

#include <includes.h>/*
********************************************************************
*                                   LOCAL DEFINES
*********************************************************************
*/OS_SEM SemOfKey;          //标志KEY1是否被按下的信号量/*
***************************************************************
*                                                 TCB
****************************************************************
*/static  OS_TCB   AppTaskStartTCB;                      //任务控制块
static  OS_TCB   AppTaskKey1TCB;
static  OS_TCB   AppTaskKey2TCB;/*
*****************************************************************
*                         STACKS
******************************************************************
*/static  CPU_STK  AppTaskStartStk[APP_TASK_START_STK_SIZE];       //任务栈
static  CPU_STK  AppTaskKey1Stk [ APP_TASK_KEY1_STK_SIZE ];
static  CPU_STK  AppTaskKey2Stk [ APP_TASK_KEY2_STK_SIZE ];/*
********************************************************************
*                        FUNCTION PROTOTYPES
***************************************************************
*/static  void  AppTaskStart  (void *p_arg);               //任务函数声明
static  void  AppTaskKey1  ( void * p_arg );
static  void  AppTaskKey2  ( 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);//计算没有应用任务(只有空闲任务)运行时 CPU 的(最大)
#endif//容量(决定OS_Stat_IdleCtrMax 的值,为后面计算 CPU使用率使用)。CPU_IntDisMeasMaxCurReset();//复位(清零)当前最大关中断时间/* 创建信号量 SemOfKey */OSSemCreate((OS_SEM      *)&SemOfKey,    //指向信号量变量的指针(CPU_CHAR    *)"SemOfKey",    //信号量的名字(OS_SEM_CTR   )5,             //表示现有资源数目(OS_ERR      *)&err);         //错误类型/* 创建 AppTaskKey1 任务 */OSTaskCreate((OS_TCB     *)&AppTaskKey1TCB,//任务控制块地址(CPU_CHAR   *)"App Task Key1",//任务名称(OS_TASK_PTR ) AppTaskKey1,//任务函数(void       *) 0,//传递给任务函数(形参p_arg)的实参(OS_PRIO     ) APP_TASK_KEY1_PRIO,//任务的优先级(CPU_STK    *)&AppTaskKey1Stk[0],//任务栈的基地址(CPU_STK_SIZE) APP_TASK_KEY1_STK_SIZE / 10,//任务栈空间剩下1/10时限制其增长(CPU_STK_SIZE) APP_TASK_KEY1_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);//返回错误类型/* 创建 AppTaskKey2 任务 */OSTaskCreate((OS_TCB     *)&AppTaskKey2TCB,//任务控制块地址(CPU_CHAR   *)"App Task Key2",//任务名称(OS_TASK_PTR ) AppTaskKey2,//任务函数(void       *) 0,//传递给任务函数(形参p_arg)的实参(OS_PRIO     ) APP_TASK_KEY2_PRIO,//任务的优先级(CPU_STK    *)&AppTaskKey2Stk[0],//任务栈的基地址(CPU_STK_SIZE) APP_TASK_KEY2_STK_SIZE / 10,//任务栈空间剩下1/10时限制其增长(CPU_STK_SIZE) APP_TASK_KEY2_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 );//删除起始任务本身,该任务不再运行}/*
********************************************************************
*                                          KEY1 TASK
*********************************************************************
*/
static  void  AppTaskKey1 ( void * p_arg )
{OS_ERR      err;OS_SEM_CTR  ctr;CPU_SR_ALLOC();//使用到临界段(在关/开中断时)时必须用到该宏,该宏声明和定义一个局部变//量,用于保存关中断前的 CPU 状态寄存器SR(临界段关中断只需保存SR),开中断时将该值还原。uint8_t ucKey1Press = 0;(void)p_arg;while (DEF_TRUE)//任务体{if ( Key_Scan ( macKEY1_GPIO_PORT, macKEY1_GPIO_PIN, 1, & ucKey1Press ) )//如果KEY1被按下{ctr = OSSemPend ((OS_SEM   *)&SemOfKey, //等待该信号量SemOfKey(OS_TICK   )0,//下面选择不等待,该参无效(OS_OPT    )OS_OPT_PEND_NON_BLOCKING,//如果没信号量可用不等待(CPU_TS   *)0,       //不获取时间戳(OS_ERR   *)&err);     //返回错误类型OS_CRITICAL_ENTER();                  //进入临界段if ( err == OS_ERR_NONE )printf ( "\r\nKEY1被按下:成功申请到停车位,剩下%d个停车位。\r\n", ctr );else if ( err == OS_ERR_PEND_WOULD_BLOCK )printf ( "\r\nKEY1被按下:不好意思,现在停车场已满,请等待!\r\n" );OS_CRITICAL_EXIT();}OSTimeDlyHMSM ( 0, 0, 0, 20, OS_OPT_TIME_DLY, & err );}}/*
************************************************************************
*                                          KEY2 TASK
***********************************************************************
*/
static  void  AppTaskKey2 ( void * p_arg )
{OS_ERR      err;OS_SEM_CTR  ctr;CPU_SR_ALLOC();//使用到临界段(在关/开中断时)时必须用到该宏,该宏声明和定义一个局部变//量,用于保存关中断前的 CPU 状态寄存器SR(临界段关中断只需保存SR)//,开中断时将该值还原。uint8_t ucKey2Press = 0;(void)p_arg;while (DEF_TRUE)//任务体{if ( Key_Scan ( macKEY2_GPIO_PORT, macKEY2_GPIO_PIN, 1, & ucKey2Press ) )//如果KEY2被按下{ctr = OSSemPost((OS_SEM  *)&SemOfKey,//发布SemOfKey(OS_OPT   )OS_OPT_POST_ALL,//发布给所有等待任务(OS_ERR  *)&err);//返回错误类型OS_CRITICAL_ENTER();//进入临界段printf ( "\r\nKEY2被按下:释放1个停车位,剩下%d个停车位。\r\n", ctr );OS_CRITICAL_EXIT();}OSTimeDlyHMSM ( 0, 0, 0, 20, OS_OPT_TIME_DLY, & err );//每20ms扫描一次}}

别忘了每次修改函数都要在app_cfg.h文件中修改 优先级的宏 和 栈的宏

*********************************************************************************************************
*                                            TASK PRIORITIES
*********************************************************************************************************
*/#define  APP_TASK_START_PRIO                        2            //任务优先级#define  APP_TASK_KEY1_PRIO                         3
#define  APP_TASK_KEY2_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_KEY1_STK_SIZE                     512 
#define  APP_TASK_KEY2_STK_SIZE                     512 

2、信号量实验现象

将程序编译好,用USB线连接计算机和开发板的USB接口, 用DAP仿真器把配套程序下载到野火STM32开发板, 在计算机上打开串口调试助手。
按下开发板的KEY1按键获取信号量模拟停车,按下KEY2按键释放信号量模拟取车;
在串口调试助手中可以看到运行结果,具体见图
在这里插入图片描述

相关文章:

  • 二、Docker部署Jenckins(详细步骤)
  • 软考--软件设计师(软件工程总结3)
  • 天眼护航 安全无界:天通哨兵PS02—电力巡检保护的智能利器
  • Redis主从集群-主从复制(通俗易懂)
  • electron入门教程
  • LeetCode 1365. 有多少小于当前数字的数字
  • fastjson list转json
  • 用TOMCAT部署web项目教程
  • JavaScript权威指南(第7版) 笔记 - 扩展操作符总结
  • 小林coding图解计算机网络|TCP篇06|如何理解TCP面向字节流协议、为什么UDP是面向报文的协议、如何解决TCP的粘包问题?
  • 律所如何做好内容运营,提升品牌影响力
  • 数据生成 | Matlab实现基于DE差分进化算法的数据生成
  • vue + koa + Sequelize + 阿里云部署 + 宝塔:宝塔数据库连接
  • OpenCV中的模块:三维重建-SFM(1)
  • 设计模式 --5观察者模式
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • Angular4 模板式表单用法以及验证
  • EOS是什么
  • git 常用命令
  • IDEA 插件开发入门教程
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • OpenStack安装流程(juno版)- 添加网络服务(neutron)- controller节点
  • Service Worker
  • vue数据传递--我有特殊的实现技巧
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 订阅Forge Viewer所有的事件
  • 服务器从安装到部署全过程(二)
  • 快速构建spring-cloud+sleuth+rabbit+ zipkin+es+kibana+grafana日志跟踪平台
  • 每天10道Java面试题,跟我走,offer有!
  • 面试总结JavaScript篇
  • 前端设计模式
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 深度解析利用ES6进行Promise封装总结
  • 使用API自动生成工具优化前端工作流
  • 小试R空间处理新库sf
  • 因为阿里,他们成了“杭漂”
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #{} 和 ${}区别
  • #HarmonyOS:Web组件的使用
  • (1)(1.13) SiK无线电高级配置(六)
  • (1)SpringCloud 整合Python
  • (C#)获取字符编码的类
  • (libusb) usb口自动刷新
  • (二)hibernate配置管理
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (四)图像的%2线性拉伸
  • (一)UDP基本编程步骤
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转)VC++中ondraw在什么时候调用的
  • (转)拼包函数及网络封包的异常处理(含代码)
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .bat批处理(九):替换带有等号=的字符串的子串
  • .net 8 发布了,试下微软最近强推的MAUI