嵌入式软件编程思想之事件驱动+表驱动状态机+事件参数+优先级FIFO

在状态机 + 事件驱动的嵌入式架构中,如果所有事件都简单塞进一个 FIFO,高优先级事件可能被低优先级事件阻塞,导致实时性下降。实现事件优先级排序的核心思想是:让高优先级事件先于低优先级事件被处理,同时不破坏状态机的主逻辑。总体设计思想:把系统行为抽象为事件触发状态迁移,用 FIFO 解耦事件生产与消费,用优先级保证关键事件实时响应。

c 复制代码
`#ifndef CORE_EVENT_H
#define CORE_EVENT_H
#include <stdint.h>
#include <stdbool.h>
#define EVT_QUEUE_SIZE 8
typedef uint16_t EvtId;
typedef uint8_t  EvtPrio;
/* 事件参数 */
typedef enum {
    PARAM_NONE = 0,
    PARAM_U8,
    PARAM_U16,
    PARAM_U32,
} ParamType;

typedef union {
    uint8_t  u8;
    uint16_t u16;
    uint32_t u32;
} ParamData;

typedef struct {
    ParamType type;
    ParamData data;
} EventParam;
/* 事件 */
typedef struct {
    EvtId      id;
    EventParam param;
} Event;
/* 优先级 */
typedef enum {
    PRIO_HIGH = 0,
    PRIO_MID,
    PRIO_LOW,
    PRIO_NUM
} EvtPrioEnum;
void  Event_Init(void);
bool  Event_Post(EvtId id, const EventParam *p);
bool  Event_Get(Event *e);
#endif`
c 复制代码
#include "core_event.h"

typedef struct {
    Event buf[EVT_QUEUE_SIZE];
    uint8_t head;
    uint8_t tail;
} EventQueue;

static EventQueue s_queue[PRIO_NUM];

void Event_Init(void)
{
    for (int i = 0; i < PRIO_NUM; i++) {
        s_queue[i].head = 0;
        s_queue[i].tail = 0;
    }
}

static bool Enqueue(EventQueue *q, const Event *e)
{
    uint8_t next = (q->tail + 1) % EVT_QUEUE_SIZE;
    if (next == q->head) return false;
    q->buf[q->tail] = *e;
    q->tail = next;
    return true;
}

static bool Dequeue(EventQueue *q, Event *e)
{
    if (q->head == q->tail) return false;
    *e = q->buf[q->head];
    q->head = (q->head + 1) % EVT_QUEUE_SIZE;
    return true;
}

bool Event_Post(EvtId id, const EventParam *p)
{
    static const EvtPrio prio[] = {
        [1] = PRIO_HIGH,
        [2] = PRIO_HIGH,
        [3] = PRIO_MID,
        [4] = PRIO_LOW,
    };

    Event e = {
        .id = id,
        .param = *p
    };

    EvtPrio p = (id < sizeof(prio)) ? prio[id] : PRIO_LOW;
    return Enqueue(&s_queue[p], &e);
}

bool Event_Get(Event *e)
{
    for (int p = PRIO_HIGH; p < PRIO_NUM; p++) {
        if (Dequeue(&s_queue[p], e))
            return true;
    }
    return false;
}
c 复制代码
#ifndef CORE_FSM_H
#define CORE_FSM_H

#include "core_event.h"

typedef void (*ActionFn)(Event *e);

typedef struct {
    uint8_t   state;
    EvtId     event;
    ActionFn  action;
    uint8_t   nextState;
} FsmTable;

void FSM_Init(const FsmTable *table, uint8_t tableSize, uint8_t initState);
void FSM_Dispatch(Event *e);

#endif
c 复制代码
#include "core_fsm.h"

static const FsmTable *s_table;
static uint8_t s_tableSize;
static uint8_t s_state;

void FSM_Init(const FsmTable *table, uint8_t tableSize, uint8_t initState)
{
    s_table = table;
    s_tableSize = tableSize;
    s_state = initState;
}

void FSM_Dispatch(Event *e)
{
    for (uint8_t i = 0; i < s_tableSize; i++) {
        const FsmTable *t = &s_table[i];
        if (t->state == s_state && t->event == e->id) {
            if (t->action) t->action(e);
            s_state = t->nextState;
            return;
        }
    }
}

应用层:

c 复制代码
typedef enum {
    EVT_KEY = 1,
    EVT_TEMP,
    EVT_FAULT,
    EVT_MAX
} AppEvent;

typedef enum {
    ST_IDLE = 0,
    ST_RUN,
    ST_ERR,
    ST_MAX
} AppState;
c 复制代码
#include "core_fsm.h"
#include "app_event.h"
#include <stdio.h>

static void Act_Start(Event *e);
static void Act_Temp(Event *e);
static void Act_Fault(Event *e);
static void Act_Null(Event *e) { (void)e; }

static const FsmTable s_appFsm[] = {
    {ST_IDLE, EVT_KEY,   Act_Start, ST_RUN},
    {ST_RUN,  EVT_TEMP,  Act_Temp,  ST_RUN},
    {ST_RUN,  EVT_FAULT, Act_Fault, ST_ERR},
    {ST_ERR,  EVT_KEY,   Act_Start, ST_IDLE},
};

void App_FsmInit(void)
{
    FSM_Init(s_appFsm, sizeof(s_appFsm)/sizeof(s_appFsm[0]), ST_IDLE);
}

static void Act_Start(Event *e)
{
    printf("Start, key=%d\r\n", e->param.data.u8);
}

static void Act_Temp(Event *e)
{
    printf("Temp=%d\r\n", e->param.data.u16);
}

static void Act_Fault(Event *e)
{
    printf("Fault=%lu\r\n", e->param.data.u32);
}

主程序

c 复制代码
#include "core_event.h"
#include "core_fsm.h"
#include "app_event.h"

int main(void)
{
    EventParam p;

    Event_Init();
    App_FsmInit();

    /* 模拟事件 */
    p.type = PARAM_U8; p.data.u8 = 1;
    Event_Post(EVT_KEY, &p);

    p.type = PARAM_U16; p.data.u16 = 25;
    Event_Post(EVT_TEMP, &p);

    while (1) {
        Event e;
        if (Event_Get(&e)) {
            FSM_Dispatch(&e);
        } else {
            /* 低功耗 / 睡眠 */
        }
    }
}
相关推荐
secondyoung2 小时前
Cortex-R52学习:存储系统
arm开发·单片机·学习·arm
开发笔记-阿牛3 小时前
CK6159A 语音主控 USB 恒温热敷控制器硬件设计(原理图 + PCB + 温控安全方案)
单片机·嵌入式硬件
sramdram6 小时前
低功耗串口通信蓝牙模块应用原理
单片机·嵌入式硬件·蓝牙模块·通信蓝牙模块·串口蓝牙模块
__Rhaast丶6 小时前
set_data_check用法解析(一) lib库中的data check解析
单片机·嵌入式硬件
wuyk5558 小时前
21. 嵌入式面试避坑指南:sizeof 是关键字,不是函数!
c语言·开发语言·stm32·单片机·嵌入式硬件
FreakStudio12 天前
W55MH32L-EVB 上手测评:硬件 TCP/IP 加持的以太网单片机,MicroPython 零门槛开发
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
ifndef14 天前
GPIO同时复用(ADC与TIM)
mcu
✎ ﹏梦醒͜ღ҉繁华落℘17 天前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
zd84510150017 天前
RS485 总线详解
单片机·嵌入式硬件