×
单片机 > 单片机程序设计 > 详情

PIC16F877A矩阵键盘的用法

发布时间:2020-06-16 发布时间:
|

/*******************************************************************************
Platform: PIC1687A
Project : 实验16:矩阵式按键
Clock F : 外部4M
Software: PICC
Author  : 竹林清风
comments:
学习使用矩阵式按键的用法
本例功能是按一下相应键,数码管显示相应的值
0-9;不带连发,不带组合,希望有兴趣的人帮忙完成
并共享
UP键按键计数
proteus仿真通过;
*******************************************************************************/
#include
#include
#include"delay.h"
#include"key.h"

unsigned char led_7[]={0x3f,0x06,0x5b,0x4F,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//数码管显示值

unsigned char key_temp;
void main(void)
{
  unsigned char ID=0;
  TRISB=0X00;//所有B0端口输出
  PORTB=0XFF;
  
  TRISD=0X0F;//初始化键盘接口
  PORTD=0XFF;//置输出为高电平
  
while(1){  
           delay_nms(5); 
           key_temp = read_keyboard();  // 调用键盘接口函数读键盘
   if (key_temp != No_key)
   {       // 有按键按下
                
    switch(key_temp)
    {
      case 1:
      PORTB=led_7[1];
      break;
      case 2:
      PORTB=led_7[2];
      break;
                  case 3:
                  PORTB=led_7[3];
                  break;
                  case 4:
                  PORTB=led_7[4];
                  break;
                  case 5:
                  PORTB=led_7[5];
                  break;
                  case 6:
                  PORTB=led_7[6];
                  break;
                  case 7:
                  PORTB=led_7[7];
                  break;
                  case 8:
                  PORTB=led_7[8];
                  break;
                  case 9:
                  PORTB=led_7[9];
                  break;
                  case K3_2:
                  PORTB=led_7[0];
                  break;
                  case 13:
                  if(++ID>=10)
                   {
                   ID=0;
                   }
                  PORTB=led_7[ID];
                   
                  break;
                  }
             }
          }
}                   
下面为延时函数:文件delay.c      

void delay_1us(void)                 //1us
  {
   asm("nop");
  }

void delay_nus(unsigned int n)       //N us延时函数
  {
   unsigned int i=0;
   for (i=0;i   delay_1us();
  }
  
void delay_1ms(void)                 //1ms延时函数
  {
   unsigned int i;
   for (i=0;i<1140;i++); 
  }
  
void delay_nms(unsigned int n)       //N ms延时函数
  {
   unsigned int i=0;
   for (i=0;i   delay_1ms();}
 

头文件:delay.h

void delay_1us(void);
void delay_nus(unsigned int n);       //N us延时函数
void delay_1ms(void);                 //1ms延时函数 
void delay_nms(unsigned int n);       //N ms延时函数

 

键盘key.h

#define No_key  255
#define K1_1 1
#define K1_2 2
#define K1_3 3
#define k1_4    4
#define K2_1 5
#define K2_2 6
#define K2_3 7
#define K2_4 8
#define K3_1 9
#define K3_2 0
#define K3_3 10
#define K3_4 11
#define K4_1 12
#define K4_2 13
#define K4_3 14
#define K4_4 15
#define Key_mask 0b00001111

unsigned char read_keyboard()

 static unsigned char key_state = 0, key_value, key_line;
    unsigned char key_return = No_key,i,key_time;
 
 switch (key_state)
 {
  case 0:
   key_line = 0b00010000;
   for (i=1; i<=4; i++)     // 扫描键盘
   { 
    PORTD = ~key_line;     // 输出行线电平
    PORTD = ~key_line;     // 必须送2次!!!
                key_value = Key_mask & PORTD;  // 读列电平
    if (key_value == Key_mask)
     key_line <<= 1;    // 没有按键,继续扫描
    else
    {
     key_state++;     // 有按键,停止扫描
     break;      // 转消抖确认状态
    }
   }
   break;
  case 1:
   if (key_value == (Key_mask & PORTD))  // 再次读列电平,
   {
    switch (key_line | key_value)  // 与状态0的相同,确认按键
    {        // 键盘编码,返回编码值 
     case 0b00011110: 
      key_return = K1_1;      //"1"
      key_state++; 
      break;
     case 0b00011101:
      key_return = K1_2;      //"2"
      key_state++; 
      break;
      case 0b00011011:
      key_return = K1_3;     //"3"
      key_state++; 
      break;
     case 0b00010111:
      key_return = k1_4;     //"4"
      key_state++; 
      break;
      case 0b00101110:
      key_return = K2_1;     //"5"
      key_state++; 
      break;
     case 0b00101101:
      key_return = K2_2;     //"6"
      key_state++; 
      break;
      case 0b00101011:
      key_return = K2_3;     //"7"
      key_state++; 
      break;
      case 0b00100111:
      key_return = K2_4;    //"8"
      key_state++; 
      break;
     case 0b01001110:         
      key_return = K3_1;     //"9"
      key_state++; 
      break;
      case 0b01001101:          
      key_return = K3_2;    //"0"
      key_state++; 
      break;
      case 0b01001011:          
      key_return = K3_3;    //"A"
      key_state++; 
      break;
     case 0b01000111:          
      key_return = K3_4;     //"B"
      key_state++; 
      break;
     case 0b10001110:         
      key_return = K4_1;    //"C"
      key_state++; 
      break;
     case 0b10001101:          
         //key_return = K4_2; //"D"
        // key_state++; 
           key_time=0;
      key_state=3;
      break;
     case 0b10001011:          
      key_return = K4_3;   //"E"
      key_state++; 
      break;
     case 0b10000111:
      key_return = K4_4;    //"F"
      key_state++; 
      break;
    }
       // 转入等待按键释放状态
   }
   else
    key_state--;    // 两次列电平不同返回状态0,(消抖处理)
   break;      
  case 2:       // 等待按键释放状态
   PORTD = 0b00000111;   // 行线全部输出低电平
   PORTD = 0b00000111;   // 重复送一次
   if ( (Key_mask & PORTD) == Key_mask)
    key_state=0;    // 列线全部为高电平返回状态0
   break;
  case 3:
  PORTD = 0b00000111;   // 行线全部输出低电平
  PORTD = 0b00000111;   // 重复送一次
  if ( (Key_mask & PORTD) == Key_mask)
    {
    key_state=0;    // 列线全部为高电平返回状态0
    key_return = K4_2; 
    }
    //break;
   else if( (Key_mask & PORTD)!=Key_mask)
   {
   if(++key_time>=100)
     {
     key_state=4;
      key_time=0;
   
   key_return=20;
   
   }
   }
     break;
    case 4:
   PORTD = 0b00000111;   // 行线全部输出低电平
   PORTD = 0b00000111;   // 重复送一次
  if ( (Key_mask & PORTD) == Key_mask)
    {
      key_state=0;    // 列线全部为高电平返回状态0
      //key_return = K4_2; 
    }
   else if(++key_time>=20)
         {
            key_time=0;
        
         key_return=20;
        }
   break; 
 }
 return key_return;
}


关键字:PIC16F877A  矩阵键盘 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
如何为单片机选择合适的负载电容