1. 事件驱动架构基础

事件驱动架构基础 学习卡片

任务说明

本案例实现一个基于事件驱动的LED闪烁控制器。系统维护一个事件队列,定时器周期性产生“超时事件”,事件处理器根据当前LED状态决定翻转动作,从而形成闪烁效果。核心目标是展示事件驱动架构中“事件产生—事件排队—事件分发—事件处理”的基本闭环,而非单纯实现LED翻转逻辑。

事件驱动架构设计

整个系统由三个模块组成:事件源(定时器)、事件队列(FIFO缓冲区)、事件处理器(状态机)。事件源每500ms向队列投递一次EV_TIMEOUT事件;处理器从队列头部取出事件,根据当前LED状态执行翻转,并更新状态。主循环持续执行event_loop(),该函数会阻塞等待队列非空后取出事件并分发处理。

定时器 每500ms产生 EV_TIMEOUT 投递 事件队列 FIFO 缓冲区 容量: 8 [EV_TIMEOUT, ...] 取出 事件处理器 状态机 LED_ON ↔ LED_OFF 翻转GPIO电平 控制 LED GPIO PA1 主循环: while(1) 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秒);
  • 程序正常退出,无内存错误或异常终止。