嵌入式软件编程思想之事件驱动+表驱动状态机+事件参数+优先级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 {
            /* 低功耗 / 睡眠 */
        }
    }
}
相关推荐
女神下凡3 小时前
芯参谋(85):Linux_PPI_NAND_驱动开发指南
linux·运维·arm开发·驱动开发·单片机·嵌入式硬件·设计规范
硅基手札5 小时前
【Linux 内核专栏 19】20 · 嵌入式子系统 — GPIO·pinctrl·clock·regulator
linux·运维·单片机·linux内核·嵌入式开发·调试定位
何粥学7 小时前
Vivado 2024.2 开发记录(AC820 Zynq-7020)——软件使用,点亮led灯
单片机·嵌入式硬件·zynq
Sakura_j_h_8 小时前
51 单片机驱动四位数码管:动态扫描、限流电阻与消影的取舍
单片机·嵌入式硬件·51单片机·嵌入式·数码管·动态扫描·限流电阻
蹊黎20 小时前
Linux 下用 C 语言实现进度条
linux·c语言·单片机
无敌贵点大王1 天前
从寄存器层面重学STM32(6)——串口USART实战部分
stm32·单片机·嵌入式硬件
庙堂龙吟奈我何1 天前
二进制和十六进制
stm32·单片机
国科安芯1 天前
长期在轨的计算底座:商业空间站与在轨服务飞行器健康管理中的抗辐射MCU—— 面向可维护空间平台的分层容错与安全通信综述
人工智能·单片机·嵌入式硬件·安全·低轨卫星·抗辐射
不昀1 天前
RMII切到10Mbps,50MHz参考时钟也要降到5MHz吗?
单片机·嵌入式硬件·硬件设计·以太网接口
路上有只喵1 天前
认识元器件 · 单片机(MCU/MPU/SOC) · 实战篇6
单片机·嵌入式硬件