感知节点@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() { }

浙公网安备 33010602011771号