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

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

本期在二进制信号量的基础上介绍计数信号量


01基本介绍

图片

01.什么是计数信号量

计数信号量顾名思义是用来计数的信号量,相比于二进制信号量,计数信号量的并不只有两种状态。用官方的开发者文档中的话来说,计数信号量可以看作长度大于1的队列,我们并不关心其中的内容而是关系队列是否为空。

关于队列的公众号可以参考这篇文章。

02.如何创建计数信号量

图片

官方的参考文档中提供了两种创建方式(动态和静态)我们使用动态创建方式。调用xSemaphoreCreateCounting函数

其中包含了两个参数,一个是最大计数量还有一个是初始计数量。

创建一个SemaphoreHandler_t类型的句柄变量用以接收返回值。

03.释放和获取信号量

释放和获取信号量和上一期二进制信号量的释放和获取方式一样。均是调用

xSemaphoreGive释放信号量以及调用

xSemaphoreTake获取信号量。

但是计数信号量则多了一个可以调用的函数。

图片

调用这个函数我们就可以获得计数值啦。

02代码编写

1测试流程

我们做两个实验,首先是使用一个LED函数,函数每翻转一次就向计数信号量释放一次信号。

第二个函数轮询计数信号量,当计数信号量的数量比一半多时,使另一个LED也开始进行翻转并同样释放信号量。当计数信号量到达最大数时,关闭第二个灯的翻转。

2大体思路

第一个LED灯翻转,发送信号量。定义一个轮询函数用来时刻检测信号量状况,当信号量到达一定数量时恢复LED2任务的运行,当信号量满时清空信号量列表并挂起LED2

任务的挂起与恢复可以参考这期。


3代码编写


首先是任务启动函数,在这个函数中我们要创建一个计数信号量并且启动其他的相关任务函数。


void Start_LED(void * pvParameters)

{

  taskENTER_CRITICAL();                            


  LED_SemaphoreHandler = xSemaphoreCreateCounting(20,0);//最大计数20,初始0

  if(LED_SemaphoreHandler!=NULL)

  {

    printf('Semaphore Create Successfullyrn');

  }


  xTaskCreate((TaskFunction_t        )LED_TOG,//任务函数

              (char *                )'LED_TOG',//任务名称

              (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte

              (void*                 ) NULL,//无返回

              (UBaseType_t          ) 1,//优先级1

              (TaskHandle_t *        )&LED_TOG_Handler);//任务函数句柄


   xTaskCreate((TaskFunction_t        )LED_TOG2,//任务函数

              (char *                )'LED_TOG2',//任务名称

              (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte

              (void*                 ) NULL,//无返回

              (UBaseType_t          ) 2,//优先级1

              (TaskHandle_t *        )&LED_TOG2_Handler);//任务函数句柄


     xTaskCreate((TaskFunction_t        )CountTest,//任务函数

              (char *                )'GetCount',//任务名称

              (configSTACK_DEPTH_TYPE) 128,//堆栈空间128Byte

              (void*                 ) NULL,//无返回

              (UBaseType_t          ) 0,//优先级1

              (TaskHandle_t *        )&GetCount_Handler);//任务函数句柄


  taskEXIT_CRITICAL();

  vTaskSuspend(LED_TOG2_Handler);

  vTaskDelete(NULL);

}

其次LED函数的内容非常简单,检测信号量是否创建(指针不为空)如果指针不为空则翻转LED,并且释放信号量。(注意第二个LED的函数不释放信号量防止释放两次信号量)


void LED_TOG(void * pvParameters)//参数为 void * pvParameters

{


  while(1)

  {

    if(LED_SemaphoreHandler!=NULL)

    {

      HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9);

      xSemaphoreGive(LED_SemaphoreHandler);

    }


    vTaskDelay(500);//延迟500ms

  }

}



void LED_TOG2(void * pvParameters)//参数为 void * pvParameters

{

  while(1)

  {

    if(LED_SemaphoreHandler!=NULL)

    {

      HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);

    }

    vTaskDelay(500);

  }

}

在循环检测函数中,我们定义一个count来接收计数信号量的数量。接着当信号量大于10时我们恢复LED2函数的运行(可以多次恢复,只有一次效果)。


当信号量为20时,我们先暂停LED1函数的运行防止我们清空信号量的时候LED1又在释放信号量。之后通过不断的获取信号量来清空信号量,因为信号量本质就是队列,之后恢复他们的运行。


void CountTest(void * pvParameters)

{

  while(1)

  {

    BaseType_t count;

    if(LED_SemaphoreHandler!=NULL)

    {

      count = uxSemaphoreGetCount(LED_SemaphoreHandler);

      if(count >= 9 )

      {

        vTaskResume(LED_TOG2_Handler);//恢复函数2

      }

      if(count >= 20 )

      {

        vTaskSuspend(LED_TOG_Handler);//先挂起函数1

        while(count != 0)

        {

          xSemaphoreTake(LED_SemaphoreHandler,10);

          count = uxSemaphoreGetCount(LED_SemaphoreHandler);

        }


        vTaskResume(LED_TOG_Handler);//恢复函数1

        vTaskSuspend(LED_TOG2_Handler);//挂起函数2

      }


    }

    vTaskDelay(10);

  }

}


关键字:STM32F407  FreeRTOS 引用地址:基于STM32F407的FreeRTOS学习笔记(7)

上一篇:基于STM32F407的FreeRTOS学习笔记(10)
下一篇:详解STM32单片机GPIO的工作原理

推荐阅读最新更新时间:2024-11-03 03:07

6. Stm32f407 key中断方式示例
硬件平台: stm32f407ve 软件平台: win10 (OS Name: Microsoft Windows 10 Enterprise OS Version: 10.0.18363 N/A Build 18363) Keil5 5.26.2 HAL库版本: 2.14.0(目前下载的最新的) 中断:这个概念一般有点难以理解,但是又是一个非常重要的功能,基本所有的单片机(或者说处理器)都有中断。可见中断的重要性。51单片机都有5个中断源,这是我接触到的最简单的中断系统了。 打个比方,还是手机的那个例子,上次我说的是
[单片机]
6. <font color='red'>Stm32f407</font> key中断方式示例
STM32F407-外部中断
一.基本概念 STM32F4的每个IO都可以作为外部中断输入。 STM32F4的中断控制器支持22个外部中断/事件请求: EXTI线0~15:对应外部IO口的输入中断。 EXTI线16:连接到PVD输出。 EXTI线17:连接到RTC闹钟事件。 EXTI线18:连接到USB OTG FS唤醒事件。 EXTI线19:连接到以太网唤醒事件。 EXTI线20:连接到USB OTG HS(在FS中配置)唤醒事件。 EXTI线21:连接到RTC入侵和时间戳事件。 EXTI线22:连接到RTC唤醒事件。 每个外部中断线可以独立的配置触发方式(上升沿,下降沿或者双边沿触发),触发/屏蔽,专用的状态位。
[单片机]
STM32F407-外部中断
stm32f407的TIM1的中断和PWM
调试了多半天TIM1的中断和PWM,终于算是调通了。遇到了不少问题,也深入了解了TIM1的配置过程。代码如下: /************************************************************ Copyright (C), 2012-2022, yin. FileName: main.c Author: ycw Version : 1.0 Date: 2012.04.25 Description: TIM1 PWM NVIC Version: V1.0 Function List: TIM1 PWM NVIC History:
[单片机]
PlatformIO 创建 libopencm3 + FreeRTOS 项目
以下步骤基于常见的 Bluepill STM32F103C8T6, 也适用于其它 libopencm3 支持的MCU型号 方案一: 只复制需要的文件 在 PlatformIO 中, Board 选择 Bluepill F103C8, Framework 选择 libopencm3, 创建项目 在项目的lib下新建目录 FreeRTOS 解压缩最新的 FreeRTOS 复制 FreeRTOS/Source/ 目录下, 除 portable 目录以外其它全部文件和目录, 至 lib/FreeRTOS 下 复制 FreeRTOS/Source/portable/GCC/ARM_CM3 目录下所有文件(port.c, portmacr
[单片机]
stm32f407之DMA(操作寄存器)
八、DMA 直接内存访问(DMA)是用来以提供外设和内存、内存和内存之间的高速数据传输的。数据可以在没有任何CPU干预下通过的DMA进行传输。这使得CPU资源更倾重与其他操作。 DMA控制器基于一个复杂的总线矩阵架构,结合了功能强大的双AHB主总线架构与独立的FIFO,以优化系统带宽。 两个DMA控制器共有16个数据流(stream),每个数据流可以编程与规定的通道中的一个搭配。 DMA的工作模式 1. 单次传输 2. 多次传输(burst):把数据分成多次传输 DMA的工作模式 1. 循环模式:循环模式是可用来处理循环缓冲区和连续的数据流(如ADC扫描模式)。启此功能可以设置DMA_SxC
[单片机]
<font color='red'>stm32f407</font>之DMA(操作寄存器)
基于STM32F407平台实现FATFS读写大容量(128G)SD卡的心得
本人是沈阳大学的一名小白,之前,无论是STM32,还是FATFS,都是小白一个,甚至不理解那是什么东西,但是据说这种技术目前为止好像是读写大容量卡挺费劲,只能64G,就到头了,但是最近接到一个任务就是做一个数据记录仪而且要把这个东西做成128G的。废话不多说,直接来把。 首先你要知道FATFS是一个文件管理系统,看他的手册,分为应用层,底层驱动等等,但是对于我们嵌入式开发者来说,移植他,我们需要的是修改底层驱动!应用他给出的API实现自己的任务。修改底层驱动!应用他给出的API实现自己的任务。修改底层驱动!应用他给出的API实现自己的任务。 1、修改底层驱动 官网下载,需注意他的版本,如果你做32G ,64G, OK
[单片机]
STM32F407的定时器时钟频率
//实验的思路为对TIM3进行初始化后,进入死循环等到TIM3的溢出中断,当TIM3_CNT的值等于TIM3_ARR时, 就会产生TIM3的中断,进入中断处理函数;TIM3_CNT从0开始计数。 // 看一下时钟频率 根据时钟树得到TIM3挂载在APB1时钟上,APB1来自SYSCLK时钟,是来自PLLCLK,有HSE时钟经过分频-倍频-分频得到的; stm32F407中时钟HSE的频率为8M,在systemInit()中,先分频M=8;再倍频N=336;再分频P=2;得到SYSCLK的频率为168Hz,在使用定时器TIM时,需要进行分频,APB1的时钟频率为42Mhz,这里进行了4分频。
[单片机]
<font color='red'>STM32F407</font>的定时器时钟频率
rt-thread studio新建stm32f407工程
rt-thread studio新建stm32f407工程,使用的版本是:2.2.6,stm32f4的支持包版本为0.2.2。先不用0.2.3,因为使用0.2.3建立的模板编译会报错。。 按照模板新建工程,默认使用内部时钟,编译,正常,串口1输出正常。修改为外部晶振,按照要求修改了代码,如下: void system_clock_config(int target_freq_mhz) { #if false RCC_OscInitTypeDef RCC_OscInitStruct = { 0 }; RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 }; /** Configure the m
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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