开发板: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
}
}
结果如下