Thoughts on a standalone key scanning program (integrating two algorithms)

Publisher:yunhuiLatest update time:2022-06-27 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

I just started to learn 51 MCU programming recently. When I learned about key scanning, I saw a blog post on the Internet titled "New Key Scanning" written by Etual in 2008. I was very touched. For the introduction and application of key scanning, please refer to the original article. This article is just my thoughts and experience on the program. I can't find the link to the original article, so I'll reprint it here:


http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4308630&bbs_page_no=1&search_mode=4&search_text=atommann&bbs_id=9999


http://blog.21ic.com/user1/379/archives/2010/68144.html


http://blog.ednchina.com/zp2009/983530/Message.aspx


The main parts of the source program are as follows:


volatile unsigned char Trg;    

volatile unsigned char Cont;    

volatile unsigned char Release;    

  

void KeyRead( void )    

{    

  unsigned char ReadData = PINB^0xff; // 1 read key value   

  Trg = ReadData & (ReadData ^ Cont); // 2 Get the press trigger value   

  Release = (ReadData ^ Trg ^ Cont); // 3 Get the release trigger value   

  Cont = ReadData; // 4 Get all unreleased key values   

   

First of all, I felt that the logic of the program could be optimized, so I took the initiative to use the logic optimization method on digital circuits.


void KeyRead( void )    

{    

  unsigned char ReadData = (~PINB)&0xff; // 1 read key value   

  Trg = (~Cont) & ReadData; // 2 Get the press trigger value   

  Release = Cont & (~ReadData); // 3 Get the release trigger value   

  Cont = ReadData; // 4 Get all unreleased key values   

}    


This will help you better understand the meaning of Trg, Release, and cont. Take Trg as an example. It is 1 only when Cont=0 and ReadData=1, which corresponds to the rising edge of the ReadData waveform (because ReadData is inverted, the rising edge corresponds to the falling edge of the IO port waveform when the key is pressed).



Since it is to be used on a 51 board, the program has been modified accordingly. Four independent buttons are used here, corresponding to P1.0-P1.3 of P1 port. At the same time, the names of the variables are changed for easier understanding.


Trig---KeyPressDown represents the edge corresponding to the key being pressed.


ReadData---CurrKey The key value currently read is inverted, so that when the key is pressed, the corresponding bit is 1.


Cont -----LastKey The last key value


Release-----KeyRelease The edge corresponding to when the key is released


The program after modification to 51 is


#define KEYMASK 0x0f  

//Button variables  

unsigned char KeyPressDown = 0x00;  

unsigned char KeyRelease=0x00;  

unsigned char LastKey=0x00;  

  

//Scan the buttons, execute once every 10ms  

void KeyScan(void)  

{     

    //The key value currently read  

    unsigned char CurrKey;  

    P1|=KEYMASK; //Set the IO corresponding to the key to input status  

    CurrKey=(~P1)&KEYMASK;  

  

    KeyPressDown=(~LastKey)&CurrKey;  

    KeyRelease=LastKey&(~CurrKey);  

  

    LastKey=CurrKey;  

}  


In order to test the program, I didn't think of a good way. I counted the keys with my eyes closed, counted the KeyPressDown, and then used the digital tube to display the count value. If I pressed 100 times, the digital tube should also display 100. But I tried all four keys, and there were several more than 100. I used an oscilloscope to look at the waveform of the IO port. In most cases, the waveform is a rectangular wave. Only in some cases, there will be an interference pulse (that is, jitter) at the moment of pressing or releasing. The program uses 10ms timing sampling. Since there is no correlation between the two, if the sampling happens to be at the moment of the interference pulse, this may cause the key to trigger multiple events in one key press.


If the key IO port is seriously interfered or the key contact is poor, a negative pulse may be generated when the key is not pressed, or a positive pulse may appear when the key is pressed steadily. Such a pulse may not be very wide, but once it is detected and sampled by the 10ms timing sampling of the program, it will cause a false trigger operation. Increasing the sampling time can reduce the probability, but it cannot be avoided.



In order to improve the algorithm and solve the problem of false triggering caused by interference pulses, I searched the Internet for a long time and finally found a blog post "A method of removing key jitter with software" and used it as a reference.


http://blog.csdn.net/meiyuli/article/details/5133708


http://z86k.blog.163.com/blog/static/90796156200962012657976/


The core algorithm is


Keradyn=Ktemp Kinput+Kreadyn-1 (Ktemp ⊙Kinput) (1)


Ktemp=Kinput (2)


To facilitate understanding, the variable names were modified again and additional variables were added. 


LastReadKey represents the key value read by the last KeyScan() sampling


CurrReadKey; //Record the key value read by this KeyScan() sampling


LastKey represents the key value of the last valid judgment (the actual key value after logical judgment or correction)


CurrKey represents the effective judgment key value of this time.


According to the logical


CurrKey=(CurrReadKey&LastReadKey)|LastKey&(CurrReadKey^LastReadKey) (1)


Determine CurrKey: If the key values ​​read by the last LastReadKey and the current CurReadKey are both 1, then the current valid key value CurrKey must be 1; if the key values ​​read last and currently are different, then they are consistent with the last valid key value LastKey. This method is used to eliminate interference pulses.


The algorithm requires that the width of the interference pulse must be less than the program timing sampling period. If the program timing sampling is 20ms, then the interference pulse width must be less than 20ms. In fact, if the IO key interference pulse is greater than 20ms, it is necessary to consider whether there is a problem with the hardware design, or a filter capacitor should be connected to the key IO port.


Finally, the program after integrating the two algorithms is given


//Button variables  

unsigned char KeyPressDown = 0x00;  

unsigned char KeyRelease=0x00;  

unsigned char LastKey=0x00;  

  

//Scan the buttons, execute once every 10ms  


void KeyScan(void)  

{     

    static unsigned char LastReadKey=0x00; //Record the IO port key value read by KeyScan() last time  

    unsigned char CurrReadKey; //Record the IO port key value read by KeyScan() this time  

    unsigned char CurrKey; //Record the effective key value after debounce processing   

  

    P1|=KEYMASK; //Set the IO corresponding to the key to input status  

    CurrReadKey=(~P1)&KEYMASK; //Invert  

      

    //The debounce principle is very simple:  

    //If the key values ​​read by LastReadKey and CurReadKey are both 1, then the current valid key value CurrKey must be 1  

    //If the key value read last time is different from the current one, keep it consistent with the last valid key value LastKey.  

    //To eliminate jitter in this way, the jitter time must be less than the keyscan() timing scan cycle, otherwise an error will occur.  

    CurrKey=(CurrReadKey&LastReadKey)|LastKey&(CurrReadKey^LastReadKey);  

    //Record key presses and releases  

    KeyPressDown=(~LastKey)&CurrKey;  

    KeyRelease=LastKey&(~CurrKey);  

  

    LastReadKey=CurrReadKey;  

    LastKey=CurrKey;  

  

}  


After downloading to the microcontroller, the old method is used for testing. This time, after pressing 100 times, the digital tube displays 100. It is much more stable than before. As for the performance of the key scanning program, it needs to be proved in future applications.


Reference address:Thoughts on a standalone key scanning program (integrating two algorithms)

Previous article:A keyboard scanning program for a 51 single-chip microcomputer, the algorithm is simple and effective
Next article:51 UART configuration process

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号