#include #include #include #include #include // RFID引脚定义 #define RFID_RST_PIN 14 // RC522 复位引脚 #define RFID_SS_PIN 10 // RC522 片选引脚 #define RFID_MISO_PIN 13 // MISO 引脚 #define RFID_MOSI_PIN 12 // MOSI 引脚 #define RFID_SCK_PIN 11 // SCK 引脚 // LED定义 #define LED_PIN_1 4 // 1颗WS2812灯珠引脚 #define LED_PIN_2 5 // 160颗WS2812灯带引脚 #define LED_PIN_3 48 // 1颗WS2812灯珠引脚(新增) #define LED_COUNT_1 1 // 1颗灯珠 #define LED_COUNT_2 186 // 160颗灯带 #define LED_COUNT_3 1 // 1颗灯珠(新增) // PWM定义 #define PWM_PIN 6 // PWM输出引脚 #define PWM_CHANNEL 0 // PWM通道 #define PWM_FREQ 1000 // PWM频率(Hz) #define PWM_RESOLUTION 10 // PWM分辨率(位) #define DEFAULT_DUTY 819 // 默认占空比(80%) // 按钮和输入引脚定义 #define BTN0_PIN 15 // 按钮0引脚 #define WAKEUP1_PIN 16 // 唤醒引脚1 #define BTN1_PIN 17 // 按钮1引脚 #define BTN2_PIN 18 // 按钮2引脚 // 任务句柄 TaskHandle_t TaskRFID, TaskLED1, TaskLED2, TaskLED3, TaskPWM, TaskBTN0, TaskWAKEUP1, TaskBTN1, TaskBTN2; // 全局变量 MFRC522 rfid(RFID_SS_PIN, RFID_RST_PIN); // 创建RFID实例 CRGB leds1[LED_COUNT_1]; // 1颗灯珠数组 CRGB leds2[LED_COUNT_2]; // 160颗灯带数组 CRGB leds3[LED_COUNT_3]; // 1颗灯珠数组(新增) String lastCardData = ""; // 上次读取的RFID卡数据 int ledMode = 1; // 灯带模式,默认为1(白色) int pwmDuty = DEFAULT_DUTY; // PWM占空比 bool btn0State = HIGH; // 按钮0状态 bool btn0LongPress = false; // 按钮0长按标志 bool wakeup1State = LOW; // 唤醒引脚1状态 bool btn1State = LOW; // 按钮1状态 bool btn2State = LOW; // 按钮2状态 int singleLedMode = 7; // 单颗LED模式,默认为7(白色) // 灯带动画全局变量 static uint8_t rainbowHue = 0; static int trainPos = 0; static unsigned long lastUpdate = 0; static const int TRAIN_LENGTH = 16; // 火车灯长度 static int trainPhase = 0; // 火车阶段:0-正向出站,1-正向前进,2-正向进站,3-反向出站,4-反向前进,5-反向进站 static const int VIRTUAL_LED_COUNT = LED_COUNT_2 + TRAIN_LENGTH; // 虚拟灯带长度 // 单颗LED颜色数组 CRGB singleLedColors[8] = { CRGB::Black, // 0: 熄灭 CRGB::Blue, // 1: 蓝色 CRGB::Green, // 2: 绿色 CRGB::Orange, // 3: 橙色 CRGB::Red, // 4: 红色 CRGB::Purple, // 5: 紫色 CRGB::Yellow, // 6: 黄色 CRGB::White // 7: 白色 }; // RFID读取任务 void TaskRFIDcode( void * pvParameters ) { for(;;) { // 寻找新卡片 if ( ! rfid.PICC_IsNewCardPresent()) { delay(10); continue; } // 验证NUID是否可读 if ( ! rfid.PICC_ReadCardSerial()) { delay(10); continue; } // 读取卡片数据(用户数据区) String cardData = ""; MFRC522::MIFARE_Key key; // 准备认证密钥 for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF; // 选择卡片 MFRC522::StatusCode status; status = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(rfid.uid)); if (status != MFRC522::STATUS_OK) { Serial.print(F("Authentication failed: ")); Serial.println(rfid.GetStatusCodeName(status)); rfid.PICC_HaltA(); rfid.PCD_StopCrypto1(); delay(100); continue; } // 读取数据块 byte buffer[18]; byte size = sizeof(buffer); status = rfid.MIFARE_Read(4, buffer, &size); if (status != MFRC522::STATUS_OK) { Serial.print(F("Reading failed: ")); Serial.println(rfid.GetStatusCodeName(status)); } else { // 转换为ASCII字符串 for (byte i = 0; i < 16; i++) { if (buffer[i] >= 32 && buffer[i] <= 126) { // 可打印ASCII字符 cardData += (char)buffer[i]; } } // 移除空白字符 cardData.trim(); // 卡片数据处理 if (cardData != lastCardData && !cardData.isEmpty()) { lastCardData = cardData; Serial.println("SORC_" + cardData); } } // 使放置在读卡区的IC卡进入休眠状态,不再重复读卡 rfid.PICC_HaltA(); // 停止加密PCD rfid.PCD_StopCrypto1(); delay(100); } } // LED1控制任务 void TaskLED1code( void * pvParameters ) { for(;;) { // 根据模式设置LED1颜色 if (singleLedMode >= 0 && singleLedMode <= 7) { leds1[0] = singleLedColors[singleLedMode]; } else { leds1[0] = CRGB::Blue; // 默认白色 } // 更新LED FastLED.show(); delay(20); } } // LED3控制任务(新增) void TaskLED3code( void * pvParameters ) { for(;;) { // 强制设置GPIO48的灯珠为熄灭状态 leds3[0] = CRGB::Black; // 更新LED FastLED.show(); delay(20); } } // LED2控制任务 void TaskLED2code( void * pvParameters ) { for(;;) { // 根据不同模式控制灯带 switch(ledMode) { case 0: // 全部熄灭 fill_solid(leds2, LED_COUNT_2, CRGB::Black); break; case 1: // 纯白色 fill_solid(leds2, LED_COUNT_2, CRGB::White); break; case 2: // 彩虹流水灯 for(int i = 0; i < LED_COUNT_2; i++) { leds2[i] = CHSV(rainbowHue + i * 256 / LED_COUNT_2, 255, 255); } rainbowHue++; break; case 3: // 彩虹呼吸灯 for(int i = 0; i < LED_COUNT_2; i++) { leds2[i] = CHSV(rainbowHue, 255, beatsin8(1, 64, 255)); } rainbowHue++; break; case 4: // 彩虹火车灯 if (millis() - lastUpdate > 30) { // 30ms更新一次 lastUpdate = millis(); // 清除所有灯珠 fill_solid(leds2, LED_COUNT_2, CRGB::Black); switch (trainPhase) { case 0: // 正向出站(从起点开始出现) for (int i = 0; i < TRAIN_LENGTH; i++) { int pos = trainPos + i; if (pos >= 0 && pos < LED_COUNT_2) { uint8_t hue = rainbowHue + (i * 256 / TRAIN_LENGTH); leds2[pos] = CHSV(hue, 255, 255); } } trainPos += 1; // 检查是否完全出站 if (trainPos >= 0) { trainPhase = 1; // 开始正向前进 trainPos = 0; } break; case 1: // 正向前进 for (int i = 0; i < TRAIN_LENGTH; i++) { int pos = trainPos + i; if (pos >= 0 && pos < LED_COUNT_2) { uint8_t hue = rainbowHue + (i * 256 / TRAIN_LENGTH); leds2[pos] = CHSV(hue, 255, 255); } } trainPos += 1; // 检查是否到达终点 if (trainPos >= LED_COUNT_2 - TRAIN_LENGTH) { trainPhase = 2; // 开始正向进站 trainPos = LED_COUNT_2 - TRAIN_LENGTH; } break; case 2: // 正向进站(从尾部开始消失) for (int i = 0; i < TRAIN_LENGTH; i++) { int displayPos = LED_COUNT_2 - 1 - i; if (displayPos >= trainPos) { uint8_t hue = rainbowHue + (i * 256 / TRAIN_LENGTH); leds2[displayPos] = CHSV(hue, 255, 255); } } trainPos += 1; // 检查是否完全进站 if (trainPos >= LED_COUNT_2) { trainPhase = 3; // 开始反向出站 trainPos = 0; rainbowHue += 64; // 改变彩虹颜色 } break; case 3: // 反向出站(从终点开始出现) for (int i = 0; i < trainPos + 1; i++) { int pos = LED_COUNT_2 - 1 - i; if (pos >= 0) { uint8_t hue = rainbowHue + ((TRAIN_LENGTH - 1 - i) * 256 / TRAIN_LENGTH); leds2[pos] = CHSV(hue, 255, 255); } } trainPos += 1; // 检查是否完全出站 if (trainPos >= TRAIN_LENGTH) { trainPhase = 4; // 开始反向前进 trainPos = TRAIN_LENGTH; } break; case 4: // 反向前进 for (int i = 0; i < TRAIN_LENGTH; i++) { int pos = LED_COUNT_2 - trainPos + i; if (pos >= 0 && pos < LED_COUNT_2) { uint8_t hue = rainbowHue + ((TRAIN_LENGTH - 1 - i) * 256 / TRAIN_LENGTH); leds2[pos] = CHSV(hue, 255, 255); } } trainPos += 1; // 检查是否到达起点 if (trainPos >= LED_COUNT_2) { trainPhase = 5; // 开始反向进站 trainPos = 0; } break; case 5: // 反向进站(从头部开始消失) for (int i = 0; i < TRAIN_LENGTH - trainPos; i++) { int pos = i; if (pos < LED_COUNT_2) { uint8_t hue = rainbowHue + ((TRAIN_LENGTH - 1 - i) * 256 / TRAIN_LENGTH); leds2[pos] = CHSV(hue, 255, 255); } } trainPos += 1; // 检查是否完全进站 if (trainPos >= TRAIN_LENGTH) { trainPhase = 0; // 重新开始正向出站 trainPos = -TRAIN_LENGTH; rainbowHue += 64; // 改变彩虹颜色 } break; } } break; case 5: // 马卡龙火车灯(保留原功能,未修改) // 代码保持不变... break; } // 更新LED FastLED.show(); // 根据模式调整延时 if (ledMode == 4 || ledMode == 5) { delay(10); // 火车灯模式需要更快的更新速度 } else { delay(30); } } } // PWM控制任务 void TaskPWMcode( void * pvParameters ) { for(;;) { // 设置PWM占空比 ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL, pwmDuty); ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL); delay(100); } } // 按钮0检测任务 void TaskBTN0code( void * pvParameters ) { static unsigned long pressStartTime = 0; static bool lastState = HIGH; for(;;) { bool currentState = digitalRead(BTN0_PIN); // 检测下降沿(按下) if (lastState == HIGH && currentState == LOW) { pressStartTime = millis(); btn0State = LOW; Serial.println("SO_BT0_HIGH"); btn0LongPress = false; } // 检测上升沿(释放) else if (lastState == LOW && currentState == HIGH) { btn0State = HIGH; Serial.println("SO_BT0_LOW"); btn0LongPress = false; } // 检测长按 else if (currentState == LOW && millis() - pressStartTime >= 2000 && !btn0LongPress) { btn0LongPress = true; Serial.println("SO_BT0_HIGHL"); } lastState = currentState; delay(10); } } // WAKEUP1检测任务 void TaskWAKEUP1code( void * pvParameters ) { static bool lastState = LOW; for(;;) { bool currentState = digitalRead(WAKEUP1_PIN); // 检测上升沿 if (lastState == LOW && currentState == HIGH) { wakeup1State = HIGH; Serial.println("SO_WAKEUP1"); } // 检测下降沿 else if (lastState == HIGH && currentState == LOW) { wakeup1State = LOW; Serial.println("SO_WAKEUP0"); } lastState = currentState; delay(10); } } // 按钮1检测任务 void TaskBTN1code( void * pvParameters ) { static bool lastState = LOW; for(;;) { bool currentState = digitalRead(BTN1_PIN); // 检测上升沿 if (lastState == LOW && currentState == HIGH) { btn1State = HIGH; Serial.println("SO_BT1_HIGH"); } // 检测下降沿 else if (lastState == HIGH && currentState == LOW) { btn1State = LOW; Serial.println("SO_BT1_LOW"); } lastState = currentState; delay(10); } } // 按钮2检测任务 void TaskBTN2code( void * pvParameters ) { static bool lastState = LOW; for(;;) { bool currentState = digitalRead(BTN2_PIN); // 检测上升沿 if (lastState == LOW && currentState == HIGH) { btn2State = HIGH; Serial.println("SO_BT2_HIGH"); } // 检测下降沿 else if (lastState == HIGH && currentState == LOW) { btn2State = LOW; Serial.println("SO_BT2_LOW"); } lastState = currentState; delay(10); } } // 串口命令处理 void handleSerialCommand() { static String command = ""; while (Serial.available()) { char c = Serial.read(); if (c == '\n') { // 处理命令 if (command.startsWith("MO_LED_")) { String modeStr = command.substring(7); int newMode = modeStr.toInt(); // 控制单颗LED if (newMode >= 0 && newMode <= 7) { singleLedMode = newMode; Serial.print("Single LED set to mode: "); Serial.println(newMode); } else { Serial.println("Invalid single LED mode command"); } } else if (command.startsWith("MO_LEDN_")) { String modeStr = command.substring(8); int newMode = modeStr.toInt(); // 控制灯带 if (newMode >= 0 && newMode <= 5) { ledMode = newMode; // 重置火车灯状态 if (newMode == 4) { trainPos = -TRAIN_LENGTH; trainPhase = 0; rainbowHue = random8(); } Serial.print("LED strip set to mode: "); Serial.println(newMode); } else { Serial.println("Invalid LED strip mode command"); } } else if (command.startsWith("MO_PWM_")) { String dutyStr = command.substring(7); int newDuty = dutyStr.toInt(); // 检查PWM百分比 if (newDuty == 1) { pwmDuty = 1023; // 100% } else if (newDuty == 0 || newDuty == 20 || newDuty == 40 || newDuty == 60 || newDuty == 80) { pwmDuty = (newDuty * 1023) / 100; // 转换为实际占空比 } else { Serial.println("Invalid PWM command"); } Serial.print("PWM set to: "); Serial.print((pwmDuty * 100) / 1023); Serial.println("%"); } // 清空命令 command = ""; } else { command += c; } } } void setup() { // 初始化串口 Serial.begin(115200); Serial.println("System starting..."); // 初始化SPI总线 SPI.begin(RFID_SCK_PIN, RFID_MISO_PIN, RFID_MOSI_PIN, RFID_SS_PIN); // 初始化RFID rfid.PCD_Init(); Serial.println("RFID initialized."); // 初始化LED FastLED.addLeds(leds1, LED_COUNT_1); FastLED.addLeds(leds2, LED_COUNT_2); FastLED.addLeds(leds3, LED_COUNT_3); // 新增LED3 // 初始化LED状态 fill_solid(leds1, LED_COUNT_1, singleLedColors[singleLedMode]); fill_solid(leds2, LED_COUNT_2, CRGB::White); fill_solid(leds3, LED_COUNT_3, CRGB::Black); // 强制GPIO48的灯珠熄灭 FastLED.show(); Serial.println("LED initialized."); // 初始化PWM // 创建LED控制器配置 ledc_timer_config_t ledc_timer = { .speed_mode = LEDC_LOW_SPEED_MODE, .duty_resolution = (ledc_timer_bit_t)PWM_RESOLUTION, .timer_num = (ledc_timer_t)PWM_CHANNEL, .freq_hz = PWM_FREQ, .clk_cfg = LEDC_AUTO_CLK }; ledc_timer_config(&ledc_timer); // 创建LED通道配置 ledc_channel_config_t ledc_channel = { .gpio_num = PWM_PIN, .speed_mode = LEDC_LOW_SPEED_MODE, .channel = (ledc_channel_t)PWM_CHANNEL, .intr_type = LEDC_INTR_DISABLE, .timer_sel = (ledc_timer_t)PWM_CHANNEL, .duty = 0, .hpoint = 0 }; ledc_channel_config(&ledc_channel); // 设置初始占空比 ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL, pwmDuty); ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL); Serial.println("PWM initialized."); // 初始化输入引脚 pinMode(BTN0_PIN, INPUT_PULLUP); pinMode(WAKEUP1_PIN, INPUT); pinMode(BTN1_PIN, INPUT); pinMode(BTN2_PIN, INPUT); Serial.println("Inputs initialized."); // 创建任务 xTaskCreatePinnedToCore( TaskRFIDcode, /* 任务函数 */ "TaskRFID", /* 任务名称 */ 4096, /* 任务栈大小 */ NULL, /* 传递给任务的参数 */ 1, /* 任务优先级 */ &TaskRFID, /* 任务句柄 */ 1); /* 运行在核心1上 */ xTaskCreatePinnedToCore( TaskLED1code, "TaskLED1", 2048, NULL, 1, &TaskLED1, 1); xTaskCreatePinnedToCore( TaskLED2code, "TaskLED2", 4096, NULL, 1, &TaskLED2, 1); xTaskCreatePinnedToCore( TaskLED3code, "TaskLED3", 2048, NULL, 1, &TaskLED3, 1); // 新增LED3任务 xTaskCreatePinnedToCore( TaskPWMcode, "TaskPWM", 1024, NULL, 1, &TaskPWM, 1); xTaskCreatePinnedToCore( TaskBTN0code, "TaskBTN0", 2048, NULL, 1, &TaskBTN0, 0); xTaskCreatePinnedToCore( TaskWAKEUP1code, "TaskWAKEUP1", 2048, NULL, 1, &TaskWAKEUP1, 0); xTaskCreatePinnedToCore( TaskBTN1code, "TaskBTN1", 2048, NULL, 1, &TaskBTN1, 0); xTaskCreatePinnedToCore( TaskBTN2code, "TaskBTN2", 2048, NULL, 1, &TaskBTN2, 0); Serial.println("Tasks created. System ready."); } void loop() { // 处理串口命令 handleSerialCommand(); // 让出CPU时间 delay(1); }