Buttons are one of the simplest and cheapest ways of human-computer interaction. To achieve effective scanning and processing of one or more buttons, here is my modified code:
The implemented code mainly consists of four parts:
Part 1: Button initialization
void Key_Configuration(void)
{
return;
}
Different configuration methods are required here according to the IC used. I use the 51 core. During the initialization process, the I/O port is quasi-bidirectionally pulled up by default, and the button is valid at a low level, so there is no processing and it jumps out directly.
Part 2: Key level reading
//Only read the initial key level status and further process it in the state machine
static u8 Key_Read(void)
{
if(!READ_KEY1)
return KEY1_PRES;
if(!READ_KEY2)
return KEY2_PRES;
if(!READ_KEY3)
return KEY3_PRES;
if(!READ_KEY4)
return KEY4_PRES;
if(!READ_KEY5)
return KEY5_PRES;
return KEY_NONE;
}
According to the specific environment and function, only one valid level is read each time and there is a priority. From the code, we can see that the order of priority is: KEY1>KEY2>KEY3>KEY4>KEY5. Of course, the number of keys to be used depends on the needs of the project. In theory, any number of independent keys is supported.
Part 3: Key judgment part of the state machine
//state machine
static u8 Key_Scan(void)
{
static u8 state = 0; //Button initialization state
static u8 KEY_LAST=0,KEY_NOW=0; //Record the status of two levels
u8 KEY_VALUE=0;
KEY_NOW = Key_Read(); //Read key value
switch(state)
{
case 0:
{
if(KEY_NOW != KEY_LAST) state = 1; //A key is pressed
}break;
case 1:
{
if(KEY_NOW == KEY_LAST) state = 2; //The key is valid after the fight ends
else state = 0; // considered as accidental touch
}break;
case 2: //After the fight
{
if(KEY_NOW == KEY_LAST) //Still pressed
{
state = 3;
}
else//Release, short press
{
state = 0;
KEY_VALUE = KEY_LAST|KEY_SHORT; //Return key value short press
}
}break;
case 3: //Judge long press or short press
{
if(KEY_NOW == KEY_LAST)
{
static u8 cnt = 0;
if(cnt++ > 120) //1200ms
{
cnt = 0;
state = 4;
KEY_VALUE = KEY_LAST|KEY_LONG; //Return key value long press
}
}
else
{
state = 0;
KEY_VALUE = KEY_LAST|KEY_SHORT; //Return key value short press
}
}break;
case 4://Long press and release detection
{
if(KEY_NOW != KEY_LAST)
state = 0;
}break;
}//switch
KEY_LAST = KEY_NOW; //更新
return KEY_VALUE;
}
This part is also the core code of the whole process. First, three static variables are defined: the key state, the currently read key value KEY_NOW, the last key value KEY_LAST, and the returned valid key value KEY_VALUE. Next, we will study them step by step:
The initial value of state is 0, and the switch and case are entered. The time interval for each case judgment is determined by the fourth part. Here I choose 10ms
Judge 0, as long as the key value recorded last time and the key value read this time do not equal, enter 1. There is another function here, that is, the release detection of short press. This is also the reason why there is no else. Please see state 4 for specific implementation.
Judge 1, the last key value is equal to this key value. Note that KEY_LAST has been updated after case 0, which means that the key value read this time after 10ms is still equal to the last key value. Here we consider it to be a valid press, not caused by accidental touch or interference. In this case, go to 2. Otherwise, return to 0.
Judgment 2, here comes from 1, that is, the key value at this time is valid, here we still judge the last updated KEY_LAST and the new key value read this time, if you don't want to wait, it proves that the hand has been released (single key case). In this way, it is recognized as a short press, the state returns to 0 and returns the key value of the short press, which is 0. If the key has not been released, there is a tendency to long press, enter 3.
Judgment 3 is also very simple. It determines whether the key value has been released. The count starts every time it comes in. It enters once every 10ms, so it is counted as 120 times here, which means it takes 1200ms to meet the conditions and assign the returned key value as a long press. At the same time, it enters 4. Otherwise, it is recognized as a short press and re-enters 0.
Judgment 4, the role of the code here is mainly as a long press release detection, the reason is very simple, the key is not released, then the historical key value and the current key value must be equal and not 0, and after the key is released, the read key value must be 0, which jumps out of state 4.
Part 4: Entity functions and called functions
static void KEY1_ShortHander(void)
{
}
static void KEY1_LongHander(void)
{
}
static void KEY2_ShortHander(void)
{
}
static void KEY2_LongHander(void)
{
}
static void KEY3_ShortHander(void)
{
}
static void KEY3_LongHander(void)
{
}
static void KEY4_ShortHander(void)
{
}
static void KEY4_LongHander(void)
{
}
static void KEY5_ShortHander(void)
{
}
static void KEY5_LongHander(void)
{
}
void Key_Hander(void) //Key handling function
{
u8 KEY_NUM=0;
static u32 LAST=0;
if(Systick_ms-LAST<10) return;
LAST = Systick_ms;
KEY_NUM = Key_Scan(); //Key scan value
if(KEY_NUM == KEY_NONE) return;
//A button is pressed
if(KEY_NUM & KEY_SHORT) //short press
{
if(KEY_NUM & KEY1_PRES)//KEY1_PRES
{
KEY1_ShortHander();
}
else if(KEY_NUM & KEY2_PRES)//KEY2_PRES
{
KEY2_ShortHander();
}
else if(KEY_NUM & KEY3_PRES)//KEY3_PRES
{
KEY3_ShortHander();
}
else if(KEY_NUM & KEY4_PRES)//KEY4_PRES
{
KEY4_ShortHander();
}
else if(KEY_NUM & KEY5_PRES)//KEY5_PRES
{
KEY5_ShortHander();
}
}
else if(KEY_NUM & KEY_LONG) //长按
{
if(KEY_NUM & KEY1_PRES)//KEY1_PRES
{
KEY1_LongHander();
}
else if(KEY_NUM & KEY2_PRES)//KEY2_PRES
{
KEY2_LongHander();
}
else if(KEY_NUM & KEY3_PRES)//KEY3_PRES
{
KEY3_LongHander();
}
else if(KEY_NUM & KEY4_PRES)//KEY4_PRES
{
KEY4_LongHander();
}
else if(KEY_NUM & KEY5_PRES)//KEY5_PRES
{
KEY5_LongHander();
}
}
}
This part of the code is relatively clear. Through the analysis of the previous three parts, the results of the key values are obtained by calling the previous three parts here, and then the results are judged to perform corresponding functions and functional processing. The function body is given directly here, and the user can directly add the corresponding code in the function body. However, a more effective way should be to replace the execution function with a marker variable, so that the program execution will be more organized and will not occupy the time slice incorrectly.
Finally, attach the header file:
#ifndef __FY_KEY_H
#define __FY_KEY_H
#include "fy_includes.h"
#define READ_KEY1 P30
#define READ_KEY2 P14
#define READ_KEY3 P13
#define READ_KEY4 P10
//#define READ_KEY5 P17
#define KEY1_PRES 0x01
#define KEY2_PRES 0x02
#define KEY3_PRES 0x04
#define KEY4_PRES 0x08
#define KEY5_PRES 0x10
#define KEY_SHORT 0x40
#define KEY_LONG 0x80
#define KEY_NONE 0
#define HOT_KEY_PRES KEY1_PRES
#define PWR_KEY_PRES KEY2_PRES
#define H2_KEY_PRES KEY3_PRES
#define MP3_KEY_PRES KEY4_PRES
void Key_Configuration(void);
void Key_Hander(void);
#endif
/*********************************************END OF FILE**********************************************/
Previous article:[MCU Notes] Single button to achieve single click, double click, long press
Next article:[MCU Notes] Power supply design integrating USB charging, USB power supply and battery power supply
Recommended ReadingLatest update time:2024-11-15 18:56
- Popular Resources
- Popular amplifiers
- Wireless Sensor Network Technology and Applications (Edited by Mou Si, Yin Hong, and Su Xing)
- Modern Electronic Technology Training Course (Edited by Yao Youfeng)
- Modern arc welding power supply and its control
- Small AC Servo Motor Control Circuit Design (by Masaru Ishijima; translated by Xue Liang and Zhu Jianjun, by Masaru Ishijima, Xue Liang, and Zhu Jianjun)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- 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
- Sandia Labs develops battery failure early warning technology to detect battery failures faster
- Ranking of installed capacity of smart driving suppliers from January to September 2024: Rise of independent manufacturers and strong growth of LiDAR market
- Industry first! Xiaopeng announces P7 car chip crowdfunding is completed: upgraded to Snapdragon 8295, fluency doubled
- P22-009_Butterfly E3106 Cord Board Solution
- Chinese mobile phones continue to sell well in India, Vivo surpasses Samsung to become the second largest brand
- Share CC2541 Bluetooth learning about ADC
- Summary of frequently asked questions about oscilloscopes (Part 2)
- MSP430 LCD5110 driver programming example
- NUCLEO F446RE meets X-NUCLEO-IKS01A3
- A huge reward! Looking for someone who can crack the RSA2048 and factory protocol in the ECU!
- Family Pet Health Maintenance System
- How to solve the problem that the STM32 does not run at full speed when entering the simulation debugging interface?
- HF Antenna Analyzer(3MHz to 30MHz)
- 1. Previous Power Supply Competition Topics