// ПР2. GPIO: проект «Светофор» с пешеходной кнопкой
// Плата: NUCLEO-C031C6 (STM32C031C6), Wokwi + STM32duino
// Автор: Алексеев Ф.В., ЭФБО-08-23
// --- Назначение выводов ---
#define CAR_R D13 // PA5 — автомобильный красный
#define CAR_Y D12 // PA6 — автомобильный жёлтый
#define CAR_G D11 // PA7 — автомобильный зелёный
#define PED_R D9 // PC7 — пешеходный красный
#define PED_G D8 // PA9 — пешеходный зелёный
#define BTN D4 // PB10 — кнопка пешехода (к GND, внутренняя подтяжка вверх)
// --- Длительности фаз, мс (по заданию) ---
const uint32_t T_RED = 5000;
const uint32_t T_RED_YEL = 2000;
const uint32_t T_GREEN = 5000;
const uint32_t T_YELLOW = 2000;
const uint32_t T_GREEN_MIN = 1000; // минимальный зелёный при вызове пешеходом
// --- Состояния конечного автомата ---
enum State { RED, RED_YELLOW, GREEN, YELLOW };
const char *NAMES[] = { "RED (ped GO)", "RED+YELLOW", "GREEN", "YELLOW" };
State state = RED;
uint32_t tState = 0; // момент входа в текущее состояние
bool request = false; // заявка пешехода
// Установка ламп для каждого состояния (таблица состояний)
void applyState(State s) {
digitalWrite(CAR_R, s == RED || s == RED_YELLOW);
digitalWrite(CAR_Y, s == RED_YELLOW || s == YELLOW);
digitalWrite(CAR_G, s == GREEN);
digitalWrite(PED_G, s == RED); // пешеходам разрешено только при красном для машин
digitalWrite(PED_R, s != RED);
}
void enter(State s) {
state = s;
tState = millis();
applyState(s);
Serial.print("t="); Serial.print(tState); Serial.print(" ms -> ");
Serial.println(NAMES[s]);
}
// Опрос кнопки с антидребезгом 20 мс (нажатие = LOW)
void pollButton() {
static bool last = HIGH, stable = HIGH;
static uint32_t tChange = 0;
bool raw = digitalRead(BTN);
if (raw != last) { last = raw; tChange = millis(); }
if (millis() - tChange > 20 && raw != stable) {
stable = raw;
if (stable == LOW && state != RED) {
request = true;
Serial.print("t="); Serial.print(millis());
Serial.println(" ms [button] pedestrian request");
}
}
}
void setup() {
Serial.begin(115200);
pinMode(CAR_R, OUTPUT); pinMode(CAR_Y, OUTPUT); pinMode(CAR_G, OUTPUT);
pinMode(PED_R, OUTPUT); pinMode(PED_G, OUTPUT);
pinMode(BTN, INPUT_PULLUP); // подтяжка вверх: отпущена = 1, нажата = 0
enter(RED);
}
void loop() {
pollButton();
uint32_t dt = millis() - tState;
switch (state) {
case RED:
if (dt >= T_RED) enter(RED_YELLOW);
break;
case RED_YELLOW:
if (dt >= T_RED_YEL) enter(GREEN);
break;
case GREEN:
// по заявке пешехода зелёный сокращается (но не меньше T_GREEN_MIN)
if (dt >= T_GREEN || (request && dt >= T_GREEN_MIN)) enter(YELLOW);
break;
case YELLOW:
if (dt >= T_YELLOW) { request = false; enter(RED); }
break;
}
}
Loading
st-nucleo-c031c6
st-nucleo-c031c6