主循环SYS_TICK无阻塞延迟
#include "stm32f4xx_hal.h"
#include <stdint.h>
typedef enum {
EVT_RELAY_ON = 0,
EVT_RELAY_OFF
} evt_type_t;
typedef struct {
uint8_t active;
uint8_t relay_id;
uint8_t type;
uint8_t token; // 防止旧事件误执行(可选但强烈推荐)
uint32_t deadline_ms;
} event_t;
#define MAX_EVENTS 32
#define RELAY_NUM 8
static event_t g_events[MAX_EVENTS];
static uint8_t g_relay_token[RELAY_NUM]; // 每路继电器的版本号
// 你自己实现:根据 relay_id 控制对应 GPIO
void Relay_On(uint8_t id);
void Relay_Off(uint8_t id);
// 添加事件:在 delay_ms 后执行 ON/OFF
static int Scheduler_Add(uint8_t relay_id, evt_type_t type, uint32_t delay_ms, uint8_t token)
{
uint32_t now = HAL_GetTick();
uint32_t deadline = now + delay_ms;
for (int i = 0; i < MAX_EVENTS; i++) {
if (!g_events[i].active) {
g_events[i].active = 1;
g_events[i].relay_id = relay_id;
g_events[i].type = (uint8_t)type;
g_events[i].deadline_ms = deadline;
g_events[i].token = token;
return 0; // ok
}
}
return -1; // 队列满了
}
// 主循环里一直调用
void Scheduler_Poll(void)
{
uint32_t now = HAL_GetTick();
for (int i = 0; i < MAX_EVENTS; i++) {
if (!g_events[i].active) continue;
// 到期判断(防溢出)
if ((int32_t)(now - g_events[i].deadline_ms) >= 0) {
uint8_t id = g_events[i].relay_id;
// token 检查:不一致说明被更新过,丢弃旧事件
if (g_events[i].token == g_relay_token[id]) {
if (g_events[i].type == EVT_RELAY_ON) Relay_On(id);
else Relay_Off(id);
}
g_events[i].active = 0; // 释放槽位
}
}
}
// 继电器“脉冲”:立即开,ms 后关
int Relay_Pulse(uint8_t id, uint32_t ms)
{
if (id >= RELAY_NUM) return -2;
g_relay_token[id]++; // 更新版本号
Relay_On(id); // 立即执行
// 安排 ms 后关
return Scheduler_Add(id, EVT_RELAY_OFF, ms, g_relay_token[id]);
}
主循环内运行
int main(void)
{
HAL_Init();
// ... GPIO/时钟初始化
while (1) {
Scheduler_Poll();
// 比如某条件触发
// Relay_Pulse(3, 80);
}
}

浙公网安备 33010602011771号