前面做到了多任务点灯,今天用按键检测来控制LED灯的闪烁。
这里用到freertos的信号量来做控制:
/*
程序: Binary Semaphore 是一种信号机制
一个任务(生产者)发出信号。另外一个任务(消费者)接受信号
公众号:孤独的二进制
语法:
SemaphoreHandle_t xHandler; 创建Handler
xHandler = xSemaphoreCreateBinary(); 创建一个二进制信号量 返回NULL,或者handler
xSemaphoreGive(xHandler); 生产者+1
xSemaphoreTake(xHanlder, timeout); 消费者-1 返回pdPASS, 或者pdFAIL
二进制信号量可以想成就是一个整数 0 或者 1
Give就是+1
Take就是-1
Take的时候如果这个整数是0的话,就等待一直到timeout
*/
思路是:1个是周期任务闪灯,另一人任务是接收到信号量才产生灯的转换。如果不按按键就保持原来的状态,如果检测按键按下,测周期闪灯。
程序如下:
#include <Arduino.h>
#include <STM32FreeRTOS.h>
SemaphoreHandle_t xSemaLED = NULL;//创建信号量Handler
TickType_t timeOut = 1000; //用于获取信号的Timeout
typedef struct {
byte pin;
int delayTime;
} LEDFLASH;
void ledFlash(void *pt){
LEDFLASH *ptLedFlash = (LEDFLASH *)pt;
byte pin = ptLedFlash->pin;
int delayTime = ptLedFlash->delayTime;
pinMode(pin,OUTPUT);
while(1){
//Serial.println("led1 flash");
digitalWrite(pin,!digitalRead(pin));
vTaskDelay(delayTime);
}
}
void ledFlash2(void *pt){
byte pin = PC7;
int delayTime = 500;
pinMode(pin,OUTPUT);
while(1){
if(xSemaphoreTake(xSemaLED,timeOut) == pdTRUE)
{
digitalWrite(pin,!digitalRead(pin));
vTaskDelay(delayTime);
}
}
}
void readBtn(void *pt)
{
byte pin = PC13;
pinMode(pin, INPUT_PULLDOWN);
while(1)
{
if(digitalRead(pin) == HIGH){
xSemaphoreGive(xSemaLED);
vTaskDelay(120);
}
}
}
LEDFLASH led1,led2;
void setup() {
Serial.begin(115200);
led1.pin = PB7;
led1.delayTime = 200;
led2.pin = PC7;
led2.delayTime = 500;
TaskHandle_t myTask1,butTask;
xSemaLED = xSemaphoreCreateBinary(); //创建二进制信号量
if(xTaskCreate(ledFlash,
"FLASH LED",
1024,
(void *)&led1,
6,
NULL) == pdPASS)
Serial.println("led1,flash task Created.");
if (xTaskCreate(ledFlash2,
"Flash LED.",
1024,
NULL,
6,
NULL) == pdPASS)
Serial.println("led2 flash task Created.");
if (xTaskCreate(readBtn,
"Read Button",
1024,
NULL,
1,
&butTask)== pdPASS)
Serial.println("Create Read Button Semaphore.");
vTaskStartScheduler();
}
void loop() {
// put your main code here, to run repeatedly:
}
实验现象见视频。
2022-12-14 09.41拍摄的影片