感知节点@6@ ESP32+arduino+ 第四个程序FreeRTOS 上 LED灯显示 和 串口打印LED开关状态

思路:

两个任务:LED灯闪烁任务      串口打印LED开关状态切换

两个任务间有通信,这里使用队列传递信息

1)学习 FreeROTS任务间通过队列传递通信

https://www.bilibili.com/video/BV1uU4y117rn?spm_id_from=333.788.player.switch&vd_source=25818e6e97754951f67187083c89af5a

程序实例 https://wokwi.com/projects/332962439743144532

 
   程序:  消息队列
   公众号:孤独的二进制

   API:
    QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength,
                             UBaseType_t uxItemSize );

    BaseType_t xQueueSend(
                            QueueHandle_t xQueue,
                            const void * pvItemToQueue,
                            TickType_t xTicksToWait
                         );
    BaseType_t xQueueReceive(
                               QueueHandle_t xQueue,
                               void *pvBuffer,
                               TickType_t xTicksToWait
                            );

定义一个Queue

一个任务向Queue放入数据

另一个任务从Queue取数据

 

2)在arduino 中,定义一个结构体,表达 “LED开关状态切换” ,含一个字符串、一个整数,一个浮点数

// 定义结构体类型
typedef struct {
    char ledName[20];    // 字符串:存储消息名称(使用固定长度char数组)
    int state;          // 整数:0=关闭,1=开启
    float value;   // 浮点数:值
} qMsg;

3)定义队列

// 定义结构体类型
typedef struct {
    char ledName[20];    // 字符串:存储消息名称(使用固定长度char数组)
    int state;          // 整数:0=关闭,1=开启
    float value;   // 浮点数:值
} qMsg;

// 定义 队列
QueueHandle_t queueMsg = xQueueCreate(8, sizeof(qMsg));

4)编写 LED灯闪烁任务  函数,向Queue放入数据

/*
  程序: FREERTOS - 多任务点灯程序实例

*/

// 定义结构体类型
typedef struct {
    char msgName[20];    // 字符串:存储消息名称(使用固定长度char数组)
    int state;          // 整数:0=关闭,1=开启
    float value;   // 浮点数:值
} qMsg;

// 定义 队列
QueueHandle_t queueMsg = xQueueCreate(8, sizeof(qMsg));

//查看电路图,那个ESP32的引脚连接LED灯  图中看到是IO2
#define LED_BUILTIN 2  


void task1(void *pt) {
  //pinMode(23, OUTPUT);
  // 创建结构体实例并初始化
  qMsg LED_State  = {
    "Led state",  // 字符串初始化
    1,            // 初始状态:开启
    0.0           // 初始亮度
  };

  TickType_t timeOut = portMAX_DELAY;
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);

  while (1) {

      //TickType_t timeOut = 10;

      digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
      // 正确字符串赋值方式(使用strncpy防止溢出)
      strncpy(LED_State.msgName, "Led state", sizeof(LED_State.msgName)-1);
      LED_State.msgName[sizeof(LED_State.msgName)-1] = '\0'; // 确保终止符

      LED_State.state = 1;
      xQueueSend(queueMsg, &LED_State, timeOut); //if (xQueueSend(queueMsg, &msg, timeOut) != pdPASS) {};
      vTaskDelay(1000);//delay(1000);                      // wait for a second


      digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
      // 正确字符串赋值方式(使用strncpy防止溢出)
      strncpy(LED_State.msgName, "Led state", sizeof(LED_State.msgName)-1);
      LED_State.msgName[sizeof(LED_State.msgName)-1] = '\0'; // 确保终止符

      LED_State.state = 0;
      xQueueSend(queueMsg, &LED_State, timeOut); //if (xQueueSend(queueMsg, &msg, timeOut) != pdPASS) {};
      vTaskDelay(1000);//delay(1000);                      // wait for a second
  }
}

5)编写 LED灯闪烁任务  函数 ,从Queue取数据

/*
  程序: FREERTOS - 多任务点灯程序实例

  公众号:孤独的二进制
*/

// 定义结构体类型
typedef struct {
    char msgName[20];    // 字符串:存储消息名称(使用固定长度char数组)
    int state;          // 整数:0=关闭,1=开启
    float value;   // 浮点数:值
} qMsg;

// 定义 队列
QueueHandle_t queueMsg = xQueueCreate(8, sizeof(qMsg));

//查看电路图,那个ESP32的引脚连接LED灯  图中看到是IO2
#define LED_BUILTIN 2  


void task1(void *pt) {
  //pinMode(23, OUTPUT);
  // 创建结构体实例并初始化
  qMsg LED_State  = {
    "Led state",  // 字符串初始化
    1,            // 初始状态:开启
    0.0           // 初始亮度
  };

  TickType_t timeOut = portMAX_DELAY;
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);

  while (1) {

      //TickType_t timeOut = 10;

      digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
      // 正确字符串赋值方式(使用strncpy防止溢出)
      strncpy(LED_State.msgName, "Led state", sizeof(LED_State.msgName)-1);
      LED_State.msgName[sizeof(LED_State.msgName)-1] = '\0'; // 确保终止符

      LED_State.state = 1;
      xQueueSend(queueMsg, &LED_State, timeOut); //if (xQueueSend(queueMsg, &msg, timeOut) != pdPASS) {};
      vTaskDelay(1000);//delay(1000);                      // wait for a second


      digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
      // 正确字符串赋值方式(使用strncpy防止溢出)
      strncpy(LED_State.msgName, "Led state", sizeof(LED_State.msgName)-1);
      LED_State.msgName[sizeof(LED_State.msgName)-1] = '\0'; // 确保终止符

      LED_State.state = 0;
      xQueueSend(queueMsg, &LED_State, timeOut); //if (xQueueSend(queueMsg, &msg, timeOut) != pdPASS) {};
      vTaskDelay(1000);//delay(1000);                      // wait for a second
  }
}

void task2(void *pt) {
  //pinMode(21, OUTPUT);
    //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
  }
  // 创建结构体实例并初始化
  qMsg LED_State  = {
    "Led state",  // 字符串初始化
    1,            // 初始状态:开启
    0.0           // 初始亮度
  };
  // prints title with ending line break
  Serial.println("LED State ~ 1:ON 0:OFF");

  while (1) {
    TickType_t timeOut = 10;
    if (xQueueReceive(queueMsg,&LED_State, timeOut) == pdPASS) {

      Serial.print("LED Name: ");
      Serial.println(LED_State.msgName);
      Serial.print("State: ");
      Serial.println(LED_State.state);
      Serial.print("Brightness: ");
      Serial.println(LED_State.value);

    }
  }
}

6)完整代码,含在初始化阶段,创建FreeROTS的任务

/*
  程序: FREERTOS - 多任务点灯程序实例

  公众号:孤独的二进制
*/

// 定义结构体类型
typedef struct {
    char msgName[20];    // 字符串:存储消息名称(使用固定长度char数组)
    int state;          // 整数:0=关闭,1=开启
    float value;   // 浮点数:值
} qMsg;

// 定义 队列
QueueHandle_t queueMsg = xQueueCreate(8, sizeof(qMsg));

//查看电路图,那个ESP32的引脚连接LED灯  图中看到是IO2
#define LED_BUILTIN 2  


void task1(void *pt) {
  //pinMode(23, OUTPUT);
  // 创建结构体实例并初始化
  qMsg LED_State  = {
    "Led state",  // 字符串初始化
    1,            // 初始状态:开启
    0.0           // 初始亮度
  };

  TickType_t timeOut = portMAX_DELAY;
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);

  while (1) {

      //TickType_t timeOut = 10;

      digitalWrite(LED_BUILTIN, HIGH);  // turn the LED on (HIGH is the voltage level)
      // 正确字符串赋值方式(使用strncpy防止溢出)
      strncpy(LED_State.msgName, "Led state", sizeof(LED_State.msgName)-1);
      LED_State.msgName[sizeof(LED_State.msgName)-1] = '\0'; // 确保终止符

      LED_State.state = 1;
      xQueueSend(queueMsg, &LED_State, timeOut); //if (xQueueSend(queueMsg, &msg, timeOut) != pdPASS) {};
      vTaskDelay(1000);//delay(1000);                      // wait for a second


      digitalWrite(LED_BUILTIN, LOW);   // turn the LED off by making the voltage LOW
      // 正确字符串赋值方式(使用strncpy防止溢出)
      strncpy(LED_State.msgName, "Led state", sizeof(LED_State.msgName)-1);
      LED_State.msgName[sizeof(LED_State.msgName)-1] = '\0'; // 确保终止符

      LED_State.state = 0;
      xQueueSend(queueMsg, &LED_State, timeOut); //if (xQueueSend(queueMsg, &msg, timeOut) != pdPASS) {};
      vTaskDelay(1000);//delay(1000);                      // wait for a second
  }
}

void task2(void *pt) {
  //pinMode(21, OUTPUT);
    //Initialize serial and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ;  // wait for serial port to connect. Needed for native USB port only
  }
  // 创建结构体实例并初始化
  qMsg LED_State  = {
    "Led state",  // 字符串初始化
    1,            // 初始状态:开启
    0.0           // 初始亮度
  };
  // prints title with ending line break
  Serial.println("LED State ~ 1:ON 0:OFF");

  while (1) {
    TickType_t timeOut = 10;
    if (xQueueReceive(queueMsg,&LED_State, timeOut) == pdPASS) {

      Serial.print("LED Name: ");
      Serial.println(LED_State.msgName);
      Serial.print("State: ");
      Serial.println(LED_State.state);
      Serial.print("Brightness: ");
      Serial.println(LED_State.value);

    }
  }
}


void setup() {
  // Serial.begin(9600);
  // Serial.print("ESP32 Tick Period - ");
  // Serial.print(portTICK_PERIOD_MS);
  // Serial.println("ms");

  if (xTaskCreate(task1,
                  "Blink",
                  1024,
                  NULL,
                  1,
                  NULL) == pdPASS)
    Serial.println("Task1 Created.");

  if (xTaskCreate(task2,
                  "Uart",
                  1024,
                  NULL,
                  1,
                  NULL) == pdPASS)
    Serial.println("Task2 Created.");


}

void loop() {
}

 

posted @ 2025-10-15 22:40  辛河  阅读(26)  评论(0)    收藏  举报