# 状态机集成 **Repository Path**: backsoon0/state-machine-integration ## Basic Information - **Project Name**: 状态机集成 - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-12-01 - **Last Updated**: 2025-01-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 状态机集成 ## 关于状态机 ### 状态机是什么 单片机裸机项目中,状态机是一种比较常见的编程方式,不管是学习还是做项目,我们应该具备最基础的状态机编程思想。 状态机有条件,状态和动作,当满足某个条件时,就会转移到下一个状态并执行一个动作,具体可以参考这篇文章[分享一个实用的【状态机】编程思想](https://mp.weixin.qq.com/s/Qfq7EXowmWZ_7vyln0AQpQ)。 ### 为什么要集成 由于目前非集成化的状态机导致逻辑不清晰,由于状态太多导致状态跳转混乱,逻辑及其不分明,于是有了这个集成。 ## 关于此项目 目前,该状态机具有一个状态状态表,当某个事件发生时,就会触发某个转化, 该状态表的格式如下: ```c EventTable TestEventTable[] = { {TIME_SIG,state_1,state_2}, {TIME_SIG,state_2,state_3}, {TIME_SIG,state_3,state_4}, {TIME_SIG,state_4,state_1}, }; ``` 第一个参数是状态的名称,第二个参数是当前的状态,第三个参数是要切换的状态 第二个参数和第三个参数都是函数指针的形式, 状态函数的格式如下: ```c uint8_t state_1(void *me, Sig const e) { switch (e) { case ENTRY_SIG: // 在进入当前状态时添加需要的事件 EVENT_AddDelay((Fsm*)me,2000); EVENT_AddFsm(&event_1,(Fsm*)me); printf("enter the state 1!!!\n"); break; case RUN_SIG: printf("run the state 1!!!\n"); break; case EXIT_SIG: // 在离开时删除事件 EVENT_DelDelay((Fsm*)me); EVENT_DelFsm(&event_1,(Fsm*)me); printf("exit the state 1!!!\n"); break; default: printf("state 1 error"); break; } return 0; } ``` 每一个状态机都有一个结构体,通过面向对象的方式初始化 ### 如何使用 1. 先建立一个状态表,写好每一个状态的函数,先使用`FSM_Init()`进行初始化。 2. 如果需要外部事件,写好事件检查函数,并对事件结构体使用`EVENT_Init()`进行初始化。 3. 如果此状态机需要**这个**事件的派发,需要在`case ENTRY_SIG:`中进行`EVENT_AddFsm()`注册。 4. 如果此状态机需要**所有**事件的派发,需要在启动状态机`FSM_Start()`之前进行`EVENT_AddFsmGlobal()`注册,一般不使用。 5. 如果需要特定的触发,比如延时,需要自己编写,具体参考`Mydelay.h`,如果需要可以初始化比如`EVENT_DelayInit()`,目前已添加了延时,在刚进入某状态时进行`EVENT_AddDelay()`注册。 6. 调用`FSM_Start()`启动此状态机。 7. 还需要一直调用`EVENT_Task()`和`FSM_Task()`函数。 在main.c用一个用例的展示,可以去了解 ### TODO - [x] 事件结构体 中的状态机链表改进 - [ ] 事件检测函数 多参数 - [ ] 状态切换时 更新事件链