该门锁作为2023年我的毕业设计,没有怎么优化,漏洞比较多,可以参考,但不要全抄哦

功能描述

1、矩阵按键密码解锁
2、指纹解锁
3、点灯科技手机APP解锁
4、接入米家,唤醒小爱同学解锁

所需器材

1、AS608指纹模块(RX–>TX2,TX–>RX2)

2、ESP32单片机

3、12V升压模块

4、电磁锁

5、0.96寸OLED显示屏(4针)(P4–>SDA,P5–>SCL)

6、矩阵按键(P13,P12,P14,P27,P26,P25,P33,P32)

7、兼容3.3v驱动继电器模块

原理图

esp32 freertos使用手册_嵌入式硬件

电磁锁连接线路

esp32 freertos使用手册_嵌入式硬件_02


电磁锁接线图比较粗糙,仅供参考

*下面开始写代码 *

主文件

#include "fingerprint.h"

#include "keymat.h"

#include "text.h"

#include "task.h"

#include "blinke.h"


void setup() {
  //串口初始化
  Serial.begin(115200);
  
  while (!Serial);  // For Yun/Leo/Micro/Zero/...
  delay(100);
  Serial.println("\n\nAdafruit finger detect test");
  
  xMutexInventory = xSemaphoreCreateMutex();//创建互斥锁

  if (xMutexInventory == NULL) {
    printf("No Enough Ram, Unable to Create Semaphore.");
  } else {
    //创建指纹扫描任务                                                                任务暂停句柄
    xTaskCreatePinnedToCore(fingerPrintTask, "fingerPrint Task", 1024 * 4, NULL, 1, &finPrHandle, 1); //将该任务放在核心1上运行,核心0一般用于运行wifi

    //创建KEY任务
    xTaskCreatePinnedToCore(keyTask, "KEY Task", 1024 * 6, NULL, 1, NULL, 1); //将该任务放在核心1上运行,核心0一般用于运行wifi

    //创建KEY任务
    xTaskCreatePinnedToCore(blinkeTask, "Blinke Task", 1024 * 6, NULL, 1, NULL, 0); //将该任务放在核心1上运行,核心0一般用于运行wifi
    
  }


  vTaskDelete(NULL);
}

void loop() {

}

fingerprint.h

#ifndef _FINGERPRINT_H_
#define _FINGERPRINT_H_

#include <Adafruit_Fingerprint.h>

#include "task.h"

#include "lock.h"

#include "keymat.h"

#if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__)
// For UNO and others without hardware serial, we must use software serial...
// pin #2 is IN from sensor (GREEN wire)
// pin #3 is OUT from arduino  (WHITE wire)
// Set up the serial port to use softwareserial..
SoftwareSerial mySerial(2, 3);

#else
// On Leonardo/M0/etc, others with hardware serial, use hardware serial!
// #0 is green wire, #1 is white
#define mySerial Serial2

#endif

extern Adafruit_Fingerprint finger;

uint8_t getFingerprintID();//搜索并获取指纹ID

int getFingerprintIDez();//搜索并获取指纹ID,精简版

void fingerprint_init_correlaton();//指纹初始化后相关打印

void fingerPrintTask(void * pvParam);//指纹搜索任务

uint8_t getFingerprintEnroll(uint8_t id); //指纹注册

uint8_t deleteFingerprint(uint8_t id); //指纹删除

#endif

fingerprint.cpp

#include "fingerprint.h"

Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial);


uint8_t getFingerprintID() {//获取指纹ID
  uint8_t p = finger.getImage();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println("No finger detected");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK success!

  p = finger.image2Tz();
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK converted!
  p = finger.fingerSearch();
  if (p == FINGERPRINT_OK) {
    Serial.println("Found a print match!");//从flash找到了指纹
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_NOTFOUND) {
    Serial.println("Did not find a match");//没有从flash中找到指纹
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  // found a match!找到指纹后显示ID
  Serial.print("Found ID #"); Serial.print(finger.fingerID);
  Serial.print(" with confidence of "); Serial.println(finger.confidence);

  return finger.fingerID;
}

// returns -1 if failed, otherwise returns ID #
//查询指纹ID精简
int getFingerprintIDez() {
  uint8_t p = finger.getImage();
  if (p != FINGERPRINT_OK)  return -1;

  p = finger.image2Tz();
  if (p != FINGERPRINT_OK)  return -1;

  p = finger.fingerFastSearch();
  if (p != FINGERPRINT_OK)  return -1;

  // found a match!
  Serial.print("Found ID #"); Serial.print(finger.fingerID);
  Serial.print(" with confidence of "); Serial.println(finger.confidence);//匹配程度
  
  password_input_success();
  
  unlocking();

  oled_show(1,1,0);  
  return finger.fingerID;
}

void fingerprint_init_correlaton()//指纹初始化后相关打印
{
 if (finger.verifyPassword()) {
    Serial.println("Found fingerprint sensor!");
  } else {
    Serial.println("Did not find fingerprint sensor :(");
    while (1) { delay(1); }
  }

  Serial.println(F("Reading sensor parameters"));
  finger.getParameters();
  Serial.print(F("Status: 0x")); Serial.println(finger.status_reg, HEX);
  Serial.print(F("Sys ID: 0x")); Serial.println(finger.system_id, HEX);
  Serial.print(F("Capacity: ")); Serial.println(finger.capacity);
  Serial.print(F("Security level: ")); Serial.println(finger.security_level);
  Serial.print(F("Device address: ")); Serial.println(finger.device_addr, HEX);
  Serial.print(F("Packet len: ")); Serial.println(finger.packet_len);
  Serial.print(F("Baud rate: ")); Serial.println(finger.baud_rate);

  finger.getTemplateCount();

  if (finger.templateCount == 0) {
    Serial.print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example.");
  }
  else {
    Serial.println("Waiting for valid finger...");
      Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates");
  }
}

/*-------------------------------------------
作用:指纹注册
参数:
    id:将要注册的指纹id
-------------------------------------------*/
uint8_t getFingerprintEnroll(uint8_t id) {

  int p = -1;
  Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id);
  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.println(".");
      break;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      break;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      break;
    default:
      Serial.println("Unknown error");
      break;
    }
  }

  // OK success!
  fingerprint_press_show();

  p = finger.image2Tz(1);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  Serial.println("Remove finger");
  delay(2000);
  p = 0;
  while (p != FINGERPRINT_NOFINGER) {
    p = finger.getImage();
  }
  Serial.print("ID "); Serial.println(id);
  p = -1;
  
  Serial.println("Place same finger again");

  while (p != FINGERPRINT_OK) {
    p = finger.getImage();
    switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image taken");
      break;
    case FINGERPRINT_NOFINGER:
      Serial.print(".");
      break;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      break;
    case FINGERPRINT_IMAGEFAIL:
      Serial.println("Imaging error");
      break;
    default:
      Serial.println("Unknown error");
      break;
    }
  }

  // OK success!

  p = finger.image2Tz(2);
  switch (p) {
    case FINGERPRINT_OK:
      Serial.println("Image converted");
      break;
    case FINGERPRINT_IMAGEMESS:
      Serial.println("Image too messy");
      return p;
    case FINGERPRINT_PACKETRECIEVEERR:
      Serial.println("Communication error");
      return p;
    case FINGERPRINT_FEATUREFAIL:
      Serial.println("Could not find fingerprint features");
      return p;
    case FINGERPRINT_INVALIDIMAGE:
      Serial.println("Could not find fingerprint features");
      return p;
    default:
      Serial.println("Unknown error");
      return p;
  }

  // OK converted!
  Serial.print("Creating model for #");  Serial.println(id);

  p = finger.createModel();
  if (p == FINGERPRINT_OK) {
    Serial.println("Prints matched!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_ENROLLMISMATCH) {
    Serial.println("Fingerprints did not match");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  Serial.print("ID "); Serial.println(id);
  p = finger.storeModel(id);
  if (p == FINGERPRINT_OK) {
    Serial.println("Stored!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
    return p;
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println("Could not store in that location");
    return p;
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println("Error writing to flash");
    return p;
  } else {
    Serial.println("Unknown error");
    return p;
  }

  return true;
}


/*-----------------------------------------
作用:指纹数据删除
参数:
    id:需要删除的指纹id
-----------------------------------------*/
uint8_t deleteFingerprint(uint8_t id) 
{
  uint8_t p = -1;

  p = finger.deleteModel(id);

  if (p == FINGERPRINT_OK) {
    Serial.println("Deleted!");
  } else if (p == FINGERPRINT_PACKETRECIEVEERR) {
    Serial.println("Communication error");
  } else if (p == FINGERPRINT_BADLOCATION) {
    Serial.println("Could not delete in that location");
  } else if (p == FINGERPRINT_FLASHERR) {
    Serial.println("Error writing to flash");
  } else {
    Serial.print("Unknown error: 0x"); Serial.println(p, HEX);
  }

  return p;
}


/*指纹搜索任务*/
void fingerPrintTask(void * pvParam)
{
  //指纹串口初始化
  finger.begin(57600);
  vTaskDelay(5);
  fingerprint_init_correlaton();//相关显示

  int fingerPrintID = 0;
  
  while(1){
    //互斥锁上锁
    if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {
      
      fingerPrintID = getFingerprintIDez();//搜索指纹
    
      //互斥锁开锁
      xSemaphoreGive(xMutexInventory);
      vTaskDelay(100);
    }
  } 
}

text.h

#ifndef _TEXT_H_
#define _TEXT_H_

static const uint8_t text[][60] =  
//开(0) 锁(1) 管(2) 理(3) 员(4) 改(5) 密(6) 码(7) 录(8) 指(9) 纹(10) 删(11) 指(12) 纹(13)
{
  
  {0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x01,0x04,0x04,0x01,0x02,0x04,0x01,0x01,0x04,0xC1,0x00,0xF8,0x3F,0x00,0xF8,0x07,0x00,0x04,0x01,0x00,0x04,0x01,0x00,0x04,0x01,0x00,0x04,0x01,0x00,0xF8,0xFF,0x07,0xF8,0xFF,0x03,0x04,0x01,0x00,0x04,0x01,0x00,0x06,0x01,0x00,0x84,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00},/*"开",0*/
  {0x00,0x00,0x00,0x00,0x01,0x00,0xC0,0x08,0x00,0xB8,0x08,0x00,0x1E,0xFF,0x03,0x90,0x08,0x01,0x90,0x88,0x04,0x90,0x48,0x04,0x00,0x08,0x04,0xC4,0x7F,0x02,0x58,0x00,0x02,0x40,0x00,0x01,0x40,0xE0,0x00,0x7E,0x3F,0x00,0x40,0x80,0x00,0x50,0x00,0x01,0xCC,0x7F,0x01,0x40,0x00,0x02,0x00,0x00,0x06,0x00,0x00,0x00},/*"锁",1*/  
  {0x00,0x00,0x00,0x40,0x02,0x00,0x20,0x03,0x00,0x90,0x00,0x00,0x8E,0x00,0x00,0x88,0xFE,0x07,0xF0,0x4A,0x02,0x88,0x4A,0x02,0x88,0x4A,0x02,0xE8,0x4A,0x02,0xD0,0x4A,0x02,0x88,0x4A,0x02,0x8E,0x4A,0x02,0x88,0x5E,0x02,0xB0,0xC2,0x03,0x88,0x00,0x00,0x88,0x02,0x00,0x88,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"管",2*/
  {0x00,0x00,0x00,0x00,0x80,0x00,0x08,0x81,0x00,0x08,0x41,0x00,0xF0,0x7F,0x00,0x08,0x41,0x00,0x08,0x21,0x00,0x08,0x21,0x02,0x00,0x20,0x02,0xFC,0x27,0x02,0x44,0x22,0x02,0x44,0x22,0x02,0x44,0x22,0x02,0xF8,0xFF,0x03,0x44,0x22,0x02,0x44,0x22,0x02,0xFC,0x27,0x02,0x00,0x20,0x02,0x00,0x00,0x02,0x00,0x00,0x00},/*"理",3*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x04,0x80,0x3F,0x04,0xC2,0x00,0x02,0xFE,0x00,0x02,0xA2,0x00,0x01,0xA2,0xC0,0x00,0xA2,0x7E,0x00,0xA2,0x0E,0x00,0xA2,0x40,0x00,0xA2,0x40,0x00,0xA2,0x80,0x00,0xFE,0x80,0x01,0x80,0x3F,0x03,0x80,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"员",4*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xFF,0x03,0x08,0x01,0x01,0x08,0x01,0x01,0x08,0x81,0x00,0x08,0x81,0x00,0x08,0x41,0x04,0xF8,0x41,0x04,0x00,0x01,0x02,0xC0,0x00,0x02,0xB8,0x07,0x01,0x2E,0x98,0x00,0x20,0x60,0x00,0x20,0xF0,0x00,0xA0,0x8F,0x01,0x40,0x00,0x03,0x20,0x00,0x06,0x00,0x00,0x02,0x00,0x00,0x00},/*"改",5*/
  {0x00,0x00,0x00,0x00,0x10,0x00,0x30,0x10,0x00,0x08,0x12,0x00,0x88,0xC9,0x03,0x08,0x08,0x02,0xC8,0x0F,0x02,0x08,0x0C,0x02,0x10,0x0C,0x02,0xEE,0xFA,0x03,0x0C,0x29,0x02,0x88,0x09,0x02,0xC8,0x08,0x02,0x68,0x0E,0x02,0x08,0x00,0x02,0x88,0xC0,0x07,0x10,0x03,0x00,0x18,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"密",6*/
  {0x00,0x00,0x00,0x00,0x04,0x00,0x04,0x03,0x00,0xE4,0xFF,0x01,0x98,0x40,0x00,0x84,0x40,0x00,0x84,0xFF,0x00,0x06,0x00,0x00,0x04,0x00,0x00,0x02,0x22,0x00,0xFA,0x23,0x00,0x02,0x22,0x00,0x02,0x22,0x00,0x02,0x22,0x00,0x02,0x22,0x02,0xF2,0x23,0x06,0x0E,0x02,0x06,0x00,0xFE,0x01,0x00,0x02,0x00,0x00,0x00,0x00},/*"码",7*/
  {0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x80,0x01,0x80,0x80,0x00,0x82,0x82,0x00,0x82,0x4C,0x00,0x92,0x5C,0x00,0x92,0x20,0x02,0x92,0x20,0x02,0x12,0xFF,0x07,0x12,0xFF,0x01,0x92,0x0C,0x00,0x92,0x10,0x00,0x92,0x68,0x00,0xFE,0xC4,0x00,0x80,0x86,0x01,0x80,0x00,0x01,0xC0,0x00,0x03,0x80,0x00,0x01,0x00,0x00,0x00},/*"录",8*/
  {0x00,0x00,0x00,0x00,0x08,0x00,0x20,0x08,0x02,0x20,0x08,0x02,0x22,0x04,0x06,0xFC,0xFF,0x03,0x20,0x02,0x00,0x20,0x01,0x00,0x20,0x00,0x00,0xFE,0x04,0x06,0x24,0xFD,0x03,0x20,0x25,0x01,0x10,0x25,0x01,0x10,0x25,0x01,0x18,0x25,0x01,0x08,0x25,0x01,0x08,0xFD,0x07,0xE0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"指",9*/
  {0x00,0x00,0x00,0x80,0x00,0x01,0xC0,0x39,0x01,0xA0,0x9C,0x00,0x98,0x92,0x00,0x86,0x91,0x04,0xC0,0x50,0x04,0x60,0x48,0x02,0x10,0x00,0x02,0x10,0x00,0x01,0xE0,0x83,0x00,0x12,0xCC,0x00,0x1C,0x70,0x00,0x18,0xF8,0x00,0x10,0x87,0x01,0xE0,0x01,0x01,0x10,0x00,0x03,0x10,0x00,0x06,0x10,0x00,0x02,0x00,0x00,0x00},/*"纹",10*/
  {0x00,0x00,0x00,0x00,0x00,0x02,0x00,0xE1,0x01,0xFC,0x1F,0x01,0x04,0x01,0x01,0xFC,0xFF,0x01,0x04,0x01,0x02,0x00,0xE1,0x01,0xFC,0x1F,0x02,0x04,0x01,0x02,0x04,0x01,0x06,0xFC,0xFF,0x01,0x00,0x01,0x00,0x00,0x01,0x00,0xF8,0x3F,0x00,0x00,0x00,0x02,0x00,0x00,0x06,0xFE,0xFF,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"删",11*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x84,0x00,0x01,0x98,0xFF,0x01,0x00,0xC0,0x00,0x00,0x20,0x00,0x80,0x00,0x00,0x88,0x00,0x00,0xA8,0xFC,0x07,0xA8,0x4A,0x00,0xA8,0x4A,0x00,0xFE,0x4A,0x00,0xA8,0x4A,0x02,0xA8,0x4A,0x02,0xA8,0x4A,0x06,0xA8,0xFE,0x01,0x88,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00},/*"请",12*/
  {0x00,0x00,0x00,0x00,0x42,0x00,0xD0,0x43,0x00,0x38,0x22,0x00,0x14,0x22,0x00,0x90,0xFF,0x07,0x10,0x23,0x00,0x90,0x12,0x00,0x80,0xFF,0x07,0x40,0x29,0x00,0x70,0x29,0x02,0x98,0x29,0x06,0x86,0xFF,0x01,0x88,0x00,0x00,0x50,0xFC,0x02,0xA0,0x00,0x02,0x40,0x00,0x06,0xC0,0xFE,0x03,0x00,0x00,0x00,0x00,0x00,0x00},/*"输",13*/
  {0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0x02,0x18,0x00,0x02,0x0C,0x00,0x84,0x03,0x00,0xF8,0x00,0x00,0x60,0x00,0x00,0x80,0x03,0x00,0x00,0x0C,0x00,0x00,0x38,0x00,0x00,0x60,0x00,0x00,0xC0,0x00,0x00,0x80,0x01,0x00,0x80,0x01,0x00,0x00,0x00,0x00,0x00,0x00},/*"入",14*/
  {0x00,0x00,0x00,0x00,0x00,0x02,0x80,0x80,0x01,0x90,0x68,0x00,0xE8,0x28,0x02,0x8A,0x08,0x06,0x8C,0xFF,0x03,0xE8,0x28,0x00,0x98,0x48,0x04,0x88,0xC8,0x02,0x80,0x00,0x01,0x00,0xE0,0x00,0xFC,0x1F,0x00,0x84,0x00,0x00,0x84,0x00,0x00,0x04,0xFF,0x07,0x86,0x00,0x00,0x82,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00},/*"新",15*/
  {0x00,0x00,0x00,0x00,0x01,0x00,0xC0,0x08,0x00,0xB8,0x08,0x00,0x1E,0xFF,0x03,0x90,0x08,0x01,0x90,0x08,0x01,0x10,0x88,0x00,0x10,0x08,0x00,0x10,0x09,0x04,0x10,0xF9,0x07,0xFE,0x49,0x02,0x10,0x49,0x02,0x10,0x49,0x02,0xFE,0x49,0x02,0xFC,0x49,0x02,0x10,0xF9,0x03,0x10,0x01,0x00,0x00,0x01,0x00,0x00,0x00,0x00},/*"错",16*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x82,0x00,0x00,0x9C,0xFF,0x01,0x00,0xC0,0x00,0x00,0x60,0x04,0x00,0x10,0x04,0x00,0x09,0x02,0x7E,0x09,0x01,0x22,0x89,0x00,0x22,0x71,0x00,0x22,0x1E,0x00,0x22,0x31,0x00,0x22,0xC9,0x00,0x7E,0x89,0x01,0x32,0x09,0x03,0x00,0x09,0x06,0x00,0x00,0x02,0x00,0x00,0x00},/*"误",17*/
  {0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x03,0xE0,0xFF,0x00,0x20,0x02,0x00,0x20,0x02,0x00,0x20,0x82,0x00,0x20,0x82,0x01,0x20,0xFE,0x04,0x20,0x00,0x02,0x3E,0x00,0x01,0xFC,0x07,0x01,0x20,0xF8,0x00,0x22,0x60,0x00,0x24,0xB8,0x00,0x38,0x0E,0x01,0x20,0x03,0x03,0x20,0x00,0x02,0x00,0xC0,0x07,0x00,0x00,0x00},/*"成",18*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xC0,0x00,0x10,0x40,0x00,0x10,0x40,0x00,0xE0,0x3F,0x00,0x10,0x20,0x04,0x10,0x20,0x02,0x10,0x20,0x02,0x10,0x10,0x01,0x40,0xC0,0x00,0x40,0x70,0x00,0x82,0x1F,0x00,0x7E,0x00,0x02,0x40,0x00,0x02,0x40,0x00,0x06,0x40,0x80,0x03,0xC0,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"功",19*/
  {0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01,0x00,0xC0,0x00,0x00,0xF8,0xFF,0x07,0x06,0x00,0x00,0xE0,0xFF,0x00,0x20,0x00,0x04,0x40,0x00,0x04,0x20,0x92,0x04,0x18,0x92,0x02,0x16,0x49,0x02,0xAA,0x48,0x02,0xC8,0x24,0x01,0xC8,0x22,0x01,0x28,0x91,0x00,0x18,0x93,0x00,0x00,0x42,0x00,0x00,0x40,0x00,0x00,0x00,0x00},/*"修",20*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xFF,0x03,0x08,0x01,0x01,0x08,0x01,0x01,0x08,0x81,0x00,0x08,0x81,0x00,0x08,0x41,0x04,0xF8,0x41,0x04,0x00,0x01,0x02,0xC0,0x00,0x02,0xB8,0x07,0x01,0x2E,0x98,0x00,0x20,0x60,0x00,0x20,0xF0,0x00,0xA0,0x8F,0x01,0x40,0x00,0x03,0x20,0x00,0x06,0x00,0x00,0x02,0x00,0x00,0x00},/*"改",21*/
  {0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x01,0x00,0x80,0x00,0x00,0xF0,0xFF,0x07,0x1E,0x00,0x04,0x04,0x00,0x02,0x00,0x04,0x01,0xFC,0x85,0x00,0x84,0x44,0x00,0x84,0x34,0x00,0x84,0x08,0x00,0x04,0xFF,0x07,0x84,0x08,0x00,0x84,0x34,0x00,0x84,0x44,0x00,0xFC,0x84,0x00,0x00,0x04,0x01,0x00,0x04,0x01,0x00,0x00,0x00},/*"保",22*/
  {0x00,0x00,0x00,0x00,0x10,0x00,0x08,0x10,0x00,0x08,0x08,0x00,0x08,0x06,0x00,0x88,0xFF,0x07,0xC8,0x00,0x00,0x68,0x00,0x00,0x5C,0x10,0x00,0x4E,0x10,0x00,0x48,0x10,0x02,0x48,0x10,0x02,0x48,0xFE,0x07,0x48,0x16,0x00,0x48,0x11,0x00,0xC8,0x10,0x00,0xC8,0x10,0x00,0x08,0x10,0x00,0x00,0x10,0x00,0x00,0x00,0x00},/*"存",23*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x04,0x10,0x00,0xE4,0xFF,0x07,0x24,0x11,0x00,0x24,0x11,0x00,0x24,0x11,0x00,0x24,0x11,0x00,0xF8,0x1F,0x00,0x24,0x11,0x00,0x24,0x11,0x00,0x24,0x11,0x02,0x24,0x11,0x02,0x24,0x11,0x06,0xE4,0xFF,0x03,0x06,0x10,0x00,0x04,0x18,0x00,0x00,0x10,0x00,0x00,0x00,0x00},/*"再",24*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x00,0x08,0xF0,0x01,0x38,0x0E,0x00,0x80,0x01,0x04,0x60,0x04,0x02,0x00,0x02,0x02,0x80,0x01,0x01,0x60,0x80,0x00,0x3E,0x60,0x00,0x44,0x1F,0x00,0xA0,0x03,0x00,0x20,0x1C,0x00,0x20,0x60,0x00,0x20,0x81,0x01,0xE0,0x00,0x03,0x60,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x00},/*"次",25*/
  {0x00,0x00,0x00,0x00,0x00,0x02,0x20,0x00,0x01,0x20,0xF0,0x00,0xC2,0x0F,0x01,0x2C,0x01,0x01,0x38,0x01,0x03,0x20,0x81,0x03,0x20,0xFF,0x04,0x20,0x01,0x02,0x20,0x01,0x02,0xE0,0x03,0x01,0x3E,0x9C,0x00,0x20,0x60,0x00,0x20,0xF0,0x00,0xA0,0x8F,0x01,0xC0,0x00,0x03,0x20,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x00},/*"放",26*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0xF0,0xFF,0x07,0x08,0x01,0x00,0x08,0x01,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x06,0x00,0x08,0x0C,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"下",27*/
  {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x08,0x04,0x00,0x48,0x04,0x00,0x48,0x04,0x00,0x48,0x04,0x00,0x44,0x04,0x02,0x44,0x04,0x06,0xFC,0xFF,0x03,0x44,0x04,0x00,0x44,0x04,0x00,0x44,0x04,0x00,0x44,0x04,0x00,0x46,0x04,0x00,0x66,0x04,0x00,0x44,0x04,0x00,0x00,0x06,0x00,0x00,0x04,0x00,0x00,0x00,0x00},/*"手",28*/
};

#endif

keymat.h

#ifndef _KEYMAT_H_
#define _KEYMAT_H_

#include <Preferences.h>

#include "Adafruit_Keypad.h"

#include "task.h"

#include "text.h"

#include "SSD1306Wire.h"//oled头文件包含

#include "fingerprint.h"

#include "lock.h"

extern uint8_t getFingerprintEnroll(uint8_t id);
extern Adafruit_Keypad customKeypad;


//引脚初始化
void key_init(void);

//oled初始化
void oled_init(void);

/*菜单显示*/
void oled_show(uint8_t interface_control,uint8_t cursor,uint8_t input_sign);

//密码输入错误显示
void password_input_error(void);

//密码输入成功
void password_input_success(void);

//指纹ID输入错误显示 指纹保存数量1~20
void ID_input_error(void);

//指纹ID输入成功显示
void ID_input_success(void);

//指纹删除成功显示
void finger_delete_success(void);

//密码修改成功显示
void password_amend_success(void);

//按键输入显示
void input_show(uint8_t interface_control, uint8_t cursor, char *str);

//参数运算,用于光标计算
uint8_t cursor_operation_add(uint8_t interface_control,uint8_t cursor);
uint8_t cursor_operation_sub(uint8_t cursor);

//flash密码查询
bool flash_inquire(int password_flash_inquire);

//再次按下手指
void fingerprint_press_show(void);

//密码保存
void password_save(int password_flash_save);

//界面功能实现
bool interface_function_reailze(char *str_password,uint8_t interface_control,uint8_t cursor);

void keyTask(void * pvParam);//oled任务

extern void unlocking(void);//开锁

#endif

keymat.cpp

#include "keymat.h"

/*---------------------
      按键相关
---------------------*/
const byte ROWS = 4; // 行
const byte COLS = 4; // 列
//按键定义
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};

byte rowPins[ROWS] = {13, 12, 14, 27}; //引脚接口
byte colPins[COLS] = {26, 25, 33, 32}; //引脚接口

//initialize an instance of class NewKeypad
Adafruit_Keypad customKeypad = Adafruit_Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
//-----------------------
//-----------------------


/*------------------------ 
    设置oled屏幕的相关信息 
------------------------*/
const int I2C_ADDR = 0x3c;              // oled屏幕的I2c地址
#define SDA_PIN 4                       // SDA引脚,默认gpio4(D2)
#define SCL_PIN 5                       // SCL引脚,默认gpio5(D1)

/* 新建一个oled屏幕对象,需要输入IIC地址,SDA和SCL引脚号 */
SSD1306Wire oled(I2C_ADDR, SDA_PIN, SCL_PIN);
//-----------------------


//按键引脚初始化
void key_init(void)
{
  customKeypad.begin();//初始化
}

//oled初始化
void oled_init(void)
{
  oled.init();
  oled.flipScreenVertically();        // 设置屏幕翻转
  oled.setContrast(255);              // 设置屏幕亮度
  oled.clear(); 
  oled.display();       // 清除屏幕
}

/*------------------------------------------------------
作用:界面的显示
参数:
  interface_control:界面标志
  cursor:光标设置  
  input_sign: 为0界面显示,为1按键输入娴熟  
------------------------------------------------------*/
void oled_show(uint8_t interface_control,uint8_t cursor,uint8_t input_sign)
{
  
  oled.clear(); 
  if(interface_control == 1 && input_sign == 0){//显示第一个页面
      oled.drawFastImage(32,      10, 20, 20, text[0]);
      oled.drawFastImage(32+1*20, 10, 20, 20, text[1]);
      oled.drawFastImage(32,      30, 20, 20, text[2]);
      oled.drawFastImage(32+1*20, 30, 20, 20, text[3]);
      oled.drawFastImage(32+2*20, 30, 20, 20, text[4]);
      
      if(cursor == 1){
        oled.setFont(ArialMT_Plain_16);     // 设置字体
        oled.drawString(16, 10, ">");     // 将要显示的文字写入缓存 
      }
      if(cursor == 2){
        oled.setFont(ArialMT_Plain_16);     // 设置字体w
        oled.drawString(16, 30, ">");     // 将要显示的文字写入缓存
      }      
  }
  
  if(interface_control == 2 && input_sign == 0){//显示第2个页面
      oled.drawFastImage(32,      1, 20, 20, text[5]);
      oled.drawFastImage(32+1*20, 1, 20, 20, text[6]);
      oled.drawFastImage(32+2*20, 1, 20, 20, text[7]);
      
      oled.drawFastImage(32,      22, 20, 20, text[8]);
      oled.drawFastImage(32+1*20, 22, 20, 20, text[9]);
      oled.drawFastImage(32+2*20, 22, 20, 20, text[10]);

      oled.drawFastImage(32,      43, 20, 20, text[11]);
      oled.drawFastImage(32+1*20, 43, 20, 20, text[9]);
      oled.drawFastImage(32+2*20, 43, 20, 20, text[10]);
      
      if(cursor == 1){
        oled.setFont(ArialMT_Plain_16);     // 设置字体
        oled.drawString(16, 1, ">");     // 将要显示的文字写入缓存 
      }
      if(cursor == 2){
        oled.setFont(ArialMT_Plain_16);     // 设置字体w
        oled.drawString(16, 22, ">");     // 将要显示的文字写入缓存
      }
      if(cursor == 3){
        oled.setFont(ArialMT_Plain_16);     // 设置字体w
        oled.drawString(16, 43, ">");     // 将要显示的文字写入缓存
      }      
  }

  oled.display();
}

void password_input_error(void)
{
  oled.clear();   
  oled.drawFastImage(2,        12, 20, 20, text[13]);
  oled.drawFastImage(2 + 1*20, 12, 20, 20, text[14]);
  oled.drawFastImage(2 + 2*20, 12, 20, 20, text[16]);
  oled.drawFastImage(2 + 3*20, 12, 20, 20, text[17]);
  
  oled.setFont(ArialMT_Plain_16);     // 设置字体w
  oled.drawString(2 + 4*20, 12, "!");     // 将要显示的文字写入缓存
  oled.display();
}

void password_input_success(void)
{
  oled.clear(); 
  oled.drawFastImage(2,        12, 20, 20, text[6]);
  oled.drawFastImage(2 + 1*20, 12, 20, 20, text[7]);
  oled.drawFastImage(2 + 2*20, 12, 20, 20, text[13]);
  oled.drawFastImage(2 + 3*20, 12, 20, 20, text[14]);
  oled.drawFastImage(2 + 4*20, 12, 20, 20, text[18]);
  oled.drawFastImage(2 + 5*20, 12, 20, 20, text[19]);
  oled.display();
}

void ID_input_error(void)
{
  oled.clear(); 
  
  oled.setFont(ArialMT_Plain_16);     // 设置字体w
  oled.drawString(2, 12, "ID");     // 将要显示的文字写入缓存
  oled.display();
  
  oled.drawFastImage(2 + 2*20, 12, 20, 20, text[13]);
  oled.drawFastImage(2 + 3*20, 12, 20, 20, text[14]);
  oled.drawFastImage(2 + 4*20, 12, 20, 20, text[16]);
  oled.drawFastImage(2 + 5*20, 12, 20, 20, text[17]);
  oled.display();
}

void ID_input_success(void)
{
  oled.clear(); 
  
  oled.drawFastImage(2 + 0*20, 12, 20, 20, text[9]);
  oled.drawFastImage(2 + 1*20, 12, 20, 20, text[10]);
  oled.drawFastImage(2 + 2*20, 12, 20, 20, text[22]);
  oled.drawFastImage(2 + 3*20, 12, 20, 20, text[23]);
  oled.drawFastImage(2 + 4*20, 12, 20, 20, text[18]);
  oled.drawFastImage(2 + 5*20, 12, 20, 20, text[19]);
  oled.display();
}

void finger_delete_success(void)
{
  oled.clear(); 
  oled.drawFastImage(2,        12, 20, 20, text[9]);
  oled.drawFastImage(2 + 1*20, 12, 20, 20, text[10]);
  oled.drawFastImage(2 + 2*20, 12, 20, 20, text[11]);
  oled.drawFastImage(2 + 3*20, 12, 20, 20, text[9]);
  oled.drawFastImage(2 + 4*20, 12, 20, 20, text[18]);
  oled.drawFastImage(2 + 5*20, 12, 20, 20, text[19]);
  oled.display();
}

void password_amend_success(void)//密码修改
{
  oled.clear(); 
  oled.drawFastImage(2,        12, 20, 20, text[6]);
  oled.drawFastImage(2 + 1*20, 12, 20, 20, text[7]);
  oled.drawFastImage(2 + 2*20, 12, 20, 20, text[20]);
  oled.drawFastImage(2 + 3*20, 12, 20, 20, text[21]);
  oled.drawFastImage(2 + 4*20, 12, 20, 20, text[18]);
  oled.drawFastImage(2 + 5*20, 12, 20, 20, text[19]);
  oled.display();  
}

void fingerprint_press_show(void)
{
  oled.clear(); 
  oled.drawFastImage(2,        12, 20, 20, text[24]);
  oled.drawFastImage(2 + 1*20, 12, 20, 20, text[25]);
  oled.drawFastImage(2 + 2*20, 12, 20, 20, text[26]);
  oled.drawFastImage(2 + 3*20, 12, 20, 20, text[27]);
  oled.drawFastImage(2 + 4*20, 12, 20, 20, text[28]);
  oled.drawFastImage(2 + 5*20, 12, 20, 20, text[9]);
  oled.display();  
}

void input_show(uint8_t interface_control, uint8_t cursor, char *str)
{
  oled.clear(); 
  
  if(interface_control == 1){ 
    oled.drawFastImage(2,      12, 20, 20, text[12]);
    oled.drawFastImage(2+1*20, 12, 20, 20, text[13]);
    oled.drawFastImage(2+2*20, 12, 20, 20, text[14]);
    oled.drawFastImage(2+3*20, 12, 20, 20, text[6]);
    oled.drawFastImage(2+4*20, 12, 20, 20, text[7]);
    
    oled.setFont(ArialMT_Plain_16);     // 设置字体w
    oled.drawString(2+5*20, 12, ":");     // 将要显示的文字写入缓存
  }

  if(interface_control == 2 && cursor == 1){
    oled.drawFastImage(2,      12, 20, 20, text[12]);
    oled.drawFastImage(2+1*20, 12, 20, 20, text[13]);
    oled.drawFastImage(2+2*20, 12, 20, 20, text[14]);
    oled.drawFastImage(2+3*20, 12, 20, 20, text[15]);
    oled.drawFastImage(2+4*20, 12, 20, 20, text[6]);
    oled.drawFastImage(2+5*20, 12, 20, 20, text[7]);
  }

  if(interface_control == 2 && cursor == 2){
    oled.drawFastImage(2,      12, 20, 20, text[12]);
    oled.drawFastImage(2+1*20, 12, 20, 20, text[13]);
    oled.drawFastImage(2+2*20, 12, 20, 20, text[14]);

    oled.setFont(ArialMT_Plain_16);     // 设置字体w
    oled.drawString(2+3*20, 12, "ID:");     // 将要显示的文字写入缓存
  }

  if(interface_control == 2 && cursor == 3){
    oled.drawFastImage(2,      12, 20, 20, text[12]);
    oled.drawFastImage(2+1*20, 12, 20, 20, text[13]);
    oled.drawFastImage(2+2*20, 12, 20, 20, text[14]);
    oled.setFont(ArialMT_Plain_16);     // 设置字体w
    oled.drawString(2+3*20, 12, "ID:");     // 将要显示的文字写入缓存    
  }
  
  oled.setFont(ArialMT_Plain_24);     // 设置字体w
  oled.drawString(2, 34, str);     // 将要显示的文字写入缓存
  oled.display();
}

/*-------------------------------------------------------
作用:参数运算,用于每个界面的光标显示标志运算
参数:
  interface_control:界面标志
  cursor:选项标志
--------------------------------------------------------*/
uint8_t cursor_operation_add(uint8_t interface_control,uint8_t cursor)
{
  cursor++;
  if(cursor>=2 && interface_control == 1)
    cursor = 2;
  if(cursor>=3 && interface_control == 2)//管理员界面有3个选项
    cursor = 3;
  
  return cursor;
}

uint8_t cursor_operation_sub(uint8_t cursor)
{
  cursor--;
  if(cursor <=1)
    cursor = 1;
  
  return cursor;
}

/*------------------------------------------------
            用于查询flash中的数据
password_flash_inquire:刚输入好的字符串
            cursor:光标
return 0: 没有查询到
return 1:查询到
------------------------------------------------*/
bool flash_inquire(int password_flash_inquire)
{
  int flash_data_save = 0;
  Preferences preferences;//声明一个命名空间的对象
  
  preferences.begin("my-app", false);//打开命名空间

  if(preferences.isKey("counter")) { // 如果当前命名空间中有键名为"counter"的元素
    //Serial.printf("counter: %d\n\n", preferences.getUInt("counter"));
    flash_data_save = preferences.getUInt("counter");//保存一下flash查询到的数据
    preferences.end();
  }
  
  if(password_flash_inquire == flash_data_save){//查询到flash中的数据
    Serial.printf("flash inquire success ! :%d\n\n", password_flash_inquire);
    return 1;
  } else {
    Serial.printf("flash inquire error ! :%d\n\n", password_flash_inquire);
    return 0;    
  }
  return 0;
}


/*---------------------------------------------
作用:用于密码保存
参数:
    password_flash_save:要保存的密码
返回值:无
---------------------------------------------*/
void password_save(int password_flash_save)
{
  Preferences preferences;//声明一个对象
  
  preferences.begin("my-app", false);//打开命名空间,设置读写权限

  //保存到首选项
  preferences.putUInt("counter", password_flash_save);//保存

  // 关闭
  preferences.end();
}

/*-----------------------------------------------
作用:界面功能实现
参数:
    str_password:密码,用于输入密码时与flash存入的密码配对
    interface_control:界面序号
    cursor:光标选项    
-----------------------------------------------*/
bool interface_function_reailze(char *str_password,uint8_t interface_control,uint8_t cursor)
{
  if((interface_control == 1 || interface_control == 2) && cursor == 1  && strlen(str_password) != 6){
    Serial.printf("password input long or shirt!\n\n");
    return 0;  
  }

  if(interface_control == 1 && (cursor == 1 || cursor == 2) && flash_inquire(atoi(str_password))==1){ //密码已经找到
    Serial.printf("password input success!\n\n");
    return 1;
  } else if (interface_control == 1 && (cursor == 1 || cursor == 2) && flash_inquire(atoi(str_password))==0){
    Serial.printf("password input error!\n\n");
    return 0;
  }

  if(interface_control == 2 && cursor == 1){//密码修改
    password_save(atoi(str_password));
    Serial.printf("password modification success!\n\n");
  }
  
  return 0;
}


//按键任务
void keyTask(void * pvParam) {

  char msg;//按键字符

  key_init();//引脚初始化  
  oled_init();//oled相关初始化
  
  uint8_t interface_control = 1;  //界面序号
  uint8_t cursor = 1;             //光标
  uint8_t function_sign = 0;      //功能实现标志 0.界面光标显示处理 1.密码输入
  
  char str_password[10];

  if( interface_control == 1 && cursor == 1){
    oled_show(interface_control,cursor,0);//界面1,光标1
  }
  while (1) {
    //互斥锁上锁
    if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {
      
      customKeypad.tick();
      while(customKeypad.available()){
        keypadEvent e = customKeypad.read();
        Serial.print((char)e.bit.KEY);//按键打印
        
        if(e.bit.EVENT == KEY_JUST_PRESSED)
          Serial.println(" press");
        else if (e.bit.EVENT == KEY_JUST_RELEASED) {  //松开,任务处理       按键按下的宏 --> KEY_JUST_PRESSED
          Serial.println(" released");
          
          msg = (char)e.bit.KEY;
          Serial.print(msg);  //按键打印
          
          if(function_sign == 1){//功能实现标志执行密码输入    
            if(msg == '#'){

              if(interface_function_reailze(str_password,interface_control,cursor) == 1 && interface_control == 1 && cursor == 1){ //界面1,光标1,密码输入正确,开锁                  
                function_sign = 0; memset(str_password, 0, sizeof(str_password));/*字符串清空*/     
                password_input_success(); unlocking();/*开锁*/vTaskDelay(2000); oled_show(interface_control,cursor,0);  continue;              
              } else if(interface_function_reailze(str_password,interface_control,cursor)==0 && interface_control == 1 && cursor == 1){ 
                function_sign = 0; memset(str_password, 0, sizeof(str_password));
                password_input_error(); vTaskDelay(2000); oled_show(interface_control,cursor,0); continue;} //j界面1开锁密码匹配不对
              
              if(interface_function_reailze(str_password,interface_control,cursor)==1 && interface_control == 1 && cursor == 2){ //界面1,光标2,密码输入正确,进入管理员界面
                interface_control = 2;cursor = 1;function_sign = 0; memset(str_password, 0, sizeof(str_password));/*清除密码输入保存*/              
                password_input_success(); vTaskDelay(2000); oled_show(interface_control,cursor,0);    /*显示界面2*/ continue;            
              } else if(interface_function_reailze(str_password,interface_control,cursor)==0 && interface_control == 1 && cursor == 2){
                function_sign = 0; memset(str_password, 0, sizeof(str_password)); 
                password_input_error(); vTaskDelay(2000); oled_show(interface_control,cursor,0); continue;}//界面2管理员密码匹配不对

              if(interface_control == 2 && cursor == 1 && strlen(str_password) == 6){  /*界面2,选项1,按下'#' 号键 --> 密码更改*/
                interface_function_reailze(str_password, interface_control, cursor);
                memset(str_password, 0, sizeof(str_password));
                interface_control = 1; function_sign = 0; cursor = 1; 
                password_amend_success(); vTaskDelay(2000); oled_show(interface_control,cursor,0);
                continue;
              } else if(interface_control == 2 && cursor == 1 && strlen(str_password) != 6){
                memset(str_password, 0, sizeof(str_password));
                interface_control = 1; function_sign = 0; cursor = 1; 
                password_input_error(); vTaskDelay(2000); oled_show(interface_control,cursor,0);
                continue;
              }

              if(interface_control == 2 && cursor == 2){ //开始录指纹
                if(strlen(str_password)<=0 || atoi(str_password) >= 20){//如果没有输入将要存储的指纹ID,或者ID号大于20
                  interface_control = 2; function_sign = 0; cursor = 1;
                  Serial.printf("fingerprint ID input error! %d\n\n",atoi(str_password)); 
                  ID_input_error(); vTaskDelay(2000); oled_show(interface_control,cursor,0);
                  memset(str_password, 0, sizeof(str_password));
                  continue;
                } 
                if(strlen(str_password)>=0 && atoi(str_password) <= 20){
                  Serial.printf("fingerprint ID input %d!\n\n",atoi(str_password));
                  //暂停指纹搜索任务
                  vTaskSuspend(finPrHandle);//任务暂停
                  while( !getFingerprintEnroll(atoi(str_password)) );
                  vTaskResume(finPrHandle); //任务恢复
                  memset(str_password, 0, sizeof(str_password));
                  interface_control = 1; function_sign = 0; cursor = 1;
                  ID_input_success(); vTaskDelay(2000); oled_show(interface_control,cursor,0);
                  continue;
                }
              }

              if(interface_control == 2 && cursor == 3){ //开始删除指纹
                if(strlen(str_password)<=0 || atoi(str_password) >= 20){//如果没有输入将要删除的指纹ID,或者ID号大于20,退出键盘输入模式
                  interface_control = 2; function_sign = 0; cursor = 1;
                  Serial.printf("fingerprint ID input error! %d\n\n",atoi(str_password));
                  memset(str_password, 0, sizeof(str_password)); 
                  ID_input_error(); vTaskDelay(2000); oled_show(interface_control,cursor,0);
                  continue;
                } 
                if(strlen(str_password)>=0 && atoi(str_password) <= 20){
                  Serial.printf("fingerprint ID delete %d!\n\n",atoi(str_password));
                  //暂停指纹搜索任务
                  vTaskSuspend(finPrHandle);//任务暂停
                  deleteFingerprint(atoi(str_password));
                  vTaskResume(finPrHandle); //任务恢复
                  memset(str_password, 0, sizeof(str_password));
                  interface_control = 1; function_sign = 0; cursor = 1;                    
                  finger_delete_success(); vTaskDelay(2000); oled_show(interface_control,cursor,0);
                  continue;
                }
              }
           
            }
            
            if(msg == '*'){  //清空字符串
              memset(str_password, 0, sizeof(str_password)); input_show(interface_control,cursor,str_password);continue;}
            if(msg == 'A' || msg == 'B' || msg == 'C' || msg == 'D'){//退出
              oled_show(interface_control,cursor,0);
              function_sign = 0;memset(str_password, 0, sizeof(str_password));continue;}
              
            sprintf(str_password,"%s%c",str_password,msg);         //字符串拼接
            Serial.printf("str_password: %s\n\n", str_password);
            input_show(interface_control,cursor,str_password);
              
          } else {  //光标选择处理 及 光标显示处理

            if(msg == 'A' || msg == 'C'){   //1号界面光标选项只有两个,2号界面光标选项有三个
              cursor = cursor_operation_sub(cursor);
              oled_show(interface_control,cursor,0);    
            }

            if(msg == 'B' || msg == 'D'){   //1号界面光标选项只有两个,2号界面光标选项有三个
              cursor = cursor_operation_add(interface_control,cursor);
              oled_show(interface_control,cursor,0);
            }
            
            if(msg == '#'){  //确认
              input_show(interface_control, cursor, str_password);
              function_sign = 1;continue;
            }

            if(interface_control == 2 && msg == '*'){  //返回主界面
              interface_control = 1;cursor = 1;
              oled_show(interface_control,cursor,0);
              continue;
            }
          
          }
        }
      }
      //互斥锁开锁
      xSemaphoreGive(xMutexInventory);
      vTaskDelay(10);
		}  
  }
}


/*  flash数据读取
    preferences.begin("my-app", false);//打开命名空间
    if(preferences.isKey("counter")) { // 如果当前命名空间中有键名为"counter"的元素
      Serial.printf("counter: %d\n\n", preferences.getUInt("counter"));
      preferences.end();
      function_sign = 0;
    }
    int num = atoi(str);
*/

task.h

#ifndef _TASK_H_
#define _TASK_H_

#include <Arduino.h>

//互斥锁相关
extern SemaphoreHandle_t xMutexInventory;

extern TickType_t timeOut;

//消息队列相关
extern QueueHandle_t queueMsg;

extern TaskHandle_t finPrHandle;

#endif

task.cpp

/*

  该文件用于任务创建时所需要用到的TimeOut等一些变量

*/

#include "task.h"

/* 互斥锁定义 */
SemaphoreHandle_t xMutexInventory = NULL;

TickType_t timeOut = 1000; //用于获取信号量的Timeout 1000 ti

QueueHandle_t queueMsg = xQueueCreate(8, sizeof(char[20]));

TaskHandle_t finPrHandle = NULL; //指纹Task Handler

/*if (finPrHandle != NULL) {
    vTaskSuspend(finPrHandle);//任务暂停
    vTaskResume(finPrHandle); //任务恢复       
  }
*/

blink.h

#ifndef _BLINKE_H_
#define _BLINKE_H_


#include "task.h"

#include "lock.h"

void blinkeTask(void * pvParam);

void button1_callback(const String & state);//按键回调函数

#endif

blink.cpp

#include "blinke.h"

#define BLINKER_WIFI

#define BLINKER_PRINT Serial

#define BLINKER_MIOT_LIGHT

#include <Blinker.h>/*无法将其放入.h头文件中,原因不明*/

const char *auth = "57135528a92d";
const char *ssid = "Redmi K40 Pro";  
const char *pswd = "05260526";

// 新建组件对象
BlinkerButton Button1("btn-abc");
BlinkerNumber Number1("num-abc");


int counter = 0;

// 按下按键即会执行该函数
void button1_callback(const String & state) {
    BLINKER_LOG("get button state: ", state);
    //digitalWrite(23, !digitalRead(23));
    unlocking();//开锁
    
    Button1.print(state);    
}

// 如果未绑定的组件被触发,则会执行其中内容
void dataRead(const String & data)
{
    BLINKER_LOG("Blinker readString: ", data);
    counter++;
    Number1.print(counter);
}

/*小爱智能家居回调函数*/
void miotPowerState(const String & state)
{
    BLINKER_LOG("need set power state: ", state);

    if (state == BLINKER_CMD_ON) {
        digitalWrite(23, HIGH);

        BlinkerMIOT.powerState("on");
        BlinkerMIOT.print();
    }
    else if (state == BLINKER_CMD_OFF) {
        digitalWrite(23, LOW);

        BlinkerMIOT.powerState("off");
        BlinkerMIOT.print();
    }
    vTaskDelay(2000);
    digitalWrite(23, LOW);
}

void blinkeTask(void * pvParam)
{
  #if defined(BLINKER_PRINT)
    BLINKER_DEBUG.stream(BLINKER_PRINT);
  #endif

  // 初始化blinker
  Blinker.begin(auth, ssid, pswd);
  Blinker.attachData(dataRead);
  Button1.attach(button1_callback);/*注册按键回调函数*/

  BlinkerMIOT.attachPowerState(miotPowerState);/*注册小爱语音回调函数*/
  
  //测试
  pinMode(23,OUTPUT);
  digitalWrite(23,LOW);

  while(1){
    //互斥锁上锁
    if (xSemaphoreTake(xMutexInventory, timeOut) == pdPASS) {

      Blinker.run();
      
      //互斥锁开锁
      xSemaphoreGive(xMutexInventory);
      vTaskDelay(10);
    }
  }      
}

lock.h

#ifndef _LOCK_H_
#define _LOCK_H_

#include <Arduino.h>

void unlocking(void);//开锁2S




#endif

lock.cpp

#include "lock.h"

#define LOCK_PIN 23

void unlocking(void)
{
  digitalWrite(LOCK_PIN, HIGH);
  vTaskDelay(2000);
  digitalWrite(LOCK_PIN, LOW);
}

总结:1、代码花了大约一周草草了事,没有将重心及代码思路放在模块化以及优化上,像界面显示函数就直接放在了key.cpp文件处理,一些相关界面处理可以参考其他大佬博客的oled多界面处理思路更加清晰,相关处理可以基于他们那种编写,
2、本次工程运用到了freeRTOS,只创建了3个任务并行运行,按键任务是整个代码的核心,也像我在第一条总结所说,关于按键处理界面的可以参考其他大佬博客
3、该项目接入到了米家,由于点灯科技免费给开发者5种常见的家居控制方式,更多功能需要用到专业版,所以我们再喊小爱同学的时候叫开门是没有用的,叫她打开灯光是有用的,所以暂时用这种方式代替