Understanding the Principles of Standalone Keyboard Design through a Case Study

Introduction: Understanding the Principles of Standalone Keyboard Design through a Case Study

A microcontroller along with 4 independent buttons (S1~S4) and 8 LED indicator lights form a standalone keyboard system. The 4 buttons are connected to pins P1.0~P1.3, while the P3 port connects to 8 LED indicator lights. The schematic diagram is as follows: When button S1 is pressed, the 8 LED indicator lights connected to port P3 light up in a forward sequence; when button S2 is pressed, the 8 LED indicator lights light up in a reverse sequence; when button S3 is pressed, 4 LED indicator lights connected to port P3 alternate between high and low lighting; when button S4 is pressed, the 8 LED indicator lights connected to port P3 flash intermittently.

Due to the four buttons in this example corresponding to four different lighting functions, and having different logic numbers “keyval”, as follows:

  • Pressing button S1 sets keyval to 1.
  • Pressing button S2 sets keyval to 2.
  • Pressing button S3 sets keyval to 3.
  • Pressing button S4 sets keyval to 4.
    The working principle of the standalone keyboard in this example is as follows:
    (1) First, determine if any button is pressed.
    Set the lower 4 bits (P1.0~P1.3) of port P1, which are connected to the four buttons, to 1 to make the lower 4 bits of port P1 input. Then read the logic levels of the lower 4 bits. As long as they are not all 1, it indicates that a button is pressed. The reading method is as follows:
P1 = 0xFF;
while ((P1 & 0x0F) != 0x0F);
// Read the status of each button in the lower 4 bits of port P1, 
// the bitwise AND operation result is not 0x0F, indicating that at least one bit in the lower 4 bits is 0, indicating a button is pressed.

(2) Debouncing the buttons.
When a button press is detected, call a software delay subroutine, delay for about 10 ms, and then recheck. If the button is still pressed, execute the corresponding button function; otherwise, restart the scanning process.
(3) Obtaining the key number.
Once it is confirmed that a button is pressed, scanning methods can be used to determine which button is pressed and obtain the key value.

Code implementation:

  1. Define the button pins.

#include<reg52.h>
sbit S1=P1^0;
sbit S2=P1^1;
sbit S3=P1^2;
sbit S4=P1^3;
unsigned char keyval;

2. Main function

void main()
{
  keyval=0;
  while(1)
  {
    key_scan();
    switch(keyval)
    {
      case 1:forward();
        break;
      case 2:backward();
        break;
      case 3:alter();
        break;
      case 4:blink();
        break;
    }
  }
}

3. Keyboard scan function

void key_scan()
{
  P1=0xff;
  if((P1&0x0f)!=0x0f)
  {
    delay10ms();
    if(S1==0)
    keyval=1;
    if(S2==0)
    keyval=2;
    if(S3==0)
    keyval=3;
    if(S4==0)
    keyval=4;
  }
}

4. LED for forward

void forward()
{
  P3=0xfe;
  led_delay();
  P3=0xfd;
  led_delay();
  P3=0xfb;
  led_delay();
  P3=0xf7;
  led_delay();
  P3=0xef;
  led_delay();
  P3=0xdf;
  led_delay();
  P3=0xbf;
  led_delay();
  P3=0x7f;
  led_delay();
}

5. LED for Backward

void backward()
{
  P3=0x7f;
  led_delay();
  P3=0xbf;
  led_delay();
  P3=0xdf;
  led_delay();
  P3=0xef;
  led_delay();
  P3=0xf7;
  led_delay();
  P3=0xfb;
  led_delay();
  P3=0xfd;
  led_delay();
  P3=0xfe;
  led_delay();
}

6. Alter LED

void alter()
{
P3=0x0f;
led_delay();
P3=0xf0;
led_delay();
}

7. Blik LED

void blink()
{
  P3=0xff;
  led_delay();
  P3=0x00;
  led_delay();
}

8. Delay LED

void led_delay(void)
{
  unsigned char i,j;
  for(i=0;i<220;i++)
  for(j=0;j<220;j++);
}

9. Deplay 10 ms LED

void delay10ms()
{
  unsigned char i,j;
  for(i=0;i<100;i++)
  for(j=0;j<100;j++);
}

See the summary of the whole program for keyboard

#include<reg52.h>
sbit S1=P1^0;
sbit S2=P1^1;
sbit S3=P1^2;
sbit S4=P1^3;
unsigned char keyval;
 
 
void key_scan()
{
  P1=0xff;
  if((P1&0x0f)!=0x0f)
  {
    delay10ms();
    if(S1==0)
    keyval=1;
    if(S2==0)
    keyval=2;
    if(S3==0)
    keyval=3;
    if(S4==0)
    keyval=4;
  }
}
 
void forward()
{
  P3=0xfe;
  led_delay();
  P3=0xfd;
  led_delay();
  P3=0xfb;
  led_delay();
  P3=0xf7;
  led_delay();
  P3=0xef;
  led_delay();
  P3=0xdf;
  led_delay();
  P3=0xbf;
  led_delay();
  P3=0x7f;
  led_delay();
}
 
void backward()
{
  P3=0x7f;
  led_delay();
  P3=0xbf;
  led_delay();
  P3=0xdf;
  led_delay();
  P3=0xef;
  led_delay();
  P3=0xf7;
  led_delay();
  P3=0xfb;
  led_delay();
  P3=0xfd;
  led_delay();
  P3=0xfe;
  led_delay();
}
 
void alter()
{
  P3=0x0f;
  led_delay();
  P3=0xf0;
  led_delay();
}
 
 
void blink()
{
  P3=0xff;
  led_delay();
  P3=0x00;
  led_delay();
}
 
void led_delay(void)
{
  unsigned char i,j;
  for(i=0;i<220;i++)
  for(j=0;j<220;j++);
}
 
void delay10ms()
{
  unsigned char i,j;
  for(i=0;i<100;i++)
  for(j=0;j<100;j++);
}
 
void main()
{
  keyval=0;
  while(1)
  {
    key_scan();
    switch(keyval)
    {
      case 1:forward();
        break;
      case 2:backward();
        break;
      case 3:alter();
        break;
      case 4:blink();
        break;
    }
  }
}