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

发布时间:2024-04-12  

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


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);

  }

}


文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>