#define KEY_1_PIN 4
#define KEY_2_PIN 5
#define KEY_3_PIN 6
#define LED_PIN 40
#define KEY1_EVENT 1
#define KEY2_EVENT 2
#define KEY3_EVENT 4
EventGroupHandle_t key_event; // 按键事件组
volatile TickType_t keyDeounce = 0; // 按下按钮的时间
TimerHandle_t flash_timer = NULL; // 闪烁用的定时器
// 定时器回调函数
void vTimerCallback( TimerHandle_t xTimer ){
digitalWrite(LED_PIN, !digitalRead(LED_PIN));
}
// 按键时间处理函数
void key_event_task_entry(void *params){
printf("安检服务程序启动...\n");
EventBits_t uxBits;
uint16_t period=0; // 闪烁间隔时间
while(1){
uxBits= xEventGroupWaitBits(key_event, // 事件组句柄
KEY1_EVENT | KEY2_EVENT | KEY3_EVENT, // 等待事件
pdTRUE, // 退出后清空所有位
pdFALSE, // 任何一位到达都触发
portMAX_DELAY); // 无限期等待(50天)
if(uxBits>0 && ((xTaskGetTickCount() - keyDeounce) < 200)){
// 如果不是超时
switch(uxBits){
case KEY1_EVENT:
period = 1000;
break;
case KEY2_EVENT:
period = 500;
break;
case KEY3_EVENT:
// 暂停或恢复闪烁
if(flash_timer !=NULL){
if(xTimerIsTimerActive(flash_timer)){
// 启动中,暂停
if(xTimerStop(flash_timer, 0) == pdPASS){
printf("定时器停止成功!\n");
}else{
printf("错误,定时器无法停止!\n");
}
}else{
// 暂停中,启动
if(xTimerReset(flash_timer, 0) == pdPASS){ // Reset后会重启,暂停时间也会归零
printf("定时器重置成功!\n");
}else{
printf("错误,定时器无法重置!\n");
}
}
}else{
printf("还没有创建定时器!\n");
}
goto exit;
break;
}
if(flash_timer == NULL){
// 创建新的定时器
flash_timer = xTimerCreate("Timer_Flash", // 定时器的名字
period, // 调用间隔时间
pdTRUE, // 是否重复运行
NULL, // 定时器标识符,相当于参数
vTimerCallback);
if(xTimerStart(flash_timer,0) == pdPASS){ //立即启动
printf("开启闪烁,间隔 %d ms\n", period);
}else{
printf("错误,启动闪烁失败!");
}
}else{
// 如果定时器存在,则停止并删除定时器
if(xTimerIsTimerActive(flash_timer)){
// 定时器正在运行中,先停止,这一步可以不操作,直接删除效果也是一样的
if(xTimerStop(flash_timer, 0) != pdPASS){
printf("错误,定时器无法停止!\n");
}
}
if(xTimerDelete(flash_timer,0) == pdPASS){ // 立即删除
flash_timer = NULL;
printf("停止闪烁!\n");
digitalWrite(LED_PIN, LOW);
}else{
printf("错误,定时器无法删除!\n");
}
}
exit:
delay(500);
xEventGroupGetBits(key_event); // 去抖动
}
}
}
// 中断按键
void IRAM_ATTR KEY1_ISR(){
keyDeounce = xTaskGetTickCountFromISR(); // 记录下按下的时间,用于放抖动,正式开发中不要这样写,有Bug
xEventGroupSetBitsFromISR(key_event, KEY1_EVENT, NULL);
}
void IRAM_ATTR KEY2_ISR(){
keyDeounce = xTaskGetTickCountFromISR(); // 记录下按下的时间,用于放抖动,正式开发中不要这样写,有Bug
xEventGroupSetBitsFromISR(key_event, KEY2_EVENT, NULL);
}
void IRAM_ATTR KEY3_ISR(){
keyDeounce = xTaskGetTickCountFromISR(); // 记录下按下的时间,用于放抖动,正式开发中不要这样写,有Bug
xEventGroupSetBitsFromISR(key_event, KEY3_EVENT, NULL);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println("Hello, ESP32-S3!");
// 初始化LED
pinMode(LED_PIN, OUTPUT);
// 初始化事件组
key_event = xEventGroupCreate();
// 安装中断
pinMode(KEY_1_PIN, INPUT_PULLUP);
pinMode(KEY_2_PIN, INPUT_PULLUP);
pinMode(KEY_3_PIN, INPUT_PULLUP);
attachInterrupt(KEY_1_PIN, KEY1_ISR, FALLING);
attachInterrupt(KEY_2_PIN, KEY2_ISR, FALLING);
attachInterrupt(KEY_3_PIN, KEY3_ISR, FALLING);
// 启动按键服务线程
xTaskCreate(key_event_task_entry, "KEY_SERVICE", 10240, NULL, 1, NULL);
vTaskDelete(NULL);
}
void loop() {
}
esp:0
esp:1
esp:2
esp:3
esp:4
esp:5
esp:6
esp:7
esp:8
esp:9
esp:10
esp:11
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:20
esp:21
esp:35
esp:36
esp:37
esp:38
esp:39
esp:40
esp:41
esp:42
esp:45
esp:46
esp:47
esp:48
esp:3V3.1
esp:3V3.2
esp:RST
esp:5V
esp:GND.1
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:GND.4
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
led1:A
led1:C
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r