(学习日记)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按键释放信号量模拟取车;
在串口调试助手中可以看到运行结果,具体见图
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/524283.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

激光雷达和相机的联合标定工具箱[cam_lidar_calibration]介绍

激光雷达和相机的联合标定工具箱[cam_lidar_calibration]介绍 写在前面安装过程调试过程标定成功可视化展示 写在前面 激光雷达和相机联合标定工具 论文地址&#xff1a;https://ieeexplore.ieee.org/stamp/stamp.jsp?tp&arnumber9564700 github地址: https://github.com…

设计方案:914-基于64路AD的DBF波束形成硬件

一、硬件概述 &#xff24;&#xff22;&#xff26;技术的实现全部是在数字域实现&#xff0c;然而天线阵列接收的信号经过多次混频后得到的中频信号是模拟信号&#xff0c;实现&#xff24;&#xff22;&#xff26;处理并充分发挥&#xff24;&#xff22;&…

[C++][算法基础]模拟堆(堆)

维护一个集合&#xff0c;初始时集合为空&#xff0c;支持如下几种操作&#xff1a; I x&#xff0c;插入一个数 x&#xff1b;PM&#xff0c;输出当前集合中的最小值&#xff1b;DM&#xff0c;删除当前集合中的最小值&#xff08;数据保证此时的最小值唯一&#xff09;&…

【LeetCode热题100】153. 寻找旋转排序数组中的最小值(二分)

一.题目要求 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后&#xff0c;得到输入数组。例如&#xff0c;原数组 nums [0,1,2,4,5,6,7] 在变化后可能得到&#xff1a; 若旋转 4 次&#xff0c;则可以得到 [4,5,6,7,0,1,2]若旋转 7…

Flutter应用发布前的关键iOS设备测试策略

大家好&#xff0c;我是咕噜铁蛋&#xff01;今天我想和大家分享一下关于Flutter应用在发布前&#xff0c;如何进行关键iOS设备测试的策略。随着移动应用的普及&#xff0c;Flutter作为一种跨平台的开发框架&#xff0c;越来越受到开发者的青睐。但是&#xff0c;跨平台也意味着…

10 Python进阶:MongoDB

MongoDb介绍 MongoDB是一个基于分布式架构的文档数据库&#xff0c;它使用JSON样式的数据存储&#xff0c;支持动态查询&#xff0c;完全索引。MongoDB是NoSQL数据库的一种&#xff0c;主要用于处理大型、半结构化或无结构化的数据。以下是MongoDB数据库的一些关键特点和优势&a…

蓝桥杯 历届真题 杨辉三角形【第十二届】【省赛】【C组】

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 思路&#xff1a; 由于我第一写没考虑到大数据的原因&#xff0c;直接判断导致只得了40分&#xff0c;下面是我的代码&#xff1a; #…

4.7 IO day6

1&#xff1a;有一个隧道&#xff0c;全长5公里&#xff0c;有2列火车&#xff0c;全长200米&#xff0c; 火车A时速 100公里每小时 火车B时速 50公里每小时 现在要求模拟火车反复通过隧道的场景(不可能2列火车都在隧道内运行) #include <stdio.h> #include <string.…

1、java语法入门(找工作版)

文章目录 一、Java简介二、Java常量与变量1、标识符2、关键字3、变量4、类的命名规则5、数据类型6、基本数据类型字面值7、变量的定义与初始化8、ASCII码和Unicode编码9、转义字符10、类型转换11、常量 三、Java运算符1、算术运算符2、赋值运算符3、关系运算符4、逻辑运算符5、…

C#/.NET/.NET Core推荐学习书籍(24年4月更新,已分类)

前言 古人云&#xff1a;“书中自有黄金屋&#xff0c;书中自有颜如玉”&#xff0c;说明了书籍的重要性。作为程序员&#xff0c;我们需要不断学习以提升自己的核心竞争力。以下是一些优秀的C#/.NET/.NET Core相关学习书籍&#xff08;包含了C#、.NET、.NET Core、Linq、EF/E…

瓦拉纳西(Varanasi)宗教重要性历史与文化旅游与经济社会生活环境挑战“赶due”赶due的特点包括:赶due的应对策略:陶行知生平简介教育实践与贡献

目录 瓦拉纳西&#xff08;Varanasi&#xff09; 宗教重要性 历史与文化 旅游与经济 社会生活 环境挑战 “赶due” 赶due的特点包括&#xff1a; 赶due的应对策略&#xff1a; 陶行知 生平简介 教育实践与贡献 教育思想 遗产与影响 1.澳洲限制半工半读&#xff…

SQL Sever 2008 安装教程

先从官网下载程序&#xff1a;下载地址 打开上述链接后&#xff0c;点击下载按钮。 就会跳出下面这个界面&#xff0c;如果你的电脑是64位的请选择下图中这两个程序。 下载完成后&#xff0c;在电脑磁盘中找到这两个文件&#xff0c;注意安装的顺序&#xff0c;先安装 SQLEXPR…

H5 点击图片翻转效果

需求 ☑ h5 实现点击图片得到的是放大的镜像图片&#xff08;不是放大镜效果 而是实现图片镜像对折&#xff0c;左右翻转&#xff09; ☑ 鼠标点击后原图消失/隐藏&#xff0c;在原来的位置上取而代之的是翻转后的图&#xff08;除了翻转之外不要改变其他的性质&#xff0c;比…

如何保证全部流量走代理

最近因为某些原因&#xff0c;需要做一些确保高匿的事情&#xff0c;便花时间做了一定的调研&#xff0c;至于是什么事情这里不便多说。 本文主要还是聊聊我看到的一些使用代理软件误区和确保流量全部走代理的方法&#xff0c;甚至也可以说是Proxifier的用户使用手册&#xff…

2024/4/1—力扣—栈的最小值

代码实现&#xff1a; typedef struct node {int val;struct node *next; } Node;typedef struct {struct node *top;int min; } MinStack;/** initialize your data structure here. */MinStack* minStackCreate() {MinStack *obj malloc(sizeof(*obj));obj->top NULL;ob…

Redis分布式锁误删情况说明

4.4 Redis分布式锁误删情况说明 逻辑说明&#xff1a; 持有锁的线程在锁的内部出现了阻塞&#xff0c;导致他的锁自动释放&#xff0c;这时其他线程&#xff0c;线程2来尝试获得锁&#xff0c;就拿到了这把锁&#xff0c;然后线程2在持有锁执行过程中&#xff0c;线程1反应过…

Open-GroundingDino和GroundingDino的推理流程实现

1、简单介绍 GroundingDino是一个多模态检测模型&#xff0c;可以输入文本提示输出视觉目标的位置&#xff0c;实现了文本和图像的匹配。相比较于一众的OVD算法&#xff0c;GroundingDino在文本处理上的灵活度高&#xff0c;因为大多OVD算法是采用clip文本编码器&#xff0c;这…

1.8.4 卷积神经网络近年来在结构设计上的主要发展和变迁——Inception-v2 和Inception-v3

1.8.4 卷积神经网络近年来在结构设计上的主要发展和变迁——Inception-v2 和Inception-v3 前情回顾&#xff1a; 1.8.1 卷积神经网络近年来在结构设计上的主要发展和变迁——AlexNet 1.8.2 卷积神经网络近年来在结构设计上的主要发展和变迁——VGGNet 1.8.3 卷积神经网络近年来…

C# Solidworks二次开发:获取唯一ID的API详解

大家好&#xff0c;今天要介绍的是关于solidworks中可以获取对象唯一ID的几种API&#xff0c;获取唯一ID的API有如下几种&#xff1a; &#xff08;1&#xff09;第一种是GetID Method (IComponent2)&#xff0c;其含义为获取每个组件的唯一ID。 下面是API中的使用例子&#x…

作为一个前端,在入职新公司如何快速安装好开发环境

由于电脑运行内存才16G有点卡&#xff0c;今天公司给我们换了32G内存&#xff0c;是直接整个主机都换了&#xff0c;环境自然得重新安装&#xff0c;在装的过程中&#xff0c;自己会有些心得体会&#xff0c;就是想着一个新人如何快速安装环境。 个人说一下我的思路&#xff1a…