状态机介绍

状态机一般指有限状态机,简称 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
    }
}

实验现象