1. 事件驱动架构基础
任务说明
本案例实现一个基于事件驱动的LED闪烁控制器。系统维护一个事件队列,定时器周期性产生“超时事件”,事件处理器根据当前LED状态决定翻转动作,从而形成闪烁效果。核心目标是展示事件驱动架构中“事件产生—事件排队—事件分发—事件处理”的基本闭环,而非单纯实现LED翻转逻辑。
事件驱动架构设计
整个系统由三个模块组成:事件源(定时器)、事件队列(FIFO缓冲区)、事件处理器(状态机)。事件源每500ms向队列投递一次EV_TIMEOUT事件;处理器从队列头部取出事件,根据当前LED状态执行翻转,并更新状态。主循环持续执行event_loop(),该函数会阻塞等待队列非空后取出事件并分发处理。
代码实现
// event_driven_led.c
// 编译: gcc -o event_driven_led event_driven_led.c
// 运行: ./event_driven_led (模拟环境,无真实硬件)
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h> // usleep()
// ---------- 事件定义 ----------
typedef enum {
EV_NONE = 0,
EV_TIMEOUT
} event_id_t;
typedef struct {
event_id_t id;
uint32_t param; // 扩展字段,本案例未使用
} event_t;
// ---------- 事件队列 (FIFO) ----------
#define QUEUE_SIZE 8
static event_t queue[QUEUE_SIZE];
static uint8_t head = 0;
static uint8_t tail = 0;
static uint8_t count = 0;
static bool queue_push(const event_t *ev) {
if (count >= QUEUE_SIZE) return false; // 满
queue[tail] = *ev;
tail = (tail + 1) % QUEUE_SIZE;
count++;
return true;
}
static bool queue_pop(event_t *ev) {
if (count == 0) return false; // 空
*ev = queue[head];
head = (head + 1) % QUEUE_SIZE;
count--;
return true;
}
// ---------- LED 状态机 ----------
typedef enum {
LED_OFF = 0,
LED_ON
} led_state_t;
static led_state_t led_state = LED_OFF;
// 模拟GPIO写操作(真实场景替换为寄存器操作)
static void gpio_write(bool level) {
// 在无硬件环境下,仅打印状态变化
printf("[GPIO] PA1 = %s\n", level ? "HIGH (LED ON)" : "LOW (LED OFF)");
}
static void led_toggle(void) {
if (led_state == LED_OFF) {
led_state = LED_ON;
gpio_write(true);
} else {
led_state = LED_OFF;
gpio_write(false);
}
}
// ---------- 事件源:定时器回调(模拟) ----------
static void timer_tick(void) {
event_t ev;
ev.id = EV_TIMEOUT;
ev.param = 0;
if (!queue_push(&ev)) {
printf("[WARN] 事件队列已满,事件丢失!\n");
}
}
// ---------- 事件分发 ----------
static void event_handler(const event_t *ev) {
switch (ev->id) {
case EV_TIMEOUT:
led_toggle(); // 超时事件 → 翻转LED
break;
default:
printf("[ERROR] 未知事件 ID=%d\n", ev->id);
break;
}
}
// ---------- 主循环 ----------
static void event_loop(void) {
event_t ev;
if (queue_pop(&ev)) {
event_handler(&ev);
}
}
// ---------- 模拟定时器(每500ms触发一次) ----------
static void simulate_timer(void) {
usleep(500 * 1000); // 500ms
timer_tick();
}
int main(void) {
printf("=== 事件驱动LED闪烁演示 (Ctrl+C退出) ===\n");
printf("初始状态: LED OFF\n\n");
// 模拟运行:循环10次(约5秒)
for (int i = 0; i < 10; i++) {
simulate_timer(); // 等待500ms并产生事件
event_loop(); // 处理事件
}
printf("\n演示结束。\n");
return 0;
}
编译与运行
gcc -o event_driven_led event_driven_led.c
./event_driven_led
预期输出
=== 事件驱动LED闪烁演示 (Ctrl+C退出) ===
初始状态: LED OFF
[GPIO] PA1 = HIGH (LED ON)
[GPIO] PA1 = LOW (LED OFF)
[GPIO] PA1 = HIGH (LED ON)
[GPIO] PA1 = LOW (LED OFF)
[GPIO] PA1 = HIGH (LED ON)
[GPIO] PA1 = LOW (LED OFF)
[GPIO] PA1 = HIGH (LED ON)
[GPIO] PA1 = LOW (LED OFF)
[GPIO] PA1 = HIGH (LED ON)
[GPIO] PA1 = LOW (LED OFF)
演示结束。
验证方法
运行程序后观察输出:每行[GPIO]打印间隔约500ms,且HIGH与LOW交替出现共10次,说明事件产生、排队、分发、处理全链路工作正常。若需验证队列满保护,可将QUEUE_SIZE改为1并缩短定时器间隔,可观察到[WARN]提示且程序不崩溃。
判定标准
- 输出中
HIGH与LOW严格交替,无连续相同状态; - 相邻两次打印时间间隔约500ms(可用
time命令验证总时长约5秒); - 程序正常退出,无内存错误或异常终止。