基于STM32F407的FreeRTOS学习笔记(6)

发布者:EnigmaticCharm最新更新时间:2024-04-12 来源: elecfans关键字:STM32F407  FreeRTOS  信号量 手机看文章 扫描二维码
随时随地手机看文章

信号量(Semaphore)也被称为信号灯。有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量(来自百度百科)


简而言之,信号量就是在全局中表示共享资源状态的量。例如一个停车场,其中的车位就是共享资源。每当有车辆进进出出的时候,门口门卫总会统计出入车辆的数量,这就是信号量,我们可以通过信号量来获公共资源的信息(空余车位、已用车位)


而二进制信号量顾名思义只有0和1,例如电话亭的使用情况,当有人的时候其他人就无法使用电话亭。只有当电话亭空余的时候才能使用电话亭,而电话亭的使用状态则是二进制信号,电话亭本身则是共享资源。


在原本的裸机开发中我们通常会使用大量的标记符号并且在main函数中不断轮询该标记,这样子代码的逻辑就会异常复杂,而二进制信号量则可以代替这样子的作用,当任务在继续时二值信号量返回0,任务空闲时二进制信号量返回1,可以完美的替代如下这些标志变量。

图片

FreeRTOS中我们通常也会使用一个任务来专门轮询信号量,获得信号量的状态,实现信号量的同步。


除此之外我们的程序通常会有一个公共缓存区作为共享资源,每一个资源都可以使用公共缓存区的数据,即可以从中读取数据也可以写入数据。这个公共缓存区就像是停车场,车位有限,而我们则是根据信号量来控制这个停车场是否能够继续停下车辆。

图片

在FreeRTOS的介绍中我们可以看到,而二进制信号量的可以看作只有一个项目的队列,用队列的空和满来代表信息。

图片

图片

导入我们关于信号量的头文件“semphr.h”

关于二进制信号量的API文档中,创建一个二进制信号量首先需要将相对应的宏,即configSUPPORT_DYNAMIC_ALLOCATION打开,接着创建一个SemaphoreHandle_t 的信号量句柄来接收该创建函数的返回值。


LED_SemaphoreHandler = xSemaphoreCreateBinary();  if(LED_SemaphoreHandler!=NULL)

  {    printf('Semaphore Create Successfullyrn');

  }


接着我们在启动函数中写上该函数。这样子我们编译并烧录进我们的单片机

图片

串口助手上成功显示我们创建二进制信号量的信息。


#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )    #define xSemaphoreCreateBinary()    xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )#endif


跳转之后发现,其实这个函数就是创建一个项目大小为1 的队列,因此二进制信号量的本质就是队列。

图片

在文档中找到获取信号量的函数,分别是xSemaphoreTake和xSemaphoreTakeFromISR,从名字中我们可以知道这两个函数分别是在普通函数与中断函数中获取信息量的。

图片

可以看到,用法还是非常的简单,返回值是pdTRUE和pdFALSE,是用来判断信号量是否有用,即队列是否有空余。其中的参数xTicksToWait则是用来设置等待时间,在等待时间内阻塞以试图获得信号量。

最后我们看看释放信号量的函数

图片

这个释放信号量,并不是说释放空间那种表示删除的意思,而是如最后表达的那样,发布信号量。简而言之其实也就是向队列中的项目发布数据。


所以正确的流程是:创建信号量,轮询检测信号量是否释放,释放信号量。


接下来检验一下我们的信号量。


我们先创建一个任务,轮询信号量并且一直等待信号量是否释放。如果检测到信号量则翻转LED


BaseType_t err;

  while(1)

  {

    if(LED_SemaphoreHandler!=NULL)

    {

      err = xSemaphoreTake(LED_SemaphoreHandler,portMAX_DELAY);//一直等待信号量

      if(err == pdTRUE)

      {

        HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);//LED翻转

      }

      else

      {

        printf('No Semaphorern');

      }      

    }

    vTaskDelay(10);

  }

接着编写按钮函数,如果按下按钮则释放一个信号量。


if(key==2)

    {

      if(LED_SemaphoreHandler!=NULL)

      {

        err = xSemaphoreGive(LED_SemaphoreHandler);

        printf('Give Semaphore Successrn');

      }

      else

      {

        printf('Give Semaphore Failrn');

      }

    }


关键字:STM32F407  FreeRTOS  信号量 引用地址:基于STM32F407的FreeRTOS学习笔记(6)

上一篇:小白都看得懂的STM32的DMA知识
下一篇:基于STM32F407的FreeRTOS学习笔记(3)

推荐阅读最新更新时间:2026-03-24 18:27

基于STM32F407FreeRTOS学习笔记(7)
本期在二进制信号量的基础上介绍计数信号量 01基本介绍 01.什么是计数信号量 计数信号量顾名思义是用来计数的信号量,相比于二进制信号量,计数信号量的并不只有两种状态。用官方的开发者文档中的话来说,计数信号量可以看作长度大于1的队列,我们并不关心其中的内容而是关系队列是否为空。 关于队列的公众号可以参考这篇文章。 02.如何创建计数信号量 官方的参考文档中提供了两种创建方式(动态和静态)我们使用动态创建方式。调用xSemaphoreCreateCounting函数 其中包含了两个参数,一个是最大计数量还有一个是初始计数量。 创建一个SemaphoreHandler_t类型的句柄变量用以接收返回值。 03.释放和获取信号
[单片机]
基于<font color='red'>STM32F407</font>的<font color='red'>FreeRTOS</font>学习笔记(7)
基于STM32F407FreeRTOS学习笔记(2)
上一期配置完FreeRTOS的环境后,这一期记录自己关于任务创建的学习过程。 官方的API手册中有这些函数,xTaskCreate和xTaskCreateStatic分别是利用动态方法和静态方法创建任务。(动态和静态的区别之后再研究)vTaskDelete是删除任务,因为freeRTOS的任务内存空间存储在堆区,所以很像C语言的动态内存分配,任务使用和结束我们都应该创建和删除这些任务防止占用过多空间。 xTaskCreate的函数模型如下,参数内容总共有六项:任务函数的函数指针,任务函数的名称,任务函数所需堆栈空间,任务函数的类型,任务函数的优先级,以及任务函数的函数句柄 vTaskDelete的函数模型如下,参数内容为函
[单片机]
基于<font color='red'>STM32F407</font>的<font color='red'>FreeRTOS</font>学习笔记(2)
基于STM32F407FreeRTOS学习笔记(4)
CPU工作的时候,各个任务运行会占用CPU的资源,在Windows系统中我们可以通过任务管理器来看各任务(进程)占用系统资源的情况。 那么,FreeRTOS怎么实现这个功能呢? 我们翻阅FreeRTOS官网,查询API文档,在内核控制函数部分找到了相关的函数。 文档指出实现运行时间功能需要配置外设定时器,即32板载定时器,计时器频率应为滴答计时器(1ms)的至少10倍。 传入参数为pcWriteBUffer,其实是一个char类型的数组用以存储相关信息。 我们现在工程上调用这个函数。 char informationbuff ; void Get_info(void * pvParameters) {
[单片机]
基于<font color='red'>STM32F407</font>的<font color='red'>FreeRTOS</font>学习笔记(4)
linux驱动学习(3)--同步、信号量和自旋锁
在驱动程序中,当多个线程同时访问相同的资源时(驱动程序中的全局变量是一种典型的共享资源) ,可能会引发“竞态” ,因此我们必须对共享资源进行并发控制。Linux内核中解决并发控制的最常用方法是自旋锁与信号量(绝大多数时候作为互斥锁使用) 。 自旋锁与信号量“类似而不类” ,类似说的是它们功能上的相似性, “不类”指代它们在本质和实现机理上完全不一样,不属于一类。 自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环查看是否该自旋锁的保持者已经释放了锁, “自旋”就是“在原地打转” 。而信号量则引起调用者睡眠,它把进程从运行队列上拖出去,除非获得锁。这就是它们的“不类” 。 但是,无论是信号量,还
[单片机]
μC/OS-III对信号量的改进
引言 μC/OS是一个基于优先级调度的可剥夺型实时多任务内核。在多任务的实时内核中,信号量是常用的机制,可以用来实现对共享资源的访问、任务之间的通信和同步,以及任务和中断的同步等功能。μC/OS—II中提供了等待和释放信号量等最基本的服务,而在μC/OS—III中,对信号量的使用增加了一些可选的模式,如非阻塞等待、释放但不进行任务调度等,提高了使用的灵活性。更重要的是,在μC/OS—III中还新增了任务内嵌的信号量,用户程序无需建立信号量便可和任务直接通信,比普通信号量更加简单高效。本文将分析对比μC/OS—II和μC/OS—III中信号量内部结构的差异以及μC/OS—III新增的特性。 1 μC/OS—II中信号量内部结构 在μ
[嵌入式]
逻辑分析仪为I2C信号量测提供完整方案
I2C 汇流排在电子产品中,很常见的一种汇流排,它的好处就是只需要两条线,就可以并联很多 IC 进行控制。但因为多装置(Device) 及开路集极(Open drain)的架构,常使I2C 汇流排除错工作变得困难. 本文将提出一些实际的应用案例,并使用逻辑分析仪(Logic Analyzer)之各项功能,来协助排除问题。 使用转态储存进行长时间资料纪录 在I2C汇流排讯号发生异常时,常无法明确的知道是哪个装置出错。因此,无法用设定触发的方式来做问题点的定位。使用者多半会考虑先把所有的波形都撷取回来再慢慢分析。但逻辑分析仪基本是以采样的方式撷取讯号,不管讯号有没有改变,都会随着采样撷取动作的进行,而不断地消耗记忆体。而转态储存(
[测试测量]
逻辑分析仪为I2C<font color='red'>信号量</font>测提供完整方案
使用MicroPython开发STM32F407的CAN总线
首先烧录 .dfu 固件到你自己的开发板上,之后把串口 0 的两个引脚上拉。 // A9 is used for USB VBUS detect, and A10 is used for USB_FS_ID. 不然连接电脑后不会识别。 然后就可以尝试使用 CAN 总线了。我这里使用的是 CAN2(PB12 - CAN2_RX, PB13- CAN2_TX)。发送器使用 TJA1050,据说 1050 配合 STM32 使用的时候 1050 的供电需要使用 5V。 代码也很简单。三行就能发送出去了。默认的波特率是 28K。 from pyb import CAN can = CAN(2, CAN.NORMAL)can.sen
[单片机]
UCOSII在STM32F407上的移植
1、ucosii移植准备工作 1.1准备基础工程: 移植的时候需要一个基础工程,为了方便起见我们就选取跑马灯实验,作为ucossii移植的基础工程。 1.2Ucossii源码: 1)Micrium官网下载 2)开发板光盘自带 2、Ucossii移植步骤 1)step1 在基础工程文件夹中先建立UCOSII文件夹,然后在基础工程中UCOSII下建立相应的文件夹:CONFIG、CORE和PORT。 2)step2 向core文件夹中添加文件, 3)step3 向CONFIG文件夹中添加文件, 4)step4 向PORT文件件中添加文件, 5)step5 将Ucosii源码添加到工程中,打开工程,选择 新建三个分组:
[单片机]
UCOSII在<font color='red'>STM32F407</font>上的移植
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved