introduction
In existing textbooks and related articles, the concept of saving the status of custom "bits" in microcontroller C language programming is rarely mentioned.
When the concept of "bit" is mentioned in C language programming of single-chip microcomputers, people will naturally think of the two user general flag bits F0 of PSW.5 and F1 of PSW.1 in the status word PSW. These two flag bits can participate in Boolean operations and "bit" control operations, and can also be saved with the status word PSW. However, this point is often overlooked: in some specific cases, such as in the interrupt service program programmed in C language, the operation of the two user flag bits F0 of PSW.5 and F1 of PSW.1 in the status word PSW may be invalid. For example:
void EX1_ISR() interrupt 2 {//External interrupt 1
static unsigned int tempaddr; //define the receiving address cache
static unsigned int tempkey; //define receive data cache
unsigned int timecnt;
timecnt=TH1*256+TL1;
TH1=0;
TL1=0;
TR1=1; //Timer 1 starts
F0=~F0; //Invert F0
if(F0) {
tempaddr=tempaddr<<1;
}
else {
tempkey=tempkey<<1;
}
}
The above is an interrupt service program for the external interrupt 1 of the microcontroller. At first glance, it seems that there is no problem, and it can be "edited" during simulation debugging. But in fact, this is an incorrect program - the "inversion" operation of the "F0" user flag bit cannot achieve its expected effect. Because the "inversion" operation of the "F0" user flag bit is performed in the interrupt service program. When entering the interrupt, the C language will automatically protect the "interrupt scene" - push the program pointer PC, accumulator ACC, status word PSW, etc. into the stack for protection... until the interrupt returns, the stack is popped out and the variable value during the interrupt service is overwritten, and it is restored to the original state before the stack was pushed. Therefore, F0 in the status word PSW is no exception. If F0 is in the logical "0" state before being pushed into the stack, it will still be restored to the logical "0" state after the interrupt returns - no matter how the inversion is changed in the interrupt service program - that is, the operation of trying to change the value of F0 in the interrupt service program is biased. For the interrupt service program mentioned above, if the initial state of F0 is logic "0", that is, it is always logic "0" before entering the interrupt service and after the interrupt returns, then after entering the execution of the "F0=~F0" instruction, F0 is always logic "1", so the next instruction to be executed is the "tempaddr=tempaddr<<1;" instruction in the curly braces under "if(F0)", and the "tempkey=tempkey<<1" instruction in the curly braces under "else" will never be executed. Therefore, if the interrupt service program is to achieve the expected effect - the instructions in the curly braces under "if(F0)" and the instructions in the curly braces under "else" are run in turn, a custom flag bit that is not affected by interrupt scene protection, etc. must be set.
1. Saving of custom flag "bit"
In C language programming, the use of custom flags is very likely, and some programs may have many custom flags, and some of them may have to be saved. For example, some control devices maintain some control states, and even if the power is turned on again after a power outage, the control state can still remain unchanged - this involves the issue of preservation.
Example 2: We once made a wireless remote control device for raising and lowering the laser projection screen. This control device with a single-chip microcomputer as the core and the scrolling motor for raising and lowering the screen are all installed and fixed in a narrow iron barrel with a diameter of less than 50 mm, so it is very troublesome to install or remove it. In order to succeed at one time - to avoid the trouble of disassembling and installing again, I deliberately used a custom flag bit when programming in C language - the flip flag bit "switch_sign". Because the key signs of the up "▲", pause "■", and down "▼" on the wireless remote control handle are already fixed, therefore, if due to wiring errors, the projection screen rolls up when the down "▼" key is pressed, and the projection screen extends downward when the up "▲" key is pressed... With the custom flag bit "switch_sign", there is no need to worry about these. The relevant C language program segment is as follows:
#defineuint unsigned int
#defineuchar unsigned char
uint Decode_addr, Decode_key, addr;
sbit JD1_out=P0^4; //define relay 1 control output terminal
sbit JD2_out=P0^5; //define relay 2 control output terminal
sbit BEEP=P0^3; //define beep sound output
bit bdata switch_sign; //Custom flip flag (should be defined as a global variable)
void Telecontrol_Data() {
…
if(Decode_addr==0x5535) {//Address code check
if(Decode_key==0x00C0) {//“▲” key code check
BEEP=1; //Buzzer sound output
if(switch_sign) {//Flip the flag
JD1_out=0; //Relay 1 control output
JD2_out=1; //Relay 2 control output
}
else {
JD1_out=1; //Relay 1 control output
JD2_out=0; //Relay 2 control output
}
}
if(Decode_key==0x0030) {//“■” key code check
BEEP=1; //Buzzer sound output
JD1_out=0; //Relay 1 control output
JD2_out=0; //Relay 2 control output
}[page]
if(Decode_key==0x000C) {//“▼” key code check
BEEP=1; //Buzzer sound output
if(switch_sign) {//Flip the flag
JD1_out=1; //Relay 1 control output
JD2_out=0; //Relay 2 control output
}
else {
JD1_out=0; //Relay 1 control output
JD2_out=1; //Relay 2 control output
}
}
}
if(Decode_addr==0x5D35) {//Address code verification when negating the operation
if(Decode_key==0x00C0) {//“▲” key code check
BEEP=1; //Buzzer sound output
switch_sign=~switch_sign; //Invert the flip flag
save_data(); //Call the subroutine to save data
}
}
}
From the above remote control data processing subroutine, we can see that at any time, only one of the control output terminals JD1_out and JD2_out of the two relays can be turned on. When the remote control "▲" key is pressed effectively, the logic "0" or logic "1" state of the flip flag "switch_sign" will determine whether the control output terminals JD1_out and JD2_out of the two relays are turned on and off, or turned off and on; similarly, when the remote control "▼" key is pressed effectively, the same effect opposite to the "▲" key will be obtained... In other words, as long as the logic state of the flip flag "switch_sign" is changed, the control output state of which of the two relay control output terminals is "on" and which is "off" can be changed. That is, when the same remote control button is pressed (such as the "▲" key is pressed), the logic state of the flag "switch_sign" is different, and the control output state of which of the two relay control output terminals is "on" and which is "off" will also be different. The buzzer sound indicates whether the key operation is valid.
The power motor for lifting the projection screen is an AC 220V AC motor. Figure 1 is a schematic diagram of the motor control circuit. It can be seen that when the relay JD1 is closed and JD2 is disconnected, L1 in the motor M is the main winding and L2 is the starter auxiliary winding, and the motor will run in one direction; when the relay JD1 is disconnected and JD2 is closed, L1 in the motor M is the starter auxiliary winding and L2 is the main winding, and the motor will run in the opposite direction of the original. Combined with the above, change the logical state of the flip flag "switch_sign" → change the control output state of the two relay control output terminals, which is "on" and which is "off" → change the running direction of the motor → the lifting state of the projection screen. In other words, changing the logical state of the flip flag "switch_sign" can correct the running direction of the remote control motor and the lifting state of the projection screen. After coordinating the corresponding relationship between the remote control button and the lifting of the projection screen, the current logical state of the custom flag "switch_sign" must be saved, otherwise, the next power-on reset initialization after power failure may make a fool of yourself again.
From the program in Example 2, we can also see that the inversion operation of the flip flag "switch_sign" is also performed using the "▲" key on the same remote control, but the address code of the remote control has been tampered with a little bit - the address code is changed (0x5D35), and then changed back to the original address code (0x5535) after the corresponding operation is coordinated.
2 Save 1 byte to restore the custom flag "bit"
There are many ways to save and restore a custom flag "bit". I have tried several methods. Example 3 is a method of saving 1 byte to restore a custom flag bit. The specific operation is as follows:
static unsigned char current_dat; //define a general auxiliary byte variable
bit bdata switch_sign; //Custom flip flag (should be defined as a global variable)
…
switch_sign=~switch_sign; // invert the sign bit
if(switch_sign) {//Judge whether switch_sign is logic "1" or logic "0"
current_dat=0xA5; //Assign value to general auxiliary byte variable
}
else {
current_dat=0x00; //General auxiliary byte variable
}
save_data(); //Call the subroutine to save data
BEEP=1; //Buzzer sound output
The above program is: after negating the flip flag "switch_sign", if "switch_sign" is in the logic "1" state, assign "0xA5" to the general auxiliary byte variable "current_dat" (of course, this data is set by you); if "switch_sign" is in the logic "0" state, assign "0x00" to the general auxiliary byte variable "current_dat" (this data is also set by you, as long as it is different from the previous one), and then call the data saving program to save the general auxiliary byte variable "current_dat". In this way, even if the power is off, the current state of the flip flag "switch_sign" has been indirectly saved by the general auxiliary byte variable "current_dat"... When the next power-on reset is initialized, the data of the saved auxiliary variable "current_dat" should be read out first, and restored to the corresponding logical state of the flip flag "switch_sign". When the power is turned on and the data read from the storage is "0xA5", the flip flag "switch_sign" is set to "1"; if the data read is "0x00", the flip flag "switch_sign" is set to "0" - this corresponds to the state when it was originally saved. The operation process is as shown in Example 4:
static unsigned char current_dat; //define a general auxiliary byte variable
static unsigned char addr; //Custom address variable buffer unit
static unsigned char Rdat; //Custom read data buffer unit
bit bdata switch_sign; //Custom flip flag (should be defined as a global variable)
……[page]
addr=0x7F6; //Give an original storage address
REEPROM(); //Call the subroutine to read E2PROM
current_dat=Rdat; //Return the read data to the general auxiliary byte variable
if(current_dat==0xA5) {//Judge whether the read data is equal to "0xA5"
switch_sign=1; //Set the flip flag "switch_sign" to "1"
}
else {
switch_sign=0; //Set the flip flag "switch_sign" to "0"
}
31 bytes to hold 8 custom "bits"
The process of restoring a custom flag bit by saving a custom byte variable has been described above. Next, the solution of saving 8 custom "bits" with a byte variable is described. There are many solutions for saving 8 custom "bits" with a byte variable. Example 5 is a more ideal one:
#defineuint unsigned int
#defineuchar unsigned char
uintaddr;
ucharWdat, Rdat;
uchar bdatacurrent_dat; //define the byte variable current_dat of unsigned char type in the bit-addressable area
sbitsign_bit1 = current_dat^0; //Use the keyword sbit to define a bit variable to independently access 1 bit in the addressable bit object
sbitsign_bit2 = current_dat^1; //Customized flag bit 2
sbitsign_bit3 = current_dat^2; //Customized flag bit 3
…
sbitsign_bit8 = current_dat^7; //Customized flag bit 8
…
void Bit_save() {//Custom flag bit save subroutine
addr = 0x7F6; // give storage address
Wdat = current_dat; // assign current_dat to the buffer unit Wdat of writing E2PROM
save_data(); //Call the save subroutine to store current_dat data
}
void Bit_comeback() {//Custom flag bit reset subroutine
addr=0x7F6; //Give an original storage address
REEPROM(); //Call the subroutine to read E2PROM
current_dat=Rdat;
//Return the read data to the general auxiliary byte variable
}
The above program may be the simplest solution for custom bit operations and their storage. First, define a general byte variable current_dat of ucsigned char type in the bit-addressable area, and then use the keyword "sbit" to define a bit variable to independently access one of the addressable bit objects. In this way, the custom flag bit is raised to a bit-accessible mode similar to that in the special function register (SFR) - the 8 bits in the byte variable current_dat can be operated independently, and its storage or reading and restoration can be done by directly saving or reading the byte variable current_dat, without the need for auxiliary operations such as logical AND, logical OR, etc. as in other solutions.
Conclusion
It is not necessary to have custom flags in C language programming of single-chip microcomputers, but in some cases, using custom flags will make the whole program appear concise and bright. Of course, the preservation of custom flags depends on the specific situation - it should be said that it is a last resort.
Previous article:Transplantation of μC/OS-II on C8051F series MCU
Next article:PLC and multi-machine communication based on RS485 interface Modbus protocol
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- I really want to participate! Learn!!
- I need help with the washing machine course design. Please help me modify the program. Thank you.
- How to protect smart sockets in smart homes?
- Internal structure of GD32
- Comprehensive analysis of RC step-down circuit and its application
- Introduction to PID Control Algorithm and Strategy
- Application of TI PD solutions in the security market
- DSP28335 Peripheral Clock
- EEWORLD University Hall----Live Replay: TI MSP430 low-power analog peripherals help home portable healthcare products
- [Sipeed LicheeRV 86 Panel Review] I Unboxing and Basic Function Test