当前位置:网站首页>STM32 key chattering elimination - entry state machine thinking

STM32 key chattering elimination - entry state machine thinking

2022-07-06 00:32:00 Hua Weiyun

In embedded software development , State machine programming is a very important programming idea , It is also a common programming framework in embedded development . Master the programming idea of state machine , It can realize complex business logic functions more logically .

1 State machine thinking

State machine , Or finite state machine FSM(Finite State Machine), Is an important programming idea .

The state machine has 3 elements : state event And Respond to

  • state : What state is the system in ?

  • event : What is going on? ?

  • Respond to : In this state, something like this happens , How does the system handle ?

Before state machine programming , First, according to the functions to be realized , Sort out a corresponding state transition diagram ( The state machine diagram ), Then you can use this state transition diagram , Apply the state machine programming template , The implementation corresponds to the state machine code .

State machine programming mainly includes 3 Methods :switch-case Law Table driven method Function pointer method , This article first introduces the simplest and easiest to understand switch-case Law .

2 State machine instance

The following is the key shake elimination function , To introduce switch-case Law State machine programming ideas .

2.1 Button anti shake state transition diagram

Before state machine programming , First of all, the state machine corresponding to the function needs several states , The key function of this example , Only the most basic pressed and released states are detected ( Long press will not be realized for the time being 、 Double click status ), And add the corresponding button de dithering function , therefore , Need to use 4 Status :

  • Stable release state

  • Press jitter status

  • Steady press state

  • Release the jitter state

The corresponding state transition diagram is as follows :

Because the key is usually released , Here, let the initialization state of the state machine be the released state , And here 4 Switch back and forth between states .

In the picture VT Represents the level detected by the key ,VT=0 That is, low level is detected , It may be a key press , From the initial “ Stable release ” The state changes to “ Press jitter ” state

When a low level is continuously detected (VT=0) After a while , It is considered that the chattering elimination is completed , from “ Press jitter ” The state changes to “ Press steadily ” state

stay “ Press jitter ” In the state of , Within a specified period of time , High level detected again (VT=1), It shows that the button jitters ( For example, the key is quickly pushed and then bounced up , Or key jitter caused by strong vibration ), By “ Press jitter ” The state changes to “ Stable release ” state

2.2 Programming to realize

2.2.1 State definition

Corresponding to the above button state diagram , You know you need to use 4 Status :

  • Stable release state (KS_RELEASE)

  • Press jitter status (KS_PRESS_SHAKE)

  • Steady press state (KS_PRESS)

  • Release the jitter state (KS_RELEASE_SHAKE)

Enumerations are used here to define this 4 Status . For debugging , The corresponding state name can be printed in the form of string , Use here Macro definition A little trick for :

# Symbol + Custom enumeration name 

It can be automatically converted to string form , Then put these strings into const char* key_status_name[] Array , You can access the string name form of these states in the form of an array .

Besides , In order not to repeatedly write the enumeration name and the corresponding enumeration string (#+ Enumeration name ), Further use of macro definitions , Define the state only once , Then define the following two macros , Realize to Enumeration item and The string corresponding to the enumeration item Separate acquisition of :

#define ENUM_ITEM(ITEM) ITEM,#define ENUM_STRING(ITEM) #ITEM,

Specifically, the macro definition 、 The enumeration definition and enumeration name array are declared as follows :

#define ENUM_ITEM(ITEM) ITEM,#define ENUM_STRING(ITEM) #ITEM,​#define KEY_STATUS_ENUM(STATUS)                   \    STATUS(KS_RELEASE)       /* Stable release state */       \    STATUS(KS_PRESS_SHAKE)   /* Press jitter status */       \    STATUS(KS_PRESS)         /* Steady press state */       \    STATUS(KS_RELEASE_SHAKE) /* Release the jitter state */       \    STATUS(KS_NUM)           /* The total number of States ( Invalid state )*/  \    typedef enum{    KEY_STATUS_ENUM(ENUM_ITEM)}KEY_STATUS;​const char* key_status_name[] = {    KEY_STATUS_ENUM(ENUM_STRING)};

Macro definitions are difficult to understand , Macro definitions can be brought into , To the final result , Understand the specific form after replacement , For example, the following macro definitions are used to carry in the replacement diagram :

/*KEY_STATUS_ENUM(STATUS) --> STATUS(KS_RELEASE) ... STATUS(KS_NUM)​KEY_STATUS_ENUM(ENUM_ITEM)--> ENUM_ITEM(KS_RELEASE) ... ENUM_ITEM(KS_NUM)--> KS_RELEASE, ... KS_NUM,​KEY_STATUS_ENUM(ENUM_STRING)--> ENUM_STRING(KS_RELEASE) ... ENUM_STRING(KS_NUM)--> #KS_RELEASE, ... #KS_NUM,*/

2.2.2 State machine implementation

The following is the implementation of the state machine :

  • State machine function key_status_check In a cycle , Every 10ms Call once

  • Define a g_keyStatus Indicates the state of the state machine

  • In each cycle ,switch According to the current state , Execute the logic required by the corresponding state

  • Define a g_DebounceCnt It is used to calculate the buffeting time , When it continues to enter the de chattering state , Each cycle (10ms) Add... To this value 1, Last for a certain number of times (5 Time , namely 50ms), Press or release considered stable , Buffeting complete , Jump to stable direction or stable release state

  • In the execution logic of each state , When it is detected that certain conditions are met , Jump to another state

  • Through the continuous jump of state , Realize the running of state machine

  • Besides , For the convenience of observing the change of state in the state machine , Defined a g_lastKeyStatus Indicates the previous status , When the state changes , You can print out the status name

KEY_STATUS g_keyStatus = KS_RELEASE; // The status of the current key KEY_STATUS g_lastKeyStatus = KS_NUM; // Last state int g_DebounceCnt = 0; // Buffeting time count ​void key_status_check(){    switch(g_keyStatus)    {        // Key release ( The initial state )        case KS_RELEASE:        {            // Low level detected , First, eliminate the chattering             if (KEY0 == 0)            {                g_keyStatus = KS_PRESS_SHAKE;                g_DebounceCnt = 0;            }        }        break;                // Press jitter         case KS_PRESS_SHAKE:        {            g_DebounceCnt++;                        // It's really jittery             if (KEY0 == 1)            {                g_keyStatus = KS_RELEASE;            }            // Buffeting complete             else if (g_DebounceCnt == 5)            {                g_keyStatus = KS_PRESS;                printf("=====> key press\r\n");            }        }        break;                // Press steadily         case KS_PRESS:        {            // High level detected , First, eliminate the chattering             if (KEY0 == 1)            {                g_keyStatus = KS_RELEASE_SHAKE;                g_DebounceCnt = 0;            }        }        break;                // Release the jitter         case KS_RELEASE_SHAKE:        {            g_DebounceCnt++;                        // It's really jittery             if (KEY0 == 0)            {                g_keyStatus = KS_PRESS;            }            // Buffeting complete             else if (g_DebounceCnt == 5)            {                g_keyStatus = KS_RELEASE;                printf("=====> key release\r\n");            }        }        break;                default:break;    }        if (g_keyStatus != g_lastKeyStatus)    {        g_lastKeyStatus = g_keyStatus;        printf("new key status:%d(%s)\r\n", g_keyStatus, key_status_name[g_keyStatus]);    }}​int main(void){       delay_init();       // Delay function initialization          KEY_Init();    uart_init(115200);    printf("hello\r\n");        while(1)    {        key_status_check();        delay_ms(10);    }}

notes : This routine requires the use of a key , You need to initialize the corresponding GPIO, No more code here .

2.3 Use tests

Compile and burn the complete code into the board , Connect the serial port , Press and release the key , Observe the serial port output information .

My test output information is as follows :

The first two toggles the button to simulate the shaking of the button , You can see that the serial port prints two state switches from release to press jitter .

Then press the key , Release the button again , You can see the change of state : Release -> Press jitter -> Press down -> Release the jitter -> Release

3 summary

This paper introduces the programming implementation of state machine commonly used in embedded software development , And by pressing the key to eliminate the shaking instance , In common use switch-case form , The corresponding state machine programming code is implemented , And pass the test , Serial port print corresponding status , Analyze the state jump process of the state machine .

原网站

版权声明
本文为[Hua Weiyun]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207060023327985.html