STM32实战项目 您所在的位置:网站首页 迪文液晶屏程序能读出来吗 STM32实战项目

STM32实战项目

2023-03-12 04:41| 来源: 网络整理| 查看: 265

前言:

本章主要介绍一下,状态机在工程中的应用,下面我会通过这种方式点亮LED灯,来演示他的妙用。

目录

1、状态机应用

1.1流水灯函数

1.1.1led.h

1.1.2led.c

1.2状态机函数

1.2.1定义举常量

1.2.2结构体封装

1、状态机应用

有限状态机是一种概念思想,把复杂的控制逻辑分解成有限个稳定状态,组成闭环系统,通过事件触发,让状态机按设定的顺序处理事务;

单片机C语言的状态机编程,是利用条件选择语句(switch -- case)切换状态,通过函数内部指令改变状态机状态,让程序按设定的顺序执行。

如上图所示:五个状态分别对应五个流程分别对应五种状态,我们可以使用结构体封装,保存五个状态的函数的指针。 

1.1流水灯函数

为了方便程序移植,阅读,我们自己定义源文件 LED.C和头文件LED.H头文件中放,流水灯函数的声明和定义,源文件中放函数的实现。 

1.1.1led.h /¶¨Òåö¾ÙÀàÐÍ typedef enum { LED1 = (uint8_t)0x01, LED2 = (uint8_t)0x02, LED3 = (uint8_t)0x03, }LED_Num_t; //¶¨Òå½á¹¹ÌåÀàÐÍ typedef struct { void (*LED_ON)(uint8_t); //´ò¿ª void (*LED_OFF)(uint8_t); //¹Ø±Õ void (*LED_Flip)(uint8_t); //·­×ª } LED_t; /* extern variables-----------------------------------------------------------*/ extern LED_t LED; 1.1.2led.c static void LED_ON(uint8_t); static void LED_OFF(uint8_t); static void LED_Flip(uint8_t); /* Public variables-----------------------------------------------------------*/ LED_t LED = { LED_ON, LED_OFF, LED_Flip }; static void LED_ON(uint8_t LED_Num) { //Ìõ¼þÑ¡ÔñÓï¾ä switch(LED_Num) { case LED1: HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET); break; case LED2: HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_SET); break; case LED3: HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_SET); break; default: System.Assert_Failed(); } } static void LED_OFF(uint8_t LED_Num) { //Ìõ¼þÑ¡ÔñÓï¾ä switch(LED_Num) { case LED1: HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET); break; case LED2: HAL_GPIO_WritePin(LED2_GPIO_Port,LED2_Pin,GPIO_PIN_RESET); break; case LED3: HAL_GPIO_WritePin(LED3_GPIO_Port,LED3_Pin,GPIO_PIN_RESET); break; default: System.Assert_Failed(); } } static void LED_Flip(uint8_t LED_Num) { //Ìõ¼þÑ¡ÔñÓï¾ä switch(LED_Num) { case LED1: HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin); break; case LED2: HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin); break; case LED3: HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin); break; default: System.Assert_Failed(); } }

 我们可以看到在led.c函数中,我们封装的三个函数指针分别实现了,led的开、关、和翻转,至于ON,OFF,TogglePin 这些都是HAL库自己定义的我们可以看看他的函数实现,如下图所示:

 至于端口和引脚,这个在我们使用cubemax的时候,配置好参数的时候,已经自动初始化完成了。

1.2状态机函数 1.2.1定义举常量

 首先定义五个枚举常量,不同常量对应不同选择,也就会有不同的状态。

//¶¨Òåö¾ÙÀàÐÍ typedef enum { STA1 = (uint8_t)0x01, STA2 = (uint8_t)0x02, STA3 = (uint8_t)0x03, STA4 = (uint8_t)0x04, STA5 = (uint8_t)0x05, } STA_Machine_Status_t; 1.2.2结构体封装

使用结构体封装五个函数指针,方便在运行函数中进行调用,具体代码如下:

//¶¨Òå½á¹¹ÌåÀàÐÍ typedef struct { STA_Machine_Status_t ucSTA_Machine_Status; //״̬»ú״̬ void (*Fun_STA1)(void); void (*Fun_STA2)(void); void (*Fun_STA3)(void); void (*Fun_STA4)(void); void (*Fun_STA5)(void); } STA_Machine_t;

 这五个函数指针指向五个函数,分别实现led的亮灭,所以函数内部又调用了led的函数,具体代码如下:

void Fun_STA1() { HAL_Delay(500); //ÑÓʱ500ms LED.LED_Flip(LED1); //·­×ªLED1,ÃðµÆ LED.LED_Flip(LED2); //·­×ªLED2,ÃðµÆ LED.LED_Flip(LED3); //·­×ªLED3,ÃðµÆ //״̬»úÇл»ÖÁ״̬2 STA_Machine.ucSTA_Machine_Status = STA2; } void Fun_STA2() { HAL_Delay(500); //ÑÓʱ500ms LED.LED_ON(LED1); //LED1ÁÁµÆ LED.LED_OFF(LED2); //LED2ÃðµÆ LED.LED_OFF(LED3); //LED3ÃðµÆ //״̬»úÇл»ÖÁ״̬3 STA_Machine.ucSTA_Machine_Status = STA3; } void Fun_STA3() { HAL_Delay(500); //ÑÓʱ500ms LED.LED_OFF(LED1); //LED1ÃðµÆ LED.LED_ON(LED2); //LED2ÁÁµÆ LED.LED_OFF(LED3); //LED3ÃðµÆ //״̬»úÇл»ÖÁ״̬4 STA_Machine.ucSTA_Machine_Status = STA4; } void Fun_STA4() { HAL_Delay(500); //ÑÓʱ500ms LED.LED_OFF(LED1); //LED1ÃðµÆ LED.LED_OFF(LED2); //LED2ÃðµÆ LED.LED_ON(LED3); //LED3ÁÁµÆ //״̬»úÇл»ÖÁ״̬5 STA_Machine.ucSTA_Machine_Status = STA5; } void Fun_STA5() { HAL_Delay(500); //ÑÓʱ500ms LED.LED_ON(LED1); //LED1ÁÁµÆ LED.LED_ON(LED2); //LED2ÁÁµÆ LED.LED_ON(LED3); //LED3ÁÁµÆ //״̬»úÇл»ÖÁ³õʼ״̬1 STA_Machine.ucSTA_Machine_Status = STA1; }

这样的话一个完整的状态机就完成了,我们软件框架并没有改变,只是将调用的run函数内部进行了修改。整体的框架如下图所示:

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有