Keystroke program without delay debounce

Publisher:SparklingSoulLatest update time:2016-08-18 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
Today I finished a very good key program. Generally, textbooks describe delay debounce. Once the key scanning subroutine is entered, you have to wait for the delay, which will affect the CPU to do other things. An efficient key scanning method is to use timed scanning. All the programs are attached below. I hope you can understand them. Please give me more advice. The main function of this program is to set the voltage and current values ​​of the efficient key scanning program of sampling timed scanning, and display them on the LCD1602 in real time. On the 1602, you can shift left and right, add and subtract values, and set/confirm (multiplexed key), and there is also a short circuit key.

//Main function main

#include
#include "key.h"
#include "lcd1602.h"

uchar Key_Flag=0;
uchar Keyval = 0;
uchar Respond_Key_Flag=0; //Response key
uchar Set_Confirm_Flag=0; //Set setting/confirmation flag

uchar Volt_buf[5]={'1','2','.','2','6'};                                     
uchar Curr_buf[5]={'0','5','.','5' ,'4'};

void Init_port();
void Init_SysClk();
void Init_TimerB();
void key_process(); 
///////////////////Main function////////// /////
void main()
{
   WDTCTL = WDTPW + WDTHOLD; //Turn off the watchdog
   Init_port();
   Init_LCD();
   Init_SysClk();
   Init_TimerB();
   _EINT();
   
   Disp1Char(0,0,'U ') ;
   Disp1Char(1,0,':') ;
   DispNChar(3,0, 5,Volt_buf);
   Disp1Char(0x0F,0,'V') ;
   
   Disp1Char(0,1,'I') ;
   Disp1Char(1 ,1,':') ;
   DispNChar(3,1, 5,Curr_buf);
   Disp1Char(0x0F,1,'A') ;
   
   
   
   while(1)
   {    
     key_process(); 
     
     
   }

}
/*******************************************
Function name: key_processFunction
: Execute tasks according to key values
Parameters: None
Return value: None
********************************************/
void key_process()
{
      static uchar x=3;
      uchar keyvalue;
      static uchar key_one_flag=0;
      
      keyvalue = Key_Scan();
      Keyval = 0;
      if(Set_Confirm_Flag == 1)
      {  
                if(keyvalue == 1) //Set/Confirm key
                {  
                    key_one_flag ^= 1;
                    if(key_one_flag==1)
                    {
                        write_cmd(0x0f); //Turn on the display, display the cursor, and the character at the cursor position flashes
                        LocateXY(3,0); //Write the coordinate information of the display character position to the LCD  
                    }
                    else 
                    {
                      write_cmd(0x0c);//Turn on the display, turn off the cursor, and the character at the cursor position does not flash 
                      Set_Confirm_Flag =0;
                    }
                }
                                    
                if((keyvalue == 2)&&( Respond_Key_Flag==1)) //short circuit key
                {
                  
                  Respond_Key_Flag=0;
                  Disp1Char(3,0,'Z');
                  //TACCR0 = 65535; //PWM duty cycle is set to 100%
                }
            
      
                if((keyvalue == 3)&&( Respond_Key_Flag==1)) //left shift
                { 
                  
                  Respond_Key_Flag=0;
                  if(x >3) 
                  {
                    --x; 
                    if(x<8)
                      LocateXY(x,0);
                    else
                      LocateXY(x-5,1);  
                  }
                  else 
                  {
                    x=12;
                    LocateXY(x-5,1);
                  }        
                }
                
                
     
                if((keyvalue == 4)&&( Respond_Key_Flag==1)) //right shift
                {
                  Respond_Key_Flag=0; 
                  
                  if(x < 12) 
                  {
                    ++x; 
                    if(x<8)
                      LocateXY(x,0);
                    else
                      LocateXY(x-5,1);  
                  }
                  else 
                  {
                    x=3;
                    LocateXY(x,0);
                  }        
                  
                }
                
      
      
      
                 if((keyvalue == 5)&&( Respond_Key_Flag==1)) //Value "+" key
                  {
                    Respond_Key_Flag=0; 
                    
                    if(x<3 || x>12)
                    { 
                      write_data(' ');
                    }
                    else if (x==5||x==10) 
                       {
                          write_data('.') ; 
                          if(x==5)
                            LocateXY(x,0);
                          if(x==10)
                            LocateXY(x-5,1);
                            
                       }
                     else
                       {
                           if((x>=3)&&(x<=7))
                           {
                              if(Volt_buf[x-3]<'9')
                               Volt_buf[x-3] += 1;
                               else Volt_buf[x-3] ='0';
                               Disp1Char(x,0,Volt_buf[x-3]) ;
                               LocateXY(x,0);
                           }
                           else
                             {
                               if(Curr_buf[x-8]<'9')
                               Curr_buf[x-8] += 1;
                               else Curr_buf[x-8]='0';
                               Disp1Char(x-5,1,Curr_buf[x-8]) ;
                               LocateXY(x-5,1);
                           }                                                             
                       }
                    } 
       
           
        
                    
                     if((keyvalue == 6)&&( Respond_Key_Flag==1)) //Value "-" key
                      {
                        Respond_Key_Flag=0; 
                          
                          if(x<3 || x> 12)
                          { 
                            write_data(' ');
                          }
                          else if(x==5||x==10) 
                             {
                                write_data('.'); 
                                if(x==5)
                                  LocateXY(x,0);
                                if(x= =10)
                                  LocateXY(x-5,1);
                                  
                             }
                           else
                             {
                                 if((x>=3)&&(x<=7))
                                 {
                                    if(Volt_buf[x-3]>'0')
                                     Volt_buf[x-3] -= 1;
                                     else Volt_buf[x-3]='9';
                                     Disp1Char(x,0,Volt_buf[x-3]) ;
                                     LocateXY (x,0);
                                 }
                                 else
                                   {
                                     if(Curr_buf[x-8]>'0')
                                     Curr_buf[x-8] -= 1;
                                     else Curr_buf[x-8]='9';
                                     Disp1Char(x-5, 1,Curr_buf[x-8]) ;
                                     LocateXY(x-5,1);
                                 }                                                             
                             }
                      }
                
      }

    
}

/*==============================================
Function name: Init_portFunction
: Initialize I/O port
Parameter: NoneReturn       
value: None
=====================================================*/
void Init_port()
{
    /*The following six lines of program close all IO ports*/
    P1DIR = 0XFF;P1OUT = 0XFF; P2DIR = 0XFF
    ;P2OUT = 0XFF; P3DIR = 0XFF;
    P3OUT = 0XFF;
    P4DIR = 0XFF;P4OUT = 0XFF;
    P5DIR = 0XFF;P5OUT = 0XFF;
    P6DIR = 0XFF;P6OUT = 0XFF;
    P6DIR |= BIT2;P6OUT |= BIT2; //Turn off level conversion
     //Define LCD port
    
    P4DIR = 0XFF; //Data port
    P4OUT = 0;
    //Define key port
    P1DIR = BIT6 + BIT7; //Set P1.0~P.3 to input state, P.7 to output
   
    
}
/*==============================================
Function name: Init_SysClkFunction
: Initialize system clock
Parameter: NoneReturn       
value: None
==================================================*/

void Init_SysClk()
 {
 
  unsigned int i;
   
   BCSCTL1 &= ~XT2OFF; // XT2= HF XTAL

  do
  {
  IFG1 &= ~OFIFG; // Clear OSCFault flag
  for (i = 0xFF; i > 0; i--); // Time for flag to set
  }
  while ((IFG1 & OFIFG)); // OSCFault flag still set?

  BCSCTL2 |= SELM_2; // MCLK = XT2 (safe), the division factor is 1
  BCSCTL2 |= SELS; // SMCLK's clock source is TX2CLK, the division factor is 1
  
 }


/*==============================================
Function name: Init_TimerBFunction
: Initialize timer B, set reference time 500usParameter
: NoneReturn       
value: None
===================================================*/
void Init_TimerB()  
 {
    TBCTL |= TBSSEL1 +TBCLR; //MCLK ,8M
    TBCCTL0 = CCIE;
    TBCCR0 =4000; //Timing 500us  
    TBCTL |= MC_1; // Start Timer_B in up mode
 }


/*==============================================
Function name: TimerB_ISRFunction
: Set time interval
Parameter: NoneReturn       
value: None
===================================================*/
// Timer B0 interrupt service routine
#pragma vector=TIMERB0_VECTOR
__interrupt void TimerB_ISR (void)
{
    static uchar Flag_500us = 0;  
    Flag_500us ++;
     if(Flag_500us ==20)
     {
         Key_Flag =1; // Timing 10ms
         Flag_500us=0;
        // TBCCTL0 = ~CCIE; // Turn off interrupt, used for single-step debugging, otherwise it will always be in interrupt
       
       
     }   
         
}


    

 

//Key header file key.h

#ifndef MSP430_KEY_PROCESS_H
#define MSP430_KEY_PROCESS_H
/***************************************************
Program function: Read the key values ​​of 6 determinant buttons using timed scanning method
****************************************************/
#include
#include "lcd1602.h"

#define keyin (P1IN & 0x0F)

uchar KEY_BUFFER ;
uchar KEY_BUFFER1 ;

uchar KEY_DATA = 0x00;
uchar Num=0;
extern uchar Key_Flag; 
extern uchar Keyval;
extern uchar Respond_Key_Flag;
extern uchar Set_Confirm_Flag;

/*******************************************
Function name: Delay10usFunction
: Delay about 10usParameter
: None
Return value: None
********************************************/
void Delay10us(void)

    uint i=10;
    while (i != 0)
    {
        i--;
    }
}
/*******************************************
Function name: Key_ScanFunction
: Scan key value
Parameter: None
Return value: Keyval
********************************************/
uchar Key_Scan()
{      
       
       if(Key_Flag ==1 ) //Scan once every 10ms
       {                  
         Key_Flag =0;                
        //Bit processing, first use one byte to read the value of the eight-bit key, and then make a judgment 
         P1OUT =0X70;
         Delay10us(); //Give hardware response
         timeKEY_BUFFER =keyin;
         KEY_BUFFER =~KEY_BUFFER;
         KEY_BUFFER1 =KEY_BUFFER<<4;
       
         P1OUT =0XB0;
         Delay10us();
         KEY_BUFFER =keyin;
         KEY_BUFFER =~KEY_BUFFER;
         KEY_BUFFER &=0X0F; //Shield the upper four bits
         KEY_BUFFER1 |=KEY_BUFFER ;  
         
         if(KEY_BUFFER1 != KEY_DATA) //First determine whether a key is pressed
         {
            KEY_DATA =KEY_BUFFER1; //Read key value
            Num =0;
         }
         else //KEY_BUFFER1 = KEY_DATA processing
         {
                Num ++; 
                         
                if(Num==4) //Num=4, reading 4 times is valid, the delay reaches 40ms 
                {               
                  if(KEY_DATA==0x10) //Judge key value
                     Keyval=1;
                  else if(KEY_DATA==0x20)
                     Keyval=2;
                  else if(KEY_DATA==0x40)
                     Keyval=3;
                  else if(KEY_DATA==0x80)
                     Keyval=4;
                  else if(KEY_DATA==0x01)
                     Keyval=5;
                  else if(KEY_DATA==0x02)
                     Keyval=6;
                  else Keyval=0;
                  
                }
                else // Processing of Num!=4      
                {
                          
                          
                          if( KEY_DATA == 0x00) // Release the key, allow response
                          {
                            Num=0;
                            Respond_Key_Flag =1; // Key response flag                      
                          }
                          else //The key is not released, and it is pressed continuously
                          {
                                  
                              if((KEY_DATA == 0x10)&&(Num >=100)) //1s, determine whether it is the set/confirm key
                              {                                 
                                  Num =0;
                                  Set_Confirm_Flag =1;                                   
                                 
                              }
                             
                                  
                          } }
                            
                  }
   
         }
         
       return
         
Keyval;

}
#endif




 

  //LCD 1602 header file lcd1602.h

#ifndef MSP430_LCD1602_PROCESS_H
#define MSP430_LCD1602_PROCESS_H
//Hardware connection P4 data port P3.2---EN P3.1---RW P3.0----RS

#include"msp430x14x.h" 
typedef unsigned int uint;
typedef unsigned char uchar;
//Define the interface between MCU and LCD
/**************Macro definition***************/   
#define Busy 0x80
#define CtrlDir P3DIR
#define CLR_RS P3OUT&=~BIT0 //RS = P3.0 
#define SET_RS P3OUT|=BIT0 
#define CLR_RW P3OUT&=~BIT1 //RW = P3.1
#define SET_RW P3OUT|=BIT1 
#define CLR_EN P3OUT&=~BIT2 //EN = P3.2 
#define SET_EN P3OUT|=BIT2  
/*******************************************
Function name: Delay5ms
Function: Delay about 5ms
Parameter: None
Return value: None
********************************************/
void Delay5ms(void)

    uint i=40000;
    while (i != 0)
    {
        i--;
    }
}
/*******************************************
Function name: WaitForEnableFunction
: Wait for 1602 LCD to complete internal operations
Parameter: None
Return value: None
********************************************/
void WaitForEnable(void) 
{
    P4DIR &= 0x00; //Switch P4 port to input state

    CLR_RS;
    SET_RW;
    _NOP();
    SET_EN; 
    _NOP();
    _NOP();
 
    while((P4IN & Busy)!=0); //Check busy flag

    CLR_EN;

    P4DIR |= 0xFF; //Switch P4 port to output state

/********************************************
Function name: write_cmdFunction
: Write command to LCD module
Parameter: com--command,         
return value: none
********************************************/
void write_cmd(unsigned char com) 

    WaitForEnable(); //Wait for LCD to be unbusy
    CLR_RS ; //RS=0,RW=0, write command
    CLR_RW;
    _NOP();
    P4OUT = com; 
    _NOP(); 
    SET_EN ;
    _NOP(); 
    _NOP();
    CLR_EN;
}

/*******************************************
Function name: write_dataFunction
: Write display data to the current address of the LCD display
Parameter: data--display character data
Return value: None
********************************************/ 
void write_data(unsigned char data) 
{  
    WaitForEnable(); //Wait for the LCD to be unbusy
    SET_RS; //RS=1,RW=0, write data
    CLR_RW;
    _NOP();
    P4OUT = data; 
    _NOP(); 
    SET_EN; //Generate negative pulse
    _NOP(); 
    _NOP();  
    CLR_EN;             
}

/*===============================================
Function name: Init_LCDFunction
: Initialize LCD
Parameters: None
Return value: None
===================================================*/
void Init_LCD() 

    CtrlDir |= 0x07; //Set the control line port to output state 
    P4DIR = 0xFF; //Set the data port to output state
    
    write_cmd(0x38); //Specified reset operation
    Delay5ms();
    write_cmd(0x38);  
    Delay5ms();
    write_cmd(0x38);
    Delay5ms();
   
    write_cmd(0x38); //16×2 display, 5×7 dot matrix, 8-bit data interface  
    write_cmd(0x08); //Turn off the display
    write_cmd(0x01); //Clear the screen, data pointer = 0, all displays = 0
    write_cmd(0x06); //After reading or writing a character, the address pointer increases by 1 & the cursor increases by 1, and the entire screen display does not move
    write_cmd(0x0c); //Turn on the display, turn off the cursor, and the character at the cursor position does not flash    
     
}

/*******************************************
Function name: LocateXYFunction
: Write the coordinate information of the displayed character position to the LCD
Parameters: x--column coordinate of the position
          y--row coordinate of the position
Return value: None
********************************************/
void LocateXY(uchar x,uchar y) 
{
    uchar temp;

    temp = x&0x0f;
    y &= 0x01;
    if(y) temp |= 0x40; //If in line 2
    temp |= 0x80;

    write_cmd(temp);
}
/*******************************************
Function name: Disp1CharFunction
: Display a character at a certain position
Parameters: x--column coordinate of the position
          y--row coordinate of the position
          data--character data to be displayed
Return value: None
********************************************/
void Disp1Char(uchar x,uchar y,uchar data) 
{
    LocateXY( x, y );   
    write_data( data );  
}

/***********************************************
Function name: DispStrFunction
: Let the LCD display a string continuously from a certain position
Parameters: x--column coordinate of the position
          y--row coordinate of the position
          ptr--pointer to the string storage position
Return value: None
***********************************************/
void DispStr(uchar x,uchar y,uchar *ptr) 
{
    uchar *temp;
    uchar i,n = 0;
    
    temp = ptr;
    while(*ptr++ != '\0') n++; //Calculate the number of valid characters in the string
    
    for (i=0;i     {
        Disp1Char(x++,y,temp[i]);
        if (x == 0x0f)
        {
           x = 0; 
           y ^= 1;
        }
    }
}

/*******************************************
Function name: DispNcharFunction
: Let the LCD display N characters continuously from a certain position
Parameters: x--column coordinate of the position
          y--row coordinate of the position
          n--number of characters
          ptr--pointer to the character storage position
Return value: None
********************************************/
void DispNChar(uchar x,uchar y, uchar n,uchar *ptr) 
{
    uchar i;
    
    for (i=0;i     {
        Disp1Char(x++,y,ptr[i]);
        if (x == 0x0f)
        {
           x = 0; 
        y ^= 1;
        }
    }
}

#endif

 

When I first wrote it, I found that it was not very stable when I used it in practice. After two or three days of modification, I finally finalized it into the above code, which is completely usable.

Reference address:Keystroke program without delay debounce

Previous article:Summary of using msp430f5418
Next article:A brief discussion on the instruction cycle of MSP430 single-chip microcomputer

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
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号