Execute the scanning program of independent keys in the timed interrupt function -- learning notes of "teach you the program framework of single chip microcomputer by hand - Wu Jianhong"

Posted by buttercupgreen on Mon, 11 Oct 2021 01:19:49 +0200

Disclaimer: This article is my notes on learning "teach you the program framework of single chip microcomputer hand in hand - Wu Jianhong"
Original link: Section 8: execute independent key scanning program in timing interrupt function.

original text

Section 8: execute independent key scanning program in timing interrupt function.

Opening remarks:
In the previous section, the cumulative number of timed interrupts is used to detect independent keys in the main function. However, in some projects, it is necessary to intermittently perform some one-stop time-consuming tasks in the main function. When the main function is processing one-stop time-consuming tasks (provided that the timer interrupt is not turned off), if a key is pressed at this time, It may not be responded in time and missed. This problem can be avoided by processing the scanning program of independent keys in the timed interrupt function. I want to teach you a knowledge point: how to deal with the scanning program of independent keys in the timed interrupt function with slight modifications on the basis of the previous section.

For details, please see the source code explanation.

(1) Hardware platform: Based on Zhu Zhaoqi 51 single chip microcomputer learning board. Use the S1 and S5 keys in the matrix keyboard as independent keys. Remember to output the low level of the output line P0.4 all the time to simulate the trigger GND of the independent keys.

(2) Realization function: there are two independent keys. Each time you press an independent key, the buzzer stops after giving a "drop" sound.

(3) The source code is explained as follows:

#include "REG52.H"

#define const_ voice_ Short 40 / / duration of buzzer short call


/* Note 1:
* Adjust the jitter time threshold to change the trigger sensitivity of the key.
* The time for de dithering is essentially equal to the time for accumulating the number of timing interrupts.
*/
#define const_ key_ Time1 20 / / press the key to remove the jitter delay time
#define const_ key_ Time2 20 / / press the key to remove the jitter delay time

void initial_myself();    
void initial_peripheral();
void delay_long(unsigned int uiDelaylong);
void T0_time();  //Timing interrupt function
void key_service(); //Key service application
void key_scan(); //The key scan function is placed in the timed interrupt

sbit key_sr1=P0^0; //Corresponding to the S1 key of Zhu Zhaoqi's learning board
sbit key_sr2=P0^1; //S5 key corresponding to Zhu Zhaoqi's learning board
sbit key_gnd_dr=P0^4; //Simulate the GND of independent keys, so the low level must be output all the time

sbit beep_dr=P2^7; //Drive IO port of buzzer

unsigned char ucKeySec=0;   //Triggered key number

unsigned int  uiKeyTimeCnt1=0; //Key de jitter delay counter
unsigned char ucKeyLock1=0; //Variable flag of self-locking after key triggering


unsigned int  uiKeyTimeCnt2=0; //Key de jitter delay counter
unsigned char ucKeyLock2=0; //Variable flag of self-locking after key triggering

unsigned int  uiVoiceCnt=0;  //Buzzer duration counter

void main() 
{
  initial_myself();  
  delay_long(100);   
  initial_peripheral(); 
  while(1)  
  { 
      key_service(); //Key service application
  }

}

void key_scan()//The key scan function is placed in the timed interrupt
{  
/* Note 2:
* Detailed process of independent key scanning:
* Step 1: when no key is triggered at ordinary times, the self-locking flag of the key and the de jitter delay counter are always cleared.
* Step 2: once a key is pressed, the de jitter delay counter begins to accumulate in the timing interrupt function before it is accumulated
*         Threshold const_key_time1, if it is caused by external interference or key jitter during this period
*         IO The interface is suddenly triggered to a high level. At this time, the delay counter uiKeyTimeCnt1 is immediately set
*         Cleared, this process is very clever and very effective to remove instantaneous clutter interference. This is what I found out in actual combat.
*         In the future, when the switch sensor is used, it can be interfered by similar methods.
* Step 3: if the time of pressing the key exceeds the threshold const_key_time1, trigger the key to assign the number ucKeySec.
*         At the same time, immediately set the self-locking flag ucKeyLock1 to prevent it from being triggered after holding down the key.
* Step 4: after the key is released, the self-locking flag ucKeyLock1 is cleared in time to prepare for the next self-locking.
* Step 5: the whole process above is the process of identifying the trigger of the falling edge of the key IO port.
*/
 if(key_sr1==1)//IO is high level, indicating that the key has not been pressed. At this time, some flag bits should be cleared in time
 {
    ucKeyLock1=0; //Key self-locking flag reset
        uiKeyTimeCnt1=0;//Press the key to shake and reset the delay counter. This trip is very ingenious, which I found out in practice.      
 }
 else if(ucKeyLock1==0)//A key is pressed and is pressed for the first time
 {
    uiKeyTimeCnt1++; //Cumulative timing interrupt times
    if(uiKeyTimeCnt1>const_key_time1)
    {
       uiKeyTimeCnt1=0; 
       ucKeyLock1=1;  //The self-locking key is set to avoid being triggered all the time
       ucKeySec=1;    //Trigger key 1
    }
 }

 if(key_sr2==1)
 {
    ucKeyLock2=0; 
        uiKeyTimeCnt2=0;
 }
 else if(ucKeyLock2==0)
 {
    uiKeyTimeCnt2++; //Cumulative timing interrupt times
    if(uiKeyTimeCnt2>const_key_time2)
    {
       uiKeyTimeCnt2=0;
       ucKeyLock2=1; 
       ucKeySec=2;     //Trigger key 2
    }
 }

}


void key_service() //Application of key service in zone 3
{
 switch(ucKeySec) //Key service state switching
 {
   case 1:// Key 1 corresponds to key S1 of Zhu Zhaoqi's learning board

             uiVoiceCnt=const_voice_short; //The button sound is triggered and stops with a drop.
             ucKeySec=0;  //After responding to the key service handler, the key number is cleared to avoid consistent triggering
         break;        
   case 2:// Key 2 corresponds to the S5 key of Zhu Zhaoqi's learning board

             uiVoiceCnt=const_voice_short; //The button sound is triggered and stops with a drop.
             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; //Off interrupt

 key_scan(); //Key scan function

 if(uiVoiceCnt!=0)
 {
    uiVoiceCnt--; //Each time the timing interrupt is entered, it will decrease by 1 until it is equal to zero. Just stop singing
        beep_dr=0;  //The buzzer is controlled by PNP triode and starts to sound at low level.
 }
 else
 {
    ; //An empty instruction is added here. To maintain the symmetry with the number of if parenthesis statements, there are two instructions. It's OK not to add it.
          beep_dr=1;  //The buzzer is controlled by PNP triode and stops ringing at high level.
 }


 TH0=0xf8;   //Initial value of reassembly (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<uiDelayLong;i++)
  {
     for(j=0;j<500;j++)  //Number of empty instructions in an embedded loop
         {
            ; //A semicolon is equivalent to executing an empty statement
         }
  }
}


void initial_myself()  //First zone initialization MCU
{
/* Note 3:
* The matrix keyboard can also be used as an independent key, provided that a common output line is output at a low level,
* Simulate the trigger of independent keys. In this program, put the key_gnd_dr output low level.
* The S1 and S5 keys of Zhu Zhaoqi 51 learning board are the two independent keys used in this program.
*/
 key_gnd_dr=0; //Simulate the GND of independent keys, so the low level must be output all the time


 beep_dr=1; //The buzzer is controlled by PNP triode, and the output high level is not called at ordinary times.


 TMOD=0x01;  //Set timer 0 to working mode 1


 TH0=0xf8;   //Initial value of reassembly (65535-2000)=63535=0xf82f
 TL0=0x2f;

}
void initial_peripheral() //The second area initializes the periphery
{
 EA=1;     //On total interrupt
 ET0=1;    //Allow timed interrupt
 TR0=1;    //Start timing interrupt

}

Concluding remarks:
The program in this section has shown the scanner that executes independent keys in the timed interrupt function. I have used the scanning methods mentioned in this section and the previous two sections in the project. I choose different methods according to the focus of the project. The current method is the one I use most. If we want to press the button independently to realize the double-click function similar to the mouse, how do we write the program? For more information, please listen to the next chapter - double click trigger of independent key.

(to be continued, the next section is more exciting. Don't go away)

experiment

Put the scan function into the timer interrupt, which should be the most advanced version of key processing. In this way, there will be no key failure due to too many main function codes. The simulation effect is the same as the previous key experiment:

Topics: Single-Chip Microcomputer