A Brief Discussion on the State Machine of the Single-Chip Microcomputer
[Copy link]
When it comes to single-chip microcomputer programming, we have to talk about state machines. As the main framework of software programming, state machines have been applied in various languages, including C language. In a clear and efficient program, there must be a state machine. Flexible application of state machines not only makes the program more efficient, but also has good readability and scalability. States are everywhere, and there are states in states. As long as you master this kind of thinking and make it a habit in your programming, I believe you will benefit a lot.
The state machine can be summarized into 4 elements, namely the current state, conditions, actions, and sub-states. Such an induction is mainly due to the consideration of the inherent causal relationship of the state machine. "Current state" and "conditions" are causes, and "actions" and "sub-states" are results. The detailed explanation is as follows:
① Current state: refers to the current state.
② Conditions: also known as "events". When a condition is met, an action will be triggered, or a state migration will be performed.
③ Action: The action executed after the condition is met. After the action is executed, it can be migrated to a new state or remain in the original state. Actions are not necessary. When the conditions are met, you can also migrate directly to a new state without performing any actions.
④ Sub-state: the new state to be migrated to after the conditions are met. "Sub-state" is relative to "current state". Once the "sub-state" is activated, it will be transformed into a new "current state".
If we further summarize, unify "current state" and "sub-state", and ignore "action" (downgrade), then only two most critical elements remain, namely: state and migration condition.
There are many ways to express state machines. We can use text, graphics or tables to express a state machine.
To give a simple example: in terms of key processing, the keystroke action itself can also be regarded as a state machine. A small keystroke action includes: release, jitter, closure, jitter and re-release. When we open our minds and import the state machine as a thought into the program, we will find an effective shortcut to deal with questions. Sometimes it may be more effective to think about what the program should do with the state machine thinking than with the control process thinking. In this way, the state machine has a more practical function. Without further ado, practice is the only criterion for testing the truth.
Some people may think that the state machine complicates the problem. In fact, people who have done software design have already used state machines invisibly. The following summarizes and introduces several state machines.
The first type: switch case structure state machine
switch().
case1:.
if(not repeatedly execute state 1).
Preparations to be made before entering state 1.
The process of entering state 1.
if(not repeatedly execute state 1).
The process of leaving state 1.
case2:.
....
However, this method cannot effectively predefine all states, nor can it reasonably define the switching process between these states. "State" itself does not have a reasonable definition. It is almost a process-oriented method. However, this method is simple enough and the easiest to accept. The disadvantage is that there is no definition and assignment function of "state", which leads to confusion of states, repeated code for state processing, and even inconsistent processing. According to the concept of OO, state description should be an entity. The second
state machine: ifelse statement structure state machine
This state machine is relatively flexible, but for some large projects, the system software design will be relatively complex.
The above two types of state machines are the most commonly used and are not discussed here. Let's focus on the third type of state machine. The
third state machine: message-triggered state machine
There are many ways to implement this type of state machine, and the forms are diverse, but the four elements of the state machine and the current state, condition, action, and next state remain the same.
The following introduces a message-triggered state machine.
State machine mechanism based on message drive
Principle: Once a message is triggered, the system service function immediately searches for the message and message processing function of the state, and executes the message processing function after finding it
Steps:
1. Add message and message mapping
...
BEGIN_MESSAGE_ MAP(Name,Count): state machine name, message number
ADD_NEW_MSG_ITEM (Msg,OnMsg): message and message processing function
END_MESSAGE_MAP: end
...
2. Register here
BEGIN_Register_Task: header
...
ADD_Register_Task(Name,Count): state machine name, message number
...
END_Register_Task: tail
1. Divide the electronic scale state, and complete the OnMsg message processing function after completing the above steps
Void OnMsg(void)
{
...
}
Description: The above is completed with macros, and the specific macros are defined as follows:
#defineBEGIN_MESSAGE_MAP(Name,Count) constMSG_NODE_TYP MSG_node_Array_##Name[(Count)]={
#define ADD_NEW_MSG_ITEM(Msg,OnMsg) {Msg,OnMsg},
#define END_MESSAGE_MAP };
#define BEGIN_Register_Task const MSG_MAP TaskMap[TotalTask]={
#define ADD_Register_Task(Name,Count) {(MSG_NODE_TYP*)MSG_node_Array_##Name,Count},
#define END_Register_Task };
From the above code, we can see that:
1. Adding messages and message mappings actually defines an array of messages and message processing function pairs to form a table
2. Registering the state machine actually defines the entry of all message pairs arrays as an array to form a table
How is the message executed?
Distributing messages
void Default_DisposeMessage(unsigned char *pMsg)
{
unsigned chari;
unsigned charcount=TaskMap[g_Status].cItemCount;//Locate the status tablefor
(i=0;i<count;i++)
{
if(*pMsg==TaskMap[g_Status].pMsgItems.msg)//See if the message can be matched
{
TaskMap[g_Status].pMsgItems.pMsgFunc();//Execute the message processing function if
foundreturn;
}
}
}
void DispatchMessage(unsigned char*pMsg)
{
if(*pMsg)
{
Default_DisposeMessage(pMsg);
}
}
Core function: message processing centervoid
Message_Dispose_Central(void)
{
BYTE Msg;
while(GetMessage(&Msg)) //Get the message
{
TranslateMessage(&Msg); //Interpret the messageDispatchMessage
(&Msg); //Distribute the message
}
}
|