The previous section talked about the continuous stepping trigger function of holding down an independent button. This section will teach you how to achieve accelerated uniform speed triggering of the button with slight modifications based on the previous section.
For details, please see the source code.
(1) Hardware platform: Based on Zhu Zhaoqi 51 single-chip computer learning board. Use the S1 and S5 keys in the matrix keyboard as independent keys. Remember to keep the output line P0.4 output low level to simulate the trigger ground GND of the independent keys.
(2) Function implementation: Two independent buttons S1 and S5, S1 is used as the plus button. S5 is used as the minus button. Each time the S1 button is pressed, the set parameter uiSetNumber will increase by 1. If the S1 button is held down for more than 1 second, the set parameter uiSetNumber will increase by 1 at increasingly faster time intervals. This is called the acceleration trigger function. Until the limit value is reached, it will increase by 1 at a fixed speed. This process is called uniform speed. S5 is used as a subtraction button. Each time it is triggered, uiSetNumber will decrease by 1. Its acceleration and uniform speed trigger functions are the same as those of the S1 button. When the set parameter uiSetNumber is less than 500, the LED light goes out; when it is greater than or equal to 500, the LED light comes on. It should be noted that:
Step 1: Each time you press the button, it triggers a single click. If the time from pressing to releasing the button does not exceed 1 second, it will not enter the continuous acceleration trigger mode.
Step 2: If you hold the button pressed for more than 1 second, the button will enter the continuous acceleration trigger mode. The button trigger rhythm keeps getting faster and faster, and the buzzer beep rhythm keeps getting faster and faster. Until they both reach a limit value, and then they are triggered at a uniform speed at this limit value interval. At the beginning of acceleration, the steps of button triggering and buzzer triggering are consistent. When either of them reaches the limit value, the rapid sound is inconsistent with the button triggering. The button is not triggered every time the buzzer sounds. In fact, at the end of acceleration, the button triggering speed is much faster than the buzzer triggering speed.
(3) The source code is explained as follows:
#include "REG52.H"
#define const_voice_short 40 //Duration of the buzzer short call
#define const_key_time1 20 //Key debounce delay time
#define const_key_time2 20 //Key debounce delay time
#define const_time_1s 444 //Number of timer interrupts required for 1 second
#define const_initial_set 160 //In continuous trigger mode, the interval trigger time when the button is just pressed
#define const_min_level 30 //In continuous trigger mode, after the key is accelerated, if it is found to be less than this value, it will directly change to the last interval trigger time
#define const_sub_dt 10 //The "acceleration" of the key, which is equivalent to the change in the key interval time each time
#define const_last_min_set 5 //In continuous trigger mode, the last interval trigger time after the key is accelerated
#define const_syn_min_level 45 //The minimum threshold for generating synchronous sound. This time must be slightly longer than the buzzer time.
void initial_myself();
void initial_peripheral();
void delay_long(unsigned int uiDelaylong);
void T0_time(); //Timer interrupt function
void key_service(); //Key service application
void key_scan(); //The key scan function is placed in the timer interrupt
void led_run(); //LED light application
sbit key_sr1=P0^0; //Corresponding to the S1 key of Zhu Zhaoqi learning board
sbit key_sr2=P0^1; //Corresponding to the S5 key of Zhu Zhaoqi learning board
sbit key_gnd_dr=P0^4; //Simulate the ground GND of the independent key, so it must always output a low level
sbit beep_dr=P2^7; //Buzzer driver IO port
sbit led_dr=P3^5; //LED driver IO port
unsigned char ucKeySec=0; //The key number that is triggered
unsigned int uiKeyTimeCnt1=0; //Key debounce delay counter
unsigned int uiKeyCtntyCnt1=0; //Interval delay counter for continuous key triggering
unsigned char ucKeyLock1=0; // variable flag for self-locking after key triggering
unsigned int uiSynCtntyCnt1=0; //Counter for generating key synchronization sound
unsigned int uiCtntyTimeSet1=const_initial_set; //The time interval between each button trigger. This value keeps getting smaller, resulting in a faster speed.
unsigned int uiCtntySynSet1 = const_initial_set; //Time interval for synchronizing sound, this value keeps getting smaller, resulting in faster speed
unsigned char ucCtntyFlag1=0; //Whether it is in the continuous acceleration trigger mode flag
unsigned int uiKeyTimeCnt2=0; //Key debounce delay counter
unsigned int uiKeyCtntyCnt2=0; //Interval delay counter for continuous key triggering
unsigned char ucKeyLock2=0; //Variable flag for self-locking after key triggering
unsigned int uiSynCtntyCnt2=0; //Counter for generating key synchronization sound
unsigned int uiCtntyTimeSet2 = const_initial_set; //The time interval between each button trigger. This value keeps getting smaller, resulting in a faster speed.
unsigned int uiCtntySynSet2 = const_initial_set; //Time interval for synchronizing sound. This value keeps getting smaller, causing the speed to keep getting faster.
unsigned char ucCtntyFlag2=0; //Whether it is in the continuous acceleration trigger mode flag
unsigned int uiVoiceCnt=0; //Buzzer beeping duration counter
unsigned int uiSetNumber=0; //Set data
void main()
{
initial_myself();
delay_long(100);
initial_peripheral();
while(1)
{
key_service(); //Key service application
led_run(); //LED lamp application
}
}
void led_run() //LED light application
{
if(uiSetNumber<500) //If the set parameter uiSetNumber is less than 500, the LED light will be off. Otherwise, it will be on.
{
led_dr=0; // off
}
else
{
led_dr=1; //light up
}
}
void key_scan()//The key scan function is placed in the timer interrupt
{
/* Note 1:
* Independent buttons to continuously speed up the scanning process:
* Step 1: Each time you press the button, it triggers a single click. If the time from pressing to releasing the button does not exceed 1 second, it will not enter the continuous acceleration trigger mode.
* Step 2: If you hold down the button for more than 1 second, the button will enter the continuous acceleration trigger mode. The button trigger rhythm will continue to accelerate, and the buzzer will sound faster and faster.
* also speeds up. Until they all reach a limit, and then trigger at a constant speed at this limit interval. At the beginning of acceleration, the key trigger and
* The steps of buzzer triggering are consistent. When any of them reaches the limit value, the rapid sound is inconsistent with the triggering of the button.
* Each time the buzzer sounds, the button is triggered. In fact, at the end of the acceleration, the button triggering speed is much faster than the buzzer triggering speed.
*/
if(key_sr1==1)//IO is high level, indicating that the key is not pressed, then some flags should be cleared in time
{
ucKeyLock1=0; //key self-locking flag cleared
uiKeyTimeCnt1=0; //The key de-bounce delay counter is cleared. This line is very clever and I figured it out in actual combat.
uiKeyCtntyCnt1=0; //The time delay counter of the continuous acceleration of the key is cleared
uiSynCtntyCnt1=0; //The time delay counter of the buzzer's continuous acceleration is cleared
uiCtntyTimeSet1=const_initial_set; //The initial time interval between each button trigger. This value keeps getting smaller, resulting in a faster speed.
uiCtntySynSet1=const_initial_set; //The initial value of the time interval for the synchronized sound. This value keeps getting smaller, causing the chirping rhythm to keep getting faster.
}
else if(ucKeyLock1==0)//A key is pressed, and it is the first time it is pressed
{
uiKeyTimeCnt1++; //Accumulate the number of timer interrupts
if(uiKeyTimeCnt1>const_key_time1)
{
uiKeyTimeCnt1=0;
ucKeyLock1=1; //Set the self-locking key to avoid continuous triggering
ucCtntyFlag1=0; //Continuous acceleration trigger mode flag 0 represents single click 1 represents continuous acceleration trigger
ucKeySec=1; //Trigger key 1
}
}
else if(uiKeyTimeCnt1 { uiKeyTimeCnt1++; } else //If you hold the button for 1 second, the rhythmic acceleration will start. { uiKeyCtntyCnt1++; //Key continuously triggers the delay counter to accumulate //Press and hold, the button will be triggered once every uiCtntyTimeSet1 time, and the speed will get faster and faster as uiCtntyTimeSet1 keeps decreasing if(uiKeyCtntyCnt1>uiCtntyTimeSet1) { if(uiCtntyTimeSet1>const_min_level) { uiCtntyTimeSet1=uiCtntyTimeSet1-const_sub_dt; //uiCtntyTimeSet1 keeps decreasing, the speed is getting faster and faster } else { uiCtntyTimeSet1=const_last_min_set; //uiCtntyTimeSet1 keeps decreasing and reaches a limit value } uiKeyCtntyCnt1=0; ucCtntyFlag1=1; //Enter continuous acceleration trigger mode ucKeySec=1; //Trigger key 1 } uiSynCtntyCnt1++; //Buzzer continuously triggers delay counter accumulation //If you hold down the button and don't release it, the buzzer will be triggered once every uiCtntySynSet1 time. As uiCtntySynSet1 decreases, the buzzing rhythm will become faster and faster. if(uiSynCtntyCnt1>uiCtntySynSet1) { uiCtntySynSet1=uiCtntySynSet1-const_sub_dt; //uiCtntySynSet1 keeps decreasing, and the chirping rhythm becomes faster and faster if(uiCtntySynSet1 { uiCtntySynSet1=const_syn_min_level; //uiCtntySynSet1 keeps decreasing and reaches a limit value } uiVoiceCnt=const_voice_short; //Key press triggers the sound, stops after one beep. uiSynCtntyCnt1=0; } } if(key_sr2==1) { ucKeyLock2=0; uiKeyTimeCnt2=0; uiKeyCtntyCnt2=0; uiSynCtntyCnt2=0; uiCtntyTimeSet2=const_initial_set; uiCtntySynSet2=const_initial_set; } else if(ucKeyLock2==0) { uiKeyTimeCnt2++; if(uiKeyTimeCnt2>const_key_time2) { uiKeyTimeCnt2=0; ucKeyLock2=1; ucCtntyFlag2=0; ucKeySec=2; } } else if(uiKeyTimeCnt2 { uiKeyTimeCnt2++; } else { uiKeyCtntyCnt2++; if(uiKeyCtntyCnt2>uiCtntyTimeSet2) { if(uiCtntyTimeSet2>const_min_level) { uiCtntyTimeSet2=uiCtntyTimeSet2-const_sub_dt; } else { uiCtntyTimeSet2=const_last_min_set; } uiKeyCtntyCnt2=0; ucCtntyFlag2=1; ucKeySec=2; } uiSynCtntyCnt2++; if(uiSynCtntyCnt2>uiCtntySynSet2) { uiCtntySynSet2=uiCtntySynSet2-const_sub_dt; if(uiCtntySynSet2 { uiCtntySynSet2=const_syn_min_level; } uiVoiceCnt=const_voice_short; uiSynCtntyCnt2=0; } } } void key_service() //Application for the third zone key service { switch(ucKeySec) //Key service status switch { case 1:// Continuous key addition of key 1 corresponds to the S1 key of Zhu Zhaoqi learning board uiSetNumber++; //The set parameters are continuously increased if(uiSetNumber>1000) //The maximum is 1000 { uiSetNumber=1000; } if(ucCtntyFlag1==0) //If the button is clicked, the buzzer will sound, otherwise the buzzer will sound in the key scan key_scan { uiVoiceCnt=const_voice_short; //Key press triggers the sound, stops after one beep. } ucKeySec=0; //After responding to the key service handler, the key number is cleared to avoid consistent triggering break; case 2:// The 2nd key is used for continuous reduction, corresponding to the S5 key of the Zhu Zhaoqi learning board /* Note 2: * In the C language compiler of the microcontroller, when the unsigned data 0 is subtracted from 1, it will overflow and become the maximum value of this type of data. * For example, 0 minus 1 of unsigned int equals 65535 (0xffff), and 0 minus 1 of unsigned char equals 255 (0xff) */ uiSetNumber--; //The set parameter is continuously reduced if(uiSetNumber>1000) //The minimum is 0. Why is 1000 used here? Because 0 minus 1 overflows and becomes 65535 (0xffff) { uiSetNumber=0; } if(ucCtntyFlag2==0) //If the button is clicked, the buzzer will sound, otherwise the buzzer will sound in the key scan key_scan { uiVoiceCnt=const_voice_short; //Key press triggers the sound, stops after one beep. } ucKeySec=0; //After responding to the key service handler, the key number is cleared to avoid consistent triggering break; } } void T0_time() interrupt 1 { TF0=0; //Clear interrupt flag TR0=0; //Disable interrupt key_scan(); //Key scanning function if(uiVoiceCnt!=0) { uiVoiceCnt--; //Every time the timer interrupt is entered, it will be decremented by 1 until it is equal to zero. Then the beeping will stop. beep_dr=0; //The buzzer is controlled by a PNP transistor and starts beeping when the voltage level is low. } else { ; //Add an extra empty instruction here to maintain symmetry with the number of if bracket statements, both are two instructions. It is also OK not to add it. beep_dr=1; //The buzzer is controlled by a PNP transistor, and it stops beeping when the level is high. } TH0=0xf8; //Reinstall initial value (65535-2000)=63535=0xf82f TL0=0x2f; TR0=1; //Open interrupt } void delay_long(unsigned int uiDelayLong) { unsigned int i; unsigned int j; for(i=0;i { for(j=0;j<500;j++) //Number of empty instructions in the embedded loop { ; //A semicolon is equivalent to executing an empty statement } } } void initial_myself() //Initialize the MCU in the first zone { /* Comment 3: * The matrix keyboard can also be used as an independent key, provided that one of the common output lines outputs a low level. * Simulate the triggering ground of an independent key. In this program, key_gnd_dr is outputted at a low level. * The S1 and S5 buttons of Zhu Zhaoqi 51 learning board are the two independent buttons used in this program. */ key_gnd_dr=0; //Simulate the ground GND of the independent key, so it must always output a low level beep_dr=1; //Use PNP transistor to control the buzzer, it will not sound when the output is high level. led_dr=0; //LED light off TMOD=0x01; //Set timer 0 to working mode 1 TH0=0xf8; //Reinstall initial value (65535-2000)=63535=0xf82f TL0=0x2f; } void initial_peripheral() // Initialize the periphery of the second zone { EA=1; //Open the general interrupt ET0=1; //Enable timer interrupt TR0=1; //Start timing interrupt } Closing remarks: So far, we have spent 8 sections to explain the scanning procedure of independent keys. If it is a matrix keyboard, how should we write the program? For details, please listen to the next analysis - the single trigger of the matrix keyboard.
Previous article:Section 12: Continuous stepping triggering by holding down a single button
Next article:Section 15: Compressed code programming for single trigger of matrix keyboard
- 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
- Please recommend, is there any domestic dual-channel H-bridge that can drive motors with an operating voltage of 12V or above?
- How to install and use pressure transmitter
- The flashing prompt cannot recognize the device. What's going on?
- Model-Based Design and Its Embedded Implementation
- Q&A on Connectivity: Why Wi-Fi 6 Could Be Your Competitive Advantage
- Why do we need to learn transistor circuits when we already have integrated circuits?
- 2. Hardware Introduction and Development Environment Installation
- 【New Year's Festival Competition】+ Watching Lanterns on the Lantern Festival (multiple photos)
- 5G small base stations are under the spotlight: now is the eve of the outbreak
- 【CH579M-R1】+ PWM breathing light