更新旧开发板代码备份

This commit is contained in:
Rdzleo 2026-04-21 17:22:33 +08:00
parent 87926e48a4
commit 90105a60ea

View File

@ -35,43 +35,6 @@
// 任务句柄 // 任务句柄
TaskHandle_t TaskRFID, TaskLED1, TaskLED2, TaskLED3, TaskPWM, TaskBTN0, TaskWAKEUP1, TaskBTN1, TaskBTN2; TaskHandle_t TaskRFID, TaskLED1, TaskLED2, TaskLED3, TaskPWM, TaskBTN0, TaskWAKEUP1, TaskBTN1, TaskBTN2;
// 双串口架构:
// - Serial = USB-Serial-JTAG (USB2 口),连 Windows 做调试日志
// - SerialLinux = UART0 (CH343/USB1 口),连 Linux 开发板接收业务数据
// UART0 默认引脚TX=GPIO43、RX=GPIO44对应 CH343P 的 RXD/TXD
HardwareSerial SerialLinux(0);
// Serial 输出互斥锁:防止多任务并发写串口导致数据交错/截断
SemaphoreHandle_t serialMutex = NULL;
// 带互斥保护的双串口输出:同时发到 USB CDC (Windows) 和 UART0 (Linux)
// 调用方RFID 任务发 SORC_xxx按键任务发 SO_xxx
// 机制1) 互斥锁避免多任务交错 2) 两个串口并发传输 3) flush 等待传输完成
void serialPrintlnSafe(const String& msg) {
if (serialMutex && xSemaphoreTake(serialMutex, pdMS_TO_TICKS(100)) == pdTRUE) {
// ---- 发到 USB CDC (Windows 调试) ----
// 等待 TX 缓冲区有足够空间,避免 USB CDC 缓冲区满导致截断(最多等 50ms
size_t needed = msg.length() + 2;
uint32_t waitStart = millis();
while ((size_t)Serial.availableForWrite() < needed && (millis() - waitStart) < 50) {
vTaskDelay(pdMS_TO_TICKS(2));
}
Serial.println(msg);
Serial.flush();
// ---- 发到 UART0 (Linux 业务) ----
// UART0 硬件有独立 128 字节 FIFO115200 波特率下发送 12 字节约 1ms几乎不阻塞
SerialLinux.println(msg);
SerialLinux.flush();
xSemaphoreGive(serialMutex);
} else {
// 拿不到锁的降级路径(正常情况下几乎不触发)
Serial.println(msg);
SerialLinux.println(msg);
}
}
// 全局变量 // 全局变量
MFRC522 rfid(RFID_SS_PIN, RFID_RST_PIN); // 创建RFID实例 MFRC522 rfid(RFID_SS_PIN, RFID_RST_PIN); // 创建RFID实例
CRGB leds1[LED_COUNT_1]; // 1颗灯珠数组 CRGB leds1[LED_COUNT_1]; // 1颗灯珠数组
@ -170,12 +133,11 @@ void TaskRFIDcode(void* pvParameters) {
MFRC522::StatusCode status; MFRC522::StatusCode status;
status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(rfid.uid)); status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(rfid.uid));
if (status != MFRC522::STATUS_OK) { if (status != MFRC522::STATUS_OK) {
// 调试日志用普通 Serial.println失败频率较高时避免 flush 阻塞拖慢 RFID 响应 Serial.print(F("Authentication failed: "));
// 偶尔截断可接受Linux 端用正则 ^SORC_HA\d+$ 过滤业务数据即可) Serial.println(rfid.GetStatusCodeName(status));
Serial.println(String("Authentication failed: ") + rfid.GetStatusCodeName(status));
rfid.PICC_HaltA(); rfid.PICC_HaltA();
rfid.PCD_StopCrypto1(); rfid.PCD_StopCrypto1();
delay(30); // 从 100ms 降到 30ms提升刷卡响应速度 delay(100);
continue; continue;
} }
@ -184,47 +146,23 @@ void TaskRFIDcode(void* pvParameters) {
byte size = sizeof(buffer); byte size = sizeof(buffer);
status = rfid.MIFARE_Read(4, buffer, &size); status = rfid.MIFARE_Read(4, buffer, &size);
if (status != MFRC522::STATUS_OK) { if (status != MFRC522::STATUS_OK) {
Serial.println(String("Reading failed: ") + rfid.GetStatusCodeName(status)); Serial.print(F("Reading failed: "));
rfid.PICC_HaltA(); Serial.println(rfid.GetStatusCodeName(status));
rfid.PCD_StopCrypto1(); } else {
delay(30); // 从 100ms 降到 30ms // 转换为ASCII字符串
continue; for (byte i = 0; i < 16; i++) {
} if (buffer[i] >= 32 && buffer[i] <= 126) { // 可打印ASCII字符
cardData += (char)buffer[i];
// 转换为ASCII字符串 }
for (byte i = 0; i < 16; i++) {
if (buffer[i] >= 32 && buffer[i] <= 126) { // 可打印ASCII字符
cardData += (char)buffer[i];
} }
}
// 移除空白字符 // 移除空白字符
cardData.trim(); cardData.trim();
// 卡片数据格式校验:规则 "HA" + 阿拉伯数字 // 卡片数据处理
// 过滤掉卡片读取异常或数据损坏的情况,避免发送无效数据给 Linux if (cardData != lastCardData && !cardData.isEmpty()) {
auto isValidCardData = [](const String& d) -> bool { lastCardData = cardData;
if (d.length() < 3) return false; // 至少 "HA" + 1 位数字 Serial.println("SORC_" + cardData);
if (!d.startsWith("HA")) return false; // 必须以 HA 开头
for (size_t i = 2; i < d.length(); i++) {
if (!isdigit(d[i])) return false; // HA 后面必须全是数字
}
return true;
};
// 3 秒去重窗口:同一张卡 3 秒内只发送一次,超过后允许重发
// 切换到不同卡立即发送
static String lastSentCard = "";
static unsigned long lastSentTime = 0;
const unsigned long DUPLICATE_WINDOW_MS = 3000;
if (!cardData.isEmpty() && isValidCardData(cardData)) {
unsigned long now = millis();
bool isDuplicate = (cardData == lastSentCard) && (now - lastSentTime < DUPLICATE_WINDOW_MS);
if (!isDuplicate) {
serialPrintlnSafe("SORC_" + cardData);
lastSentCard = cardData;
lastSentTime = now;
} }
} }
@ -278,19 +216,19 @@ void TaskBTN0code(void* pvParameters) {
if (lastState == HIGH && currentState == LOW) { if (lastState == HIGH && currentState == LOW) {
pressStartTime = millis(); pressStartTime = millis();
btn0State = LOW; btn0State = LOW;
serialPrintlnSafe("SO_BT0_HIGH"); Serial.println("SO_BT0_HIGH");
btn0LongPress = false; btn0LongPress = false;
} }
// 检测上升沿(释放) // 检测上升沿(释放)
else if (lastState == LOW && currentState == HIGH) { else if (lastState == LOW && currentState == HIGH) {
btn0State = HIGH; btn0State = HIGH;
serialPrintlnSafe("SO_BT0_LOW"); Serial.println("SO_BT0_LOW");
btn0LongPress = false; btn0LongPress = false;
} }
// 检测长按 // 检测长按
else if (currentState == LOW && millis() - pressStartTime >= 2000 && !btn0LongPress) { else if (currentState == LOW && millis() - pressStartTime >= 2000 && !btn0LongPress) {
btn0LongPress = true; btn0LongPress = true;
serialPrintlnSafe("SO_BT0_HIGHL"); Serial.println("SO_BT0_HIGHL");
} }
lastState = currentState; lastState = currentState;
@ -308,12 +246,12 @@ void TaskWAKEUP1code(void* pvParameters) {
// 检测上升沿 // 检测上升沿
if (lastState == LOW && currentState == HIGH) { if (lastState == LOW && currentState == HIGH) {
wakeup1State = HIGH; wakeup1State = HIGH;
serialPrintlnSafe("SO_WAKEUP1"); Serial.println("SO_WAKEUP1");
} }
// 检测下降沿 // 检测下降沿
else if (lastState == HIGH && currentState == LOW) { else if (lastState == HIGH && currentState == LOW) {
wakeup1State = LOW; wakeup1State = LOW;
serialPrintlnSafe("SO_WAKEUP0"); Serial.println("SO_WAKEUP0");
} }
lastState = currentState; lastState = currentState;
@ -331,12 +269,12 @@ void TaskBTN1code(void* pvParameters) {
// 检测上升沿 // 检测上升沿
if (lastState == LOW && currentState == HIGH) { if (lastState == LOW && currentState == HIGH) {
btn1State = HIGH; btn1State = HIGH;
serialPrintlnSafe("SO_BT1_HIGH"); Serial.println("SO_BT1_HIGH");
} }
// 检测下降沿 // 检测下降沿
else if (lastState == HIGH && currentState == LOW) { else if (lastState == HIGH && currentState == LOW) {
btn1State = LOW; btn1State = LOW;
serialPrintlnSafe("SO_BT1_LOW"); Serial.println("SO_BT1_LOW");
} }
lastState = currentState; lastState = currentState;
@ -354,12 +292,12 @@ void TaskBTN2code(void* pvParameters) {
// 检测上升沿 // 检测上升沿
if (lastState == LOW && currentState == HIGH) { if (lastState == LOW && currentState == HIGH) {
btn2State = HIGH; btn2State = HIGH;
serialPrintlnSafe("SO_BT2_HIGH"); Serial.println("SO_BT2_HIGH");
} }
// 检测下降沿 // 检测下降沿
else if (lastState == HIGH && currentState == LOW) { else if (lastState == HIGH && currentState == LOW) {
btn2State = LOW; btn2State = LOW;
serialPrintlnSafe("SO_BT2_LOW"); Serial.println("SO_BT2_LOW");
} }
lastState = currentState; lastState = currentState;
@ -382,8 +320,6 @@ void handleSerialCommand() {
char c = Serial.read(); char c = Serial.read();
if (c == '\n') { if (c == '\n') {
// 去掉命令末尾可能的 \r兼容不同行尾符设置\n 或 \r\n
command.trim();
// 处理命令 // 处理命令
if (command.startsWith("MO_LED_")) { if (command.startsWith("MO_LED_")) {
String modeStr = command.substring(7); String modeStr = command.substring(7);
@ -489,13 +425,6 @@ void handleSerialCommand() {
} }
command = ""; // 清空命令 command = ""; // 清空命令
} }
// 软复位命令:串口发送 "RESET" 触发 ESP32 重启
else if (command == "RESET") {
Serial.println("System resetting...");
Serial.flush(); // 等待串口数据发送完成
delay(100); // 留时间让串口打印完
ESP.restart(); // 触发软复位
}
command = ""; // 清空命令 command = ""; // 清空命令
} else { } else {
@ -518,9 +447,7 @@ void handleSerialCommand() {
// 5. 防闪烁机制确保LED显示稳定 // 5. 防闪烁机制确保LED显示稳定
void TaskLEDUnifiedCode(void* pvParameters) { void TaskLEDUnifiedCode(void* pvParameters) {
static unsigned long lastLEDUpdate = 0; static unsigned long lastLEDUpdate = 0;
// 20FPS 更新频率:兼顾视觉流畅度和 RFID 稳定性 const unsigned long LED_UPDATE_INTERVAL = 33; // ~30FPS降低更新频率减少闪烁
// 每秒 20 次 WS2812 传输(每次 ~5.6ms 关中断),相比 30FPS 减少 33% 干扰窗口
const unsigned long LED_UPDATE_INTERVAL = 50;
for (;;) { for (;;) {
unsigned long currentTime = millis(); unsigned long currentTime = millis();
@ -722,20 +649,9 @@ void TaskLEDUnifiedCode(void* pvParameters) {
void setup() { void setup() {
// 初始化 USB CDC 串口Windows 调试) // 初始化串口
// 增大 TX 缓冲区到 4KB防止多任务并发写串口时 USB CDC 默认缓冲区溢出导致数据截断
Serial.setTxBufferSize(4096);
Serial.begin(115200); Serial.begin(115200);
// 初始化 UART0CH343/USB1 → Linux 业务通讯)
// 默认引脚TX=GPIO43、RX=GPIO44波特率与 Linux 端保持一致
SerialLinux.begin(115200);
// 创建 Serial 输出互斥锁
serialMutex = xSemaphoreCreateMutex();
Serial.println("System starting..."); Serial.println("System starting...");
SerialLinux.println("System starting...");
// 初始化SPI总线 // 初始化SPI总线
SPI.begin(RFID_SCK_PIN, RFID_MISO_PIN, RFID_MOSI_PIN, RFID_SS_PIN); SPI.begin(RFID_SCK_PIN, RFID_MISO_PIN, RFID_MOSI_PIN, RFID_SS_PIN);
@ -793,15 +709,14 @@ void setup() {
Serial.println("Inputs initialized."); Serial.println("Inputs initialized.");
// 创建任务 // 创建任务
// TaskRFID 放 Core 0避开 Core 1 上 WS2812 bit-banging 关中断窗口SPI 通讯更稳定
xTaskCreatePinnedToCore( xTaskCreatePinnedToCore(
TaskRFIDcode, /* 任务函数 */ TaskRFIDcode, /* 任务函数 */
"TaskRFID", /* 任务名称 */ "TaskRFID", /* 任务名称 */
4096, /* 任务栈大小 */ 4096, /* 任务栈大小 */
NULL, /* 传递给任务的参数 */ NULL, /* 传递给任务的参数 */
2, /* 任务优先级(提高到 2避免被按键任务频繁抢占*/ 1, /* 任务优先级 */
&TaskRFID, /* 任务句柄 */ &TaskRFID, /* 任务句柄 */
0); /* 运行在核心0上与 LED 任务物理隔离)*/ 1); /* 运行在核心1上 */
xTaskCreatePinnedToCore( xTaskCreatePinnedToCore(
TaskLEDUnifiedCode, TaskLEDUnifiedCode,