uCOSii信号量的作用
uCOSii中信号量的作用:
在创建信号量时,Sem_Event=OSSemCreate(1)用于分时复用共享资源;
Sem_Event=OSSemCreate(0)用于中断和任务间同步或任务之间的同步。
具体在使用时,需要灵活运用。在访问共享资源时,我喜欢用互斥信号量,爱好不同而已。
一、uCOSii信号量用于对共享资源的保护
1、举例如下:
任务1每隔1小时,将DATA1数据保存到EEPROM。
任务2每隔2小时,将DATA2数据保存到EEPROM。
可见,任务1和任务2都要使用公共资源“写EEPROM”。为了防止使用冲突,我们通过发送信号量和接收信号量来分时操作“写EEPROM”,保证写入正确。
当然也可以放在一个任务里去做,为了了解怎么使用共享资源,这里使用信号量来实现。
2、实现方法:
1)、声明事件指针
OS_EVENT *Sem_Event;//定义一个事件指针
2)、任务1
//函数功能:任务1每隔1小时,将DATA1数据保存到EEPROM。
void SaveDATA1_Task(void *pdata)
{
u16 SaveDATA1_Cnt;
u8 Sem_Err;
while(1)
{
OSTimeDlyHMSM(0,0,0,1000);//延时1秒
SaveDATA1_Cnt++;
if(SaveDATA1_Cnt >3600)//1小时时间到,保存DATA1
{
OSSemPend(Sem_Event,0,&Sem_Err);//等待一个信号量,实现资源保护
EEPROM_U8_Data_Write(DATA1, DATA1_address);
OSSemPost(Sem_Event);//发出一个信号量
SaveDATA1_Cnt =0;
}
}
}
3)、任务2
//函数功能:任务2每隔2小时,将DATA2数据保存到EEPROM。
void SaveDATA2_Task(void *pdata)
{
u16 SaveDATA2_Cnt;
u8 Sem_Err;
while(1)
{
OSTimeDlyHMSM(0,0,0,1000);//延时1秒
SaveDATA2_Cnt++;
if(SaveDATA2_Cnt >7200)//2小时时间到,保存DATA2
{
OSSemPend(Sem_Event,0,&Sem_Err);//等待一个信号量,实现资源保护
EEPROM_U8_Data_Write(DATA2, DATA2_address);
OSSemPost(Sem_Event);//发出一个信号量
SaveDATA2_Cnt =0;
}
}
}
4)、启动任务
void Start_Task(void *pdata)
{
OS_CPU_SR cpu_sr=0;
OS_ENTER_CRITICAL();
//进入临界区(无法被中断打断),需要定义cpu_sr变量
Sem_Event=OSSemCreate(1);
//创建信号量Sem_Event,设置计数器初始值设置为1,即发送了一个信号量。
OSTaskCreate(
SaveDATA1_Task,/* 函数指针*/
(void *)0,/* 建立任务时,传递的参数*/
(OS_STK*)&SaveDATA1_Task_STACK[SaveDATA1_Task_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/
SaveDATA1_Task_PRIORITY/* 任务优先级*/
);
OSTaskCreate(
SaveDATA2_Task,/* 函数指针*/
(void *)0,/* 建立任务时,传递的参数*/
(OS_STK*)&SaveDATA2_Task_STACK[SaveDATA2_Task_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/
SaveDATA2_Task_PRIORITY/* 任务优先级*/
);
OSTaskDel(OS_PRIO_SELF); //删除自己
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
}
二、uCOSii使用信号量实现中断和任务之间的同步
1、举例如下:
串口接收一组配置参数,然后将该参数需要保存到EEPROM中。显然,我们不能在中断中写EPPROM,这样会导致串口中断执行时间太长。因此需要分成两个部分实现,一个是串口接收,一个是负责保存参数,同时还要干其他事情。
有人会在某个任务中扫描串口,若收完配置信息立即保存,不用搞这个信号量也实现,实现方法千万种。这里使用信号量实现中断和任务之间的同步,完成中断和任务之间无缝隙对接。
2、实现方法:
1)、声明事件指针
OS_EVENT *Sem_Event;//定义一个事件指针
2)中断
uint8_t UART4HeadFlag;
uint8_t UART4_in; //UART4接收缓冲区的输入下标;
#define UART4_RCV_buffer_Size 100
//定义UART4接收缓冲区的长度100;
uint8_t UART4_RCV_buffer[UART4_RCV_buffer_Size];
//用来存放硬件串口接收到的数据;
//(ID=04661219C1677461)
//函数功能:USART4中断服务函数
void UART4_IRQHandler(void)
{
unsigned char temp;
(void)temp;//不让temp产生警告
if(USART_GetITStatus(UART4, USART_IT_RXNE) != RESET)
{
temp=USART_ReceiveData(UART4); //从UART4串口读取一个字节;
if(temp==’(’&& UART4HeadFlag==0)
{
UART4_in =0;
UART4HeadFlag=1;
}
if(UART4HeadFlag==1)
{
UART4_RCV_buffer[UART4_in]=temp;
UART4_in++;
}
if(temp==’)’&& UART4HeadFlag==1)
{
UART4_in =0;
UART4HeadFlag=0;//接收完成
OSSemPost(Sem_Event);//发出一个信号量
}
}
if(USART_GetFlagStatus(UART4,USART_FLAG_PE) != RESET)
{
USART_ReceiveData(UART4);//读串口
USART_ClearFlag(UART4, USART_FLAG_PE);
}
if(USART_GetFlagStatus(UART4,USART_FLAG_ORE) != RESET)
{
USART_ReceiveData(UART4);//读串口
USART_ClearFlag(UART4,USART_FLAG_ORE); //清除溢出中断
}
if(USART_GetFlagStatus(UART4,USART_FLAG_FE) != RESET)
{
USART_ReceiveData(UART4);//读串口
USART_ClearFlag(UART4,USART_FLAG_FE);
}
}
3)、任务1
void Task1(void *pdata)
{
u8 Sem_Err;
while(1)
{
OSSemPend(Sem_Event,0,&Sem_Err);//等待一个信号量,实现无缝对接
{
Save_String_To_EEPROM(UART4_RCV_buffer,UART4_in,ID_address);
}
}
}
void LED1_Task(void *pdata)
{
while(1)
{
LED1=!LED1;//信号有效
OSTimeDlyHMSM(0,0,0,500);//500毫秒闪烁1次
}
}
4)、启动任务
void Start_Task(void *pdata)
{
OS_CPU_SR cpu_sr=0;
OS_ENTER_CRITICAL();
//进入临界区(无法被中断打断),需要定义cpu_sr变量
Sem_Event=OSSemCreate(0);
//创建信号量Sem_Event,设置计数器初始值设置为0,即不发送一个信号量
OSTaskCreate(
Task1,/* 函数指针*/
(void *)0,/* 建立任务时,传递的参数*/
(OS_STK*)&Task1_STACK[Task1_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/
Task1_PRIORITY/* 任务优先级*/
);
OSTaskCreate(
LED1_Task,/* 函数指针*/
(void *)0,/* 建立任务时,传递的参数*/
(OS_STK*)&LED1_TASK_STACK[LED1_TASK_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/
LED1_TASK_PRIORITY/* 任务优先级*/
);
OSTaskDel(OS_PRIO_SELF); //删除自己
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
}
三、uCOSii使用信号量实现任务和任务之间的同步
1、举例如下:
任务1为负责按键触发
任务2负责点灯。
任务1中的按键KEY按下,任务2负责点灯ED1开灯关灯。
使用信号量实现任务与任务之间的同步,完成任务与任务之间无缝隙对接。
2、实现方法:
1)、声明事件指针
OS_EVENT *Sem_Event;//定义一个事件指针
2)、任务1
//函数功能:任务1负责按键触发。
void Key_Task(void *pdata)
{
u8 Sem_Err;
while(1)
{
if(KEY)OSSemPost(Sem_Event);//发出一个信号量
LED0=!LED0;
OSTimeDlyHMSM(0,0,0,500);//500毫秒闪烁1次
}
}
3)、任务2
void LED_Task(void *pdata)
{
u8 Sem_Err;
while(1)
{
OSSemPend(Sem_Event,0,&Sem_Err);//等待一个信号量,实现无缝对接
LED1=!LED1;//信号有效
}
}
4)、启动任务
void Start_Task(void *pdata)
{
OS_CPU_SR cpu_sr=0;
OS_ENTER_CRITICAL();
//进入临界区(无法被中断打断),需要定义cpu_sr变量
Sem_Event=OSSemCreate(0);
//创建信号量Sem_Event,设置计数器初始值设置为0,即不发送一个信号量
OSTaskCreate(
LED_Task,/* 函数指针*/
(void *)0,/* 建立任务时,传递的参数*/
(OS_STK*)&LED_Task_STACK[LED_Task_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/
LED_Task_PRIORITY/* 任务优先级*/
);
OSTaskCreate(
Key_Task,/* 函数指针*/
(void *)0,/* 建立任务时,传递的参数*/
(OS_STK*)&KEY_TASK_STACK[KEY_TASK_STACK_SIZE-1],
/* 指向堆栈任务栈顶的指针*/
KEY_TASK_PRIORITY/* 任务优先级*/
);
OSTaskDel(OS_PRIO_SELF); //删除自己
OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
}

相关文章:
uCOSii信号量的作用
uCOSii中信号量的作用: 在创建信号量时,Sem_EventOSSemCreate(1)用于分时复用共享资源; Sem_EventOSSemCreate(0)用于中断和任务间同步或任务之间的同步。 具体在使用时,需要灵活运用。在访问共享资源时,我喜欢用互…...
Android 13 版本变更总览
Android 13 总览 https://developer.android.google.cn/about/versions/13?hlzh-cn 文章基于官方资料上提取 Android 13 功能和变更列表 https://developer.android.google.cn/about/versions/13/summary?hlzh-cn 行为变更:所有应用 https://developer.andr…...
QT 设计ROS GUI界面订阅和发布话题
QT 设计ROS GUI界面订阅和发布话题 主要参考下面的博客 ROS项目开发实战(三)——使用QT进行ROS的GUI界面设计(详细教程附代码!!!) Qt ROS 相关配置请看上一篇博客 首先建立工作空间和功能包&a…...
pandas数据预处理
pandas数据预处理 pandas及其数据结构pandas简介Series数据结构及其创建DataFrame数据结构及其创建 利用pandas导入导出数据导入外部数据导入数据文件 导出外部数据导出数据文件 数据概览及预处理数据概览分析利用DataFrame的常用属性利用DataFrame的常用方法 数据清洗缺失值处…...
Jupyter Notebook如何导入导出文件
目录 0.系统:windows 1.打开 Jupyter Notebook 2.Jupyter Notebook导入文件 3.Jupyter Notebook导出文件 0.系统:windows 1.打开 Jupyter Notebook 1)下载【Anaconda】后,直接点击【Jupyter Notebook】即可在网页打开 Jupyte…...
Linux:/dev/tty、/dev/tty0 和 /dev/console 之间的区别
在Linux操作系统中,/dev/tty、/dev/tty0和/dev/console是三个特殊的设备文件,它们在终端控制和输入/输出过程中扮演着重要的角色。尽管它们看起来很相似,但实际上它们之间存在一些重要的区别。本文将详细介绍这三个设备文件之间的区别以及它们…...
Linux 上安装 PostgreSQL——Ubuntu
打开 PostgreSQL 官网 PostgreSQL: The worlds most advanced open source database,点击菜单栏上的 Download ,可以看到这里包含了很多平台的安装包,包括 Linux、Windows、Mac OS等 。 Linux 我们可以看到支持 Ubuntu 和 Red Hat 等各个平台…...
合并两个有序链表(java)
leetcode 21题:合并两个有序链表 题目描述解题思路:链表的其它题型。 题目描述 leetcode21题:合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例: 输入&…...
KEYSIGHT是德DSOX4034A 示波器 350 MHz
KEYSIGHT是德DSOX4034A 示波器 350 MHz,是德4000 X 系列拥有一系列引以为傲的配置,包括采用了电容触摸屏技术的 12.1 英寸显示屏、InfiniiScan 区域触摸触发、100 万波形/秒捕获率、MegaZoom IV 智能存储器技术和标配分段存储器。 是德DSO-X4034A 主要特…...
局域网技术
共享信道的分配技术是局域网的核心技术,而这一技术又与网络的拓扑结构和传输介质有关。 拓扑结构: 1.总线型拓扑: 总线一种多点广播介质,所有的站点通过接口硬件连接到总线上。 传输介质主要是同轴电缆(基带和宽带…...
Pixhawk无人机-ArduPilot 软件SITL仿真模拟飞行(SITL+MAVProxy)
1 引言 本人是先看了多个博客实现了:在ubuntu下建立完整的ardupilot开发环境。 该文是基于搭建完编译环境后,也就是搭建好ardupilot的仿真环境实现的。 在文章: 《Pixhawk无人机扩展教程(5)—SITL仿真模拟飞行:开发环境搭建》.中指出&#…...
vue实现深拷贝的方法
在 vue中,深拷贝是一个很有用的功能,在不改变原来对象状态的情况下,进行对象的复制。 但要实现深拷贝,需要两个对象具有相同的属性。如果两个对象不同,深拷贝也不能实现。 1.我们将变量A的属性赋给变量B,但…...
LAMP架构
文章目录 LAMP架构一.简述各组件的主要作用如下: 二.过程展示1.编译安装Apache httpd服务(1)关闭防火墙,将安装Apache所需软件包传到/opt目录下(2)安装环境依赖包(3)配置软件模块(4)编译及安装(5)优化配置文件路径,并把httpd服务的可执行程序…...
javascript基础七:说说你对Javascript中作用域的理解?
一、作用域 作用域,即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合 换句话说,作用域决定了代码区块中变量和其他资源的可见性 举个粟子 function myFunction(){let name小爱同学 } undef…...
chatgpt赋能python:Python变量赋值
Python 变量赋值 在 Python 中,我们可以使用多种符号来给变量赋值。本文将介绍这些符号以及它们在编程中的应用。 等号() 在 Python 中,我们最常用的符号是等号(),它可以将一个值赋给一个变量…...
SAP-QM-物料主数据-质量管理视图字段解析
过账到质检库存:要勾选,否则收货后库存不进入质检库存HU检验:收货到启用HU管理的库位时产生检验批,例如某个成品物料是收货到C002库位,该库位启用了HU管理,那么此处要勾选。但是如果勾选了,却收…...
【Netty】一行简单的writeAndFlush都做了哪些事(十八)
文章目录 前言一、源码分析1.1 ctx.writeAndFlush 的逻辑1.2 writeAndFlush 源码1.3 ChannelOutBoundBuff 类1.4 addMessage 方法1.5 addFlush 方法1.6 AbstractNioByteChannel 类 总结 前言 回顾Netty系列文章: Netty 概述(一)Netty 架构设…...
STM32U575 DMA配置
起个摘要,后期维护 1、DMA原理:参考:【STM32】DMA原理,配置步骤超详细,一文搞懂DMA_dma配置_~Old的博客-CSDN博客 2、STM32U575的DMA资源: (datasheet摘要) 3、UART的使用 4、I2…...
14-Vue3快速上手
目录 1.Vue3简介2. Vue3带来了什么2.1 性能的提升2.2 源码的升级2.3 拥抱TypeScript2.4 新的特性 1、海贼王,我当定了!——路飞 2、人,最重要的是“心”啊!——山治 3、如果放弃,我将终身遗憾。——路飞 4、人的梦想是…...
Docker registry 搭建
1、安装 docker 环境 参考:https://mp.csdn.net/mp_blog/creation/editor/104673841 2、准备 registry 镜像 机器有外网访问权限,直接 docker pull registry 通过 docker images 查看本地镜像 3、启动 registry docker run -d -p 5000:5000 --rest…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
《Docker》架构
文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器,docker,镜像,k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
Linux 下 DMA 内存映射浅析
序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存,但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程,可以参考这篇文章,我觉得写的非常…...
海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》
近日,嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》,海云安高敏捷信创白盒(SCAP)成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天,网络安全已成为企业生存与发展的核心基石,为了解…...
