#include <Arduino.h>
// ==================== 纯单一功能安全引脚 ====================
const int A_PINS[] = {PA0, PA1, PA2, PA3};
const int A_GROUP_SIZE = 4;
const int B_PINS[] = {PB0, PB1, PB3, PB4};
const int B_GROUP_SIZE = 4;
// 开关:A、B独立控制 + ALL时序控制
const int SW_A_PIN = PB8;
const int SW_B_PIN = PB9;
const int SW_ALL_PIN = PB15;
const int POT_PIN = PA4;
// ==================== 配置 ====================
const bool SW_A_NC = false;
const bool SW_B_NC = false;
const bool SW_ALL_NC = false;
const unsigned long MIN_INTERVAL_MS = 500;
const unsigned long MAX_INTERVAL_MS = 5000;
const int ADC_MAX = 4095;
// ==================== 全局变量 ====================
unsigned long g_interval_ms = 1000;
// A组状态
int g_A_index = 0; // 0~4,当前已点亮的数量
bool g_A_isOn = false; // 目标状态:true=要开, false=要关
// B组状态
int g_B_index = 0; // 0~4,当前已点亮的数量
bool g_B_isOn = false; // 目标状态:true=要开, false=要关
unsigned long g_last_action_time = 0;
// ==================== 初始化 ====================
void setup() {
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_AFIO_REMAP_SWJ_NOJTAG();
Serial.begin(115200);
// A组输出
for (int i = 0; i < A_GROUP_SIZE; i++) {
pinMode(A_PINS[i], OUTPUT);
digitalWrite(A_PINS[i], LOW);
}
// B组输出
for (int i = 0; i < B_GROUP_SIZE; i++) {
pinMode(B_PINS[i], OUTPUT);
digitalWrite(B_PINS[i], LOW);
}
// 开关上拉输入
pinMode(SW_A_PIN, INPUT_PULLUP);
pinMode(SW_B_PIN, INPUT_PULLUP);
pinMode(SW_ALL_PIN, INPUT_PULLUP);
analogReadResolution(12);
g_last_action_time = millis();
}
// ==================== 读取开关 ====================
uint8_t readSwitches() {
bool raw_a = (digitalRead(SW_A_PIN) == LOW);
bool raw_b = (digitalRead(SW_B_PIN) == LOW);
bool raw_all = (digitalRead(SW_ALL_PIN) == LOW);
bool sw_a = SW_A_NC ? !raw_a : raw_a;
bool sw_b = SW_B_NC ? !raw_b : raw_b;
bool sw_all = SW_ALL_NC ? !raw_all : raw_all;
uint8_t sw = 0;
if (sw_a) sw |= 0x01;
if (sw_b) sw |= 0x02;
if (sw_all) sw |= 0x04;
return sw;
}
// ==================== 电位器 ====================
unsigned long getInterval() {
int val = analogRead(POT_PIN);
val = constrain(val, 0, ADC_MAX);
return MIN_INTERVAL_MS + (unsigned long)val * (MAX_INTERVAL_MS - MIN_INTERVAL_MS) / ADC_MAX;
}
// ==================== A组操作 ====================
void A_OnStep() {
if (g_A_index < A_GROUP_SIZE) {
digitalWrite(A_PINS[g_A_index], HIGH);
g_A_index++;
}
}
void A_OffReverseStep() {
if (g_A_index > 0) {
g_A_index--;
digitalWrite(A_PINS[g_A_index], LOW);
}
}
// ==================== B组操作 ====================
void B_OnStep() {
if (g_B_index < B_GROUP_SIZE) {
digitalWrite(B_PINS[g_B_index], HIGH);
g_B_index++;
}
}
void B_OffReverseStep() {
if (g_B_index > 0) {
g_B_index--;
digitalWrite(B_PINS[g_B_index], LOW);
}
}
// ==================== 主循环 ====================
void loop() {
uint8_t sw = readSwitches();
g_interval_ms = getInterval();
bool sw_a = sw & 0x01; // A开关
bool sw_b = sw & 0x02; // B开关
bool sw_all = sw & 0x04; // ALL开关(时序控制)
// ========== 确定目标状态 ==========
// A组目标:A开关打开 或 ALL打开
g_A_isOn = sw_a || sw_all;
// B组目标:B开关打开 或 (ALL打开 且 A组已全亮)
if (sw_b) {
g_B_isOn = true; // B开关直接控制,独立
} else if (sw_all) {
g_B_isOn = (g_A_index >= A_GROUP_SIZE); // ALL模式:A全亮后B才能亮
} else {
g_B_isOn = false;
}
if (millis() - g_last_action_time >= g_interval_ms) {
g_last_action_time = millis();
// ========== ALL模式:逆向关闭逻辑(先B后A) ==========
if (!sw_all && (g_A_index > 0 || g_B_index > 0)) {
// 优先判断:如果有任何灯亮着,先执行逆向关闭
// 关闭顺序:先关B组,B组全关后再关A组
if (g_B_index > 0) {
// B组还有灯亮,继续关B
B_OffReverseStep();
return;
}
if (g_A_index > 0 && g_B_index == 0) {
// B组全关后,开始关A
A_OffReverseStep();
return;
}
}
// ========== A组执行 ==========
if (g_A_isOn && g_A_index < A_GROUP_SIZE) {
A_OnStep();
} else if (!g_A_isOn && g_A_index > 0 && !sw_all) {
// 非ALL模式下,A独立关闭
A_OffReverseStep();
}
// ========== B组执行 ==========
if (g_B_isOn && g_B_index < B_GROUP_SIZE) {
B_OnStep();
} else if (!g_B_isOn && g_B_index > 0 && !sw_all) {
// 非ALL模式下,B独立关闭
B_OffReverseStep();
}
}
}Loading
stm32-bluepill
stm32-bluepill