/* ============================================================
* 实验二:计数信号量应用 - 资源管理
* ============================================================*/
#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#define BUTTON_ENTER 0 // 进入按键
#define BUTTON_EXIT 15 // 退出按键(GPIO15)
#define LED_GREEN 2 // 有空位指示灯
#define LED_RED 4 // 满位指示灯
#define TOTAL_PARKING 5 // 总车位数
SemaphoreHandle_t xParkingSemaphore;
int currentCars = 0;
// 显示当前车位状态
void displayStatus() {
UBaseType_t available = uxSemaphoreGetCount(xParkingSemaphore);
Serial.printf("当前车位: %d/%d (剩余: %d)\n",
TOTAL_PARKING - available, TOTAL_PARKING, available);
if(available > 0) {
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_RED, LOW);
} else {
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_RED, HIGH);
}
}
// 车辆进入任务
void vCarEnterTask(void *pvParameters) {
bool lastButtonState = HIGH;
while(1) {
bool currentButtonState = digitalRead(BUTTON_ENTER);
if(lastButtonState == HIGH && currentButtonState == LOW) {
// 尝试获取车位(信号量)
if(xSemaphoreTake(xParkingSemaphore, 0) == pdTRUE) {
currentCars++;
Serial.print("🚗 车辆进入 → ");
displayStatus();
} else {
Serial.println("❌ 车位已满,车辆无法进入!");
}
vTaskDelay(pdMS_TO_TICKS(300)); // 消抖
}
lastButtonState = currentButtonState;
vTaskDelay(pdMS_TO_TICKS(10));
}
}
// 车辆离开任务
void vCarExitTask(void *pvParameters) {
bool lastButtonState = HIGH;
while(1) {
bool currentButtonState = digitalRead(BUTTON_EXIT);
if(lastButtonState == HIGH && currentButtonState == LOW) {
// 释放车位(信号量)
if(uxSemaphoreGetCount(xParkingSemaphore) < TOTAL_PARKING) {
xSemaphoreGive(xParkingSemaphore);
currentCars--;
Serial.print("🚙 车辆离开 → ");
displayStatus();
} else {
Serial.println("⚠️ 停车场已空,无车辆离开!");
}
vTaskDelay(pdMS_TO_TICKS(300)); // 消抖
}
lastButtonState = currentButtonState;
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n=== 实验二:计数信号量应用 - 停车场管理系统 ===");
Serial.printf("总车位: %d\n\n", TOTAL_PARKING);
pinMode(BUTTON_ENTER, INPUT_PULLUP);
pinMode(BUTTON_EXIT, INPUT_PULLUP);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_RED, OUTPUT);
// 创建计数信号量:最大计数TOTAL_PARKING,初始值TOTAL_PARKING(全部空闲)
xParkingSemaphore = xSemaphoreCreateCounting(TOTAL_PARKING, TOTAL_PARKING);
if(xParkingSemaphore == NULL) {
Serial.println("信号量创建失败!");
while(1);
}
displayStatus();
// 创建任务
xTaskCreate(vCarEnterTask, "CarEnter", 2048, NULL, 2, NULL);
xTaskCreate(vCarExitTask, "CarExit", 2048, NULL, 2, NULL);
}
void loop() {
vTaskDelay(pdMS_TO_TICKS(1000));
}