单片机
返回首页

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

2024-04-02 来源:elecfans

在上一期内容中我们简单的介绍了任务通知的几个函数以及简单的使用了任务通知来实现两个信号之间的通信。


本期我们将利用任务通知来模拟三种方式的任务间通信。


信号量

在我们介绍信号量的文章中介绍过,信号分为二进制信号量和计数信号量。

接着我们使用任务通知来模拟这两项功能。

二进制信号量可以看作长度为1的队列,我们不关心其值为多少,只关心它的状态。

图片

图片

在直达任务通知中我们可以用xTaskNotifyGive来模拟二进制信号量的释放以及ulTaskNotifyTake()来模拟二进制信号量的读取。

在ulTaskNotifyTake()中需要注意的是,我们需要设置一个参数用来确定我们模拟的是二进制信号量还是计数信号量。

图片

image.png

代码测试


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

{

  while(1)

  {

    if(KEY_Scan(0)==1)

    {

      printf('Key_Pressrn');

      xTaskNotifyGive(High_Handler);//传入任务函数句柄,模拟信号量释放

    }

  }

    vTaskDelay(10);

}



void High_Task(void * pvParameters)

{

  BaseType_t err;

  while(1)

  {

    err = ulTaskNotifyTake(pdFALSE,10);//读取后清零,模拟二进制信号量

    if(err == pdTRUE)

    {

      printf('Recieve Message!rn');

    }

    vTaskDelay(10);

  }

}


模拟二进制信号量成功。

之后,我们将接收的函数中的pdFALSE修改为pdTRUE,这样子我们就可以模拟我们的计数信号量了。

这里就不作演示了,但是要注意的是,只用这样子的模拟二进制信号量也要注意优先级反转问题,关于优先级反转的问题可以参考公众号中的关于二进制信号量的文章。

事件组

合理的运用RTOS中的事件组可以很好的处理许多事件,在事件组的介绍中我们说过,我们常用的事件组可以做到24位事件位。而在直达任务通知中,我们也同样可以指定某些位的改变来实现事件组的效果。

图片

我们可以修改xTaskNotify中的eAction来将通知值作为事件组,修改特定位来实现事件位的效果。


代码测试


复制

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

{

  int i = 0; 

  while(1)

  {

    if(KEY_Scan(0)==1)

    {

      printf('Key_Press keynumber : 1rn');

      xTaskNotify( (TaskHandle_t) High_Handler,//目标任务句柄

                   (uint32_t) 0x04,//第二位 00000100

                   (eNotifyAction) eSetBits);//位设置模式,模拟事件组

    }

    if(KEY_Scan(0)==2)

    {

      printf('Key_Press keynumber : 2rn');

      xTaskNotify( (TaskHandle_t) High_Handler,//目标任务句柄

                   (uint32_t) 0x08,//第三位  00001000

                   (eNotifyAction) eSetBits);//位设置模式,模拟事件组

    }

  }

    vTaskDelay(10);

}



void High_Task(void * pvParameters)

{

  BaseType_t err;

  uint32_t number;//存放通知值

  uint32_t Value;  //模拟事件组

  while(1)

  {

     err =  xTaskNotifyWait( (uint32_t) 0x0000,//不清理

                             (uint32_t) 0xffff,//清理当前

                             (uint32_t*) &number,//接收任务值

                             (TickType_t) 10 );//等待事件

    Value = Value | number ; //获得事件位

    if((Value&(0x08+0x04)) == (0x08+0x04))

    {

      printf('KEY1 and KEY2 have Pressedrn'); 

      Value = 0;//事件组清零

    }

    vTaskDelay(10);

  }

}

图片

进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 家用电器遥控器

  • 12V 转 28V DC-DC 变换器(基于 LM2585)

  • 红外开关

  • DS1669数字电位器

  • HA1377 桥式放大器 BCL 电容 17W(汽车音频)

    相关电子头条文章