ESP32 FreeRTOS信号量

本文介绍了如何在NodeMCU32V1.3开发板上利用Arduino环境和FreeRTOS操作系统,实现通过按钮中断触发信号量,进而控制LED灯翻转的功能。代码中定义了两个任务,TaskKey负责初始化按钮和信号量,TaskAct则等待信号量并切换LED状态。当按钮被按下时,中断服务函数ButtonISR释放信号量,TaskAct在设定的时间内接收到信号量后翻转LED状态。
摘要由CSDN通过智能技术生成

开发板:NodeMCU 32 V1.3
开发板引脚图:
在这里插入图片描述

开发环境:Arduino,https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
实现功能:
(1)任务1初始化按钮,设置按钮中断,最后删除自身任务;
(2)任务2接收信号量,如果在一定时间内接收到信号量,则翻转LED灯;这个时间由函数xSemaphoreTake的第二个参数决定,该函数原型为:BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );,其中xTicksToWait可以通过宏pdMS_TO_TICKS()将毫秒转成滴答数ticks;
(3)setup:对led,串口等一些外设的初始化,创建信号量,创建freertos任务;

Arduino代码为:

#include <Arduino.h>
/*
 * 开发板:NodeMCU 32 v1.3
 * setup():初始化串口,创建freertos任务,创建信号量
 * 任务Task1:初始化按钮,添加中断等,最后删除自身任务
 * ButtonISR:按钮触发中断服务函数,在ISR中释放信号量
 * 任务Task2:等待接收信号量,翻转LED
 */
#if CONFIG_FREERTOS_UNICORE
#define ARDUINO_RUNNING_CORE 0
#else
#define ARDUINO_RUNNING_CORE 1
#endif

#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif

#define LONG_TIME 0xffff
#define buttonPin 0  // Nodemcu-32 BUTTON

volatile byte state = LOW;   //LED初始状态为低电平

// define two tasks for Blink & AnalogRead
void TaskKey( void *pvParameters );
void TaskAct( void *pvParameters );
// 声明信号量句柄
SemaphoreHandle_t xSemaphore;

// the setup function runs once when you press reset or power the board
void setup() {
  pinMode(LED_BUILTIN, OUTPUT); // 设置LED
 
  Serial.begin(115200); // 设置串口
  
  // Now set up two tasks to run independently.
  xTaskCreatePinnedToCore(
    TaskKey
    ,  "TaskKey"   // A name just for humans
    ,  2048  // This stack size can be checked & adjusted by reading the Stack Highwater
    ,  NULL
    ,  2  // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
    ,  NULL 
    ,  ARDUINO_RUNNING_CORE);

  xTaskCreatePinnedToCore(
    TaskAct
    ,  "TaskAct"
    ,  2048  // Stack size
    ,  NULL
    ,  1  // Priority
    ,  NULL 
    ,  ARDUINO_RUNNING_CORE);
  // Now the task scheduler, which takes over control of scheduling individual tasks, is automatically started.
}

void loop()
{
  // Empty. Things are done in Tasks.
}

/*---------------------- Tasks ---------------------*/

void TaskKey(void *pvParameters)  // This is a task.
{
  (void) pvParameters;
  Serial.println(">>> Start TaskKey!");
  
  // 创建信号量
  xSemaphore = xSemaphoreCreateBinary();
  
  pinMode(buttonPin, INPUT);
  //设置中断
  attachInterrupt(digitalPinToInterrupt(buttonPin), ButtonISR, RISING);

  // 删除此任务
  vTaskDelete(NULL);
}

// 按钮中断函数
void ButtonISR()
{
  BaseType_t send;
  static BaseType_t xHigherPriorityTaskWoken;
  xHigherPriorityTaskWoken = pdFALSE;
  Serial.println("Button clicked!");
  // 释放信号量
  send = xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken);
  if (send==pdTRUE) Serial.println("Release semaphore successfully!");
  else Serial.println("Fialed to release semaphore!");
}
// 
void TaskAct(void *pvParameters)  // This is a task.
{
  (void) pvParameters;
  Serial.println(">>> Start TaskAct!");
  BaseType_t rec;
  BaseType_t msToWait = 1000; // 信号量接收等待时间
  TickType_t ticks;
  for (;;)
  {
    //函数原型:BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
    rec = xSemaphoreTake(xSemaphore, pdMS_TO_TICKS(msToWait));//pdMS_TO_TICKS将ms转成对应的滴答数
    if (rec==pdTRUE) {
      Serial.println("Receive semaphore successfully!");
      state = !state;
      digitalWrite(LED_BUILTIN, state);
    }
    else {
      ticks = pdMS_TO_TICKS(msToWait);
      Serial.printf("Fialed to receive semaphore after waiting %d ticks!\n", ticks);
    }
    vTaskDelay(15);  // one tick delay (15ms) in between reads for stability
  }
}

结果如下
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于ESP32FreeRTOS教程,你可以参考以下步骤: 1. 首先,确保你已经安装了ESP32的开发环境,包括ESP-IDF(ESP32 IoT Development Framework)和相应的工具链。 2. 了解FreeRTOS的基本概念和特性。FreeRTOS是一个用于嵌入式系统的开源实时操作系统,它提供了任务管理、时间管理、内存管理等功能,可以帮助你更好地组织和管理ESP32上的任务。 3. 创建一个FreeRTOS任务。在ESP-IDF中,你可以使用FreeRTOS API创建和管理任务。你可以定义任务函数,并使用xTaskCreate函数创建一个任务。例如,你可以创建一个LED闪烁的任务,任务函数中通过控制GPIO实现LED的闪烁。 4. 理解任务优先级和调度。FreeRTOS通过任务优先级来确定任务的执行顺序。较高优先级的任务将在较低优先级的任务之前执行。你可以使用vTaskPrioritySet函数设置任务的优先级,并通过vTaskDelay函数实现任务之间的时间延迟。 5. 学习任务通信和同步机制。在多任务系统中,任务之间需要进行通信和同步。FreeRTOS提供了多种机制来实现这些功能,例如队列、信号量、事件组等。你可以根据具体的需求选择合适的机制来实现任务之间的数据传递和同步操作。 6. 调试和测试。在开发过程中,你可能会遇到一些问题,例如任务死锁、内存泄漏等。ESP-IDF提供了一些调试工具和功能来帮助你定位和解决这些问题,例如FreeRTOS的跟踪功能和内存泄漏检测工具。 希望以上步骤对你有所帮助!如果你需要更详细的教程或有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值