单片机~状态机
状态机介绍
状态机一般指有限状态机,简称 fsm
,意思是一项任务只有有限个状态。
虽然可以使用标志位来解决这些问题,但是随着功能越来越多,程序中就会出现大量标志位Flag,很容易出现某个标志位写错导致出现Bug,可读性也差。
状态机的4个重要组成部分
:
➢ 状态
➢ 状态转移(在这示例里startNow = xxx就是发生了状态改变)
➢ 转移条件(在这示例里Time2_1s_Flag就是状态发生改变的条件)
➢ 动作(就是状态改变后需要执行的内容这里是点灯)
简单的示例
芯片 | 涉及模块 | 实现效果 |
---|---|---|
STM32G431RBT6 | LED,TIM2 | 1,3,5,7灯亮然后2,4,6,8灯亮然后所有灯亮,以此循环 |
- cubeMX配置略(也就是配置LED+TIM2)
- 这里有3种状态分别是
1357亮
,2468亮
,所有亮
- 主要程序
/*************************LED.c*************************/
//枚举
enum {
START_OPEN_1_3_5_7, //打开1,3,5,7LED
START_OPEN_2_4_6_8, //打开2,4,6,8LED
START_OPEN_ALL, //打开所有灯
};
//定义一开始状态(看你想上电后先亮哪几个)
uint8_t startNow = START_OPEN_ALL;
void LED_Dis1(void)
{
switch(startNow)
{
case START_OPEN_ALL: //如果当前状态是所有灯亮则
startNow = START_OPEN_1_3_5_7; //状态改成1,3,5,7亮
lightAll_open(0); //关闭所有灯
light1357_open(1); //点亮1357
break;
case START_OPEN_1_3_5_7:
startNow = START_OPEN_2_4_6_8;
light1357_open(0);
light2468_open(1);
break;
case START_OPEN_2_4_6_8:
startNow = START_OPEN_ALL;
lightAll_open(1);
break;
}
}
//点亮/关闭1357
void light1357_open(uint8_t mode)
{
if(1 == mode)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8|GPIO_PIN_10|GPIO_PIN_12|GPIO_PIN_14,GPIO_PIN_RESET); //点亮1,3,5,7
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //拉高
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //拉低
}
else
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8|GPIO_PIN_10|GPIO_PIN_12|GPIO_PIN_14,GPIO_PIN_SET); //关闭1,3,5,7
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //拉高
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //拉低
}
}
//点亮/关闭2468
void light2468_open(uint8_t mode)
{
if(1 == mode)
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9|GPIO_PIN_11|GPIO_PIN_13|GPIO_PIN_15,GPIO_PIN_RESET); //点亮2,4,6,8
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //拉高
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //拉低
}
else
{
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9|GPIO_PIN_11|GPIO_PIN_13|GPIO_PIN_15,GPIO_PIN_SET); //关闭2,4,6,8
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //拉高
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //拉低
}
}
//点亮/关闭所有
void lightAll_open(uint8_t mode)
{
if(1 == mode)
{
HAL_GPIO_WritePin(GPIOC,0xFF00,GPIO_PIN_RESET); //点亮所有
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //拉高
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //拉低
}
else
{
HAL_GPIO_WritePin(GPIOC,0xFF00,GPIO_PIN_SET); //关闭所有
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_SET); //拉高
HAL_GPIO_WritePin(GPIOD,GPIO_PIN_2,GPIO_PIN_RESET); //拉低
}
}
/*************************TIMER.c*************************/
uint8_t Time2_1s_Flag = 0; //1秒标志位
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim == &htim2) //如果是TIM2产生中断
{
static uint16_t count = 0;
count++;
if(count >= 1000) //1s
{
count = 0;
Time2_1s_Flag = 1;
}
}
}
/*************************main.c*************************/
void main(void)
{
while(1)
{
# if 1
if(Time2_1s_Flag)
{
LED_Dis1();
Time2_1s_Flag = 0;
}
# endif
}
}
实验现象