钻石会员 
 
主题
回帖0
积分19891
阅读权限50
注册时间2009-4-2
最后登录1970-1-1
在线时间 小时
 
 
 
 
 | 
 
朋友拿了一个16键的键盘电路板,要求编一个能取出16个键的长按和短按的键值。这个电路以前没有接触过,它和一般的4*4矩阵电路不同,好像应该是2列8行,1列接到单片机的INT0口的P3.2,1列接到INT1口的P3.3. 8行分别接到138的y0-y7,138的A,B,C分别接单片机的p3.5,p3.6,p3.7,这样一共用5个口就可以控制16个按键比一般的常规4*4矩阵电路可以节省3个口。在单片机的资源不是太紧张的时候这样使用,而且占用了2个外部中断口,有什么好处呢?(没有想明白,可能是单片机的资源紧张吧,据说是用的80元1片的单片机哟,呵呵。)参考电路图,学习用c编写,试了2天,写了一个可以取出长按和短按的键值的使用程序附后,有兴趣的朋友或者到时有可能IO口紧张不够用的朋友,可以一起交流探讨,现在这个程序写得太烂,太野,我是知道的,仅仅是能用而已,呵呵。 
16键电路图 
 
 
  
/********************************************* 
2012-03-29 
键盘程序试验.c 
**********************************************/     
#include<reg1210.h> 
#include<intrins.h> 
#include"lr_lcd_api.h" 
#include <stdio.h>    
sbit led_1=P1^6; 
sbit led_2=P0^5; 
sbit  key1=P1^1; 
sbit  key2=P0^6; 
sbit io_int0=P3^2; 
sbit io_int1=P3^3; 
sbit a_138=P3^5; 
sbit b_138=P3^6; 
sbit c_138=P3^7; 
#define uchar unsigned char 
#define uint unsigned int 
unsigned char code string5c[]="5_ca"; 
unsigned char code string5[]="5_da";  
unsigned char code string6c[]="6_ca"; 
unsigned char code string6[]="6_da";  
unsigned char code string7c[]="7_ca"; 
unsigned char code string7[]="7_da";  
unsigned char code string8c[]="8_ca"; 
unsigned char code string8[]="8_da";  
unsigned char code string9c[]="9_ca"; 
unsigned char code string9[]="9_da";  
unsigned char code string10c[]="10_ca"; 
unsigned char code string10[]="10_da";  
unsigned char code string11c[]="11_ca"; 
unsigned char code string11[]="11_da";  
unsigned char code string12c[]="12_ca"; 
unsigned char code string12[]="12_da";  
unsigned char code string13c[]="13_ca"; 
unsigned char code string13[]="13_da";  
unsigned char code string14c[]="14_ca"; 
unsigned char code string14[]="14_da";  
unsigned char code string15c[]="15_ca"; 
unsigned char code string15[]="15_da";  
unsigned char code string16c[]="16_ca"; 
unsigned char code string16[]="16_da";  
unsigned char code string17c[]="17_ca"; 
unsigned char code string17[]="17_da";  
unsigned char code string18c[]="18_ca"; 
unsigned char code string18[]="18_da";  
unsigned char code string19c[]="19_ca"; 
unsigned char code string19[]="19_da";  
unsigned char code string20c[]="20_ca"; 
unsigned char code string20[]="20_da";  
bit f_int0; 
bit f_int1;           
uchar key_z=0xff; 
uchar key_z_0_00b;   //短按键键值(0x0x) 对应INT0 
uchar key_z_0_c0b;   //长按键键值(0xcx) 对应INT0 
uchar key_z_1_00b;   //短按键键值(0x0x) 对应INT1 
uchar key_z_1_c0b;   //长按键键值(0xcx) 对应INT1 
 
uchar key_jsq=0;   //按键实际的按下时间(变量) 
#define aj_ca_da_bz 25 //按键长按短按标准 (常量) 
 
#define k5_da_z 0x00 
#define k5_ca_z 0xc0 
#define k6_da_z 0x01 
#define k6_ca_z 0xc1 
#define k7_da_z 0x02 
#define k7_ca_z 0xc2 
#define k8_da_z 0x03 
#define k8_ca_z 0xc3 
#define k9_da_z 0x04 
#define k9_ca_z 0xc4 
#define k10_da_z 0x05 
#define k10_ca_z 0xc5 
#define k11_da_z 0x06 
#define k11_ca_z 0xc6 
#define k12_da_z 0x07 
#define k12_ca_z 0xc7 
#define k13_da_z 0x08 
#define k13_ca_z 0xc8 
#define k14_da_z 0x09 
#define k14_ca_z 0xc9 
#define k15_da_z 0x0a 
#define k15_ca_z 0xca 
#define k16_da_z 0x0b 
#define k16_ca_z 0xcb 
#define k17_da_z 0x0c 
#define k17_ca_z 0xcc 
#define k18_da_z 0x0d 
#define k18_ca_z 0xcd 
#define k19_da_z 0x0e 
#define k19_ca_z 0xce 
#define k20_da_z 0x0f 
#define k20_ca_z 0xcf 
/**********************************************************/ 
/**********************************************************/ 
//串口初始化 
void init_serialcomm(void) 
{ 
     SCON0=0x50;        //在12MHz下,设置串行口波特率为9600,方式1,并允许接收 
     PCON=0x00; 
     T2CON=0X34;        //定时器2波特率自动重装 
     RCAP2H=0xff;       //波特率9600,时钟频率12MHZ 
     RCAP2L=0xdC;//9; 
     EA=1;   
     ES=0;  //开串口中断  
} 
/************************************************************/ 
//中断接收服务程序 
void serial () interrupt 4 using 3 
{     
   if(RI) 
    {  
  RI=0;//清中断标志 
    } 
  if(TI) 
    { 
 TI=0;//清发送标志位  
 } 
} 
/**********************************************************/ 
//定时器0中断初始化 
void init_t0(void){ 
   TMOD=0x01;  //用定时器0 
   TH0=76; 
   TL0=0; 
   ET0=1; //定时器0中断允许 
   TR0=1; 
   EA=1; 
}   
/**********************************************************/ 
//定时器0中断服务程序 
void it0() interrupt 1 using 1 
 { TH0=76; 
 TL0=0; 
 key_jsq++;  
 }  
/**********************************************************/  
//外部中断0,外部中断1初始化 
//允许外部中断0,外部中断1中断,设置为边缘触发  
void init_int0int1(void){      
   
  f_int0=0; 
  f_int1=0;   
     
   IT0=1;  //外部中断0设为边缘触发 
   IT1=1;  //外部中断1设为边缘触发  
   EX0=1; 
   EX1=1; 
   EA=1; 
} 
/***********************************************************/ 
//外部中断0服务程序 
void int0() interrupt 0 using 0 
{ 
  EX0=0;     
  f_int0=1; 
  
}          
/***********************************************************/ 
//外部中断1服务程序 
void int1() interrupt 2 using 2 
{ 
  EX1=0;      
  
  f_int1=1; 
}  
/**********************************************************/    
/**********************************************************/   
void delay(uint dly) 
{while(dly--) 
 { _nop_(); 
   _nop_(); 
   _nop_(); 
   _nop_(); 
}} 
//############################################################## 
//############################################################## 
void LR_Send_Char(uchar byte)//串口发送一个字节 
  { 
//  while(DTR==1);//判断是否忙,如果忙的话,一直等待 
   SBUF=byte; 
   while(TI==0); 
   TI=0; 
  }  
/*=============================================== 
函数功能:显示字符前用 
参数列表:无 
2012-03-21  fxh 
=================================================*/ 
void LR_LCD_show_string(){           
 LR_Send_Char(0x1b); 
 LR_Send_Char(0x25); 
 LR_Send_Char(0x01); 
} 
/*===============================================  
/*=============================================== 
函数功能:自动判断、显示字符 
参数列表: 
     buf: 存放要显示的字符缓冲区,要以0结尾 
特别注意,buf的最后要有一个0——就是说多添加一个0 
=================================================*/ 
void LR_LCD_ShowString(unsigned char *buf) 
{ 
 LR_LCD_show_string(); 
 while(*buf)LR_Send_Char(*buf++);   
} 
//################################################################  
/*=============================================== 
函数功能:调用预置画面 
参数列表: 
    n:预置画面的起始页 
=================================================*/ 
void LR_LCD_CallPage(uchar n) 
{ 
 LR_Send_Char(0x1b); 
 LR_Send_Char(0x50); 
 LR_Send_Char(n); 
}  
/*================================================== 
函数功能:清屏 
参数列表: 
    clr:清屏颜色 
===================================================*/ 
void LR_LCD_ScreenClear(uchar clr) 
{ 
 LR_Send_Char(0x1b); 
 LR_Send_Char(0x42); 
 LR_Send_Char(clr); 
} 
/**********************************************************/ 
/*=================================================== 
函数功能:取按键值 
参数列表: 
=====================================================*/ 
void q_key_z(void) 
  {  
   while(f_int0){ key_jsq=0; 
           while(!io_int0){                  
   if(key_jsq>=aj_ca_da_bz){key_jsq=0; key_z=key_z_0_c0b;}}     
  
  if(key_z==key_z_0_c0b){key_jsq=0;f_int0=0;EX0=1;delay(4400);} 
  else { key_z=key_z_0_00b;f_int0=0;EX0=1;delay(4400);}  
       } 
//-------------------------------------------------------------------     
   while(f_int1){ key_jsq=0; 
           while(!io_int1){                  
   if(key_jsq>=aj_ca_da_bz){key_jsq=0; key_z=key_z_1_c0b;}}     
  
  if(key_z==key_z_1_c0b){key_jsq=0;f_int1=0;EX1=1;delay(4400);} 
  else { key_z=key_z_1_00b;f_int1=0;EX1=1;delay(4400);}       
       } 
  } 
/******************************************************************** 
/*******************************************************************/ 
/*******************************************************************/ 
void main() 
{ //uchar k; 
 delay(100); 
 init_t0(); 
 init_serialcomm(); 
  
 LR_LCD_ScreenClear(1); //发送清兰屏指令1B 42 01 
    
    led_1=1; 
    led_2=0; 
    init_int0int1(); 
 key_z=0xff; 
while(1){ 
   key_z=0xff; 
   
   if(key1==0){led_1=~led_1;led_2=~led_2;while(key1==0){;}} 
   //if(key2==0){ 
  
   // LR_LCD_ShowString(string20); 
 //LR_LCD_CallPage(48); 
  
 //k++; if(k>7)k=0; while(key2==0){;} delay(1000); 
  // } 
/***********************************************************/      
   c_138=0;b_138=0;a_138=0;  //000 
   delay(2200);   
     
  key_z_0_c0b=k17_ca_z; // 
  key_z_0_00b=k17_da_z; // 
   
  key_z_1_c0b=k18_ca_z; // 
  key_z_1_00b=k18_da_z; // 
   q_key_z(); 
/***********************************************************/  
   c_138=0;b_138=0;a_138=1;  //001 
   delay(2200);   
  key_z_0_c0b=k13_ca_z; // 
  key_z_0_00b=k13_da_z; // 
   
  key_z_1_c0b=k14_ca_z; // 
  key_z_1_00b=k14_da_z;  // 
   
   q_key_z(); 
/***********************************************************/     
   c_138=0;b_138=1;a_138=0; //010 
   delay(2200);   
  key_z_0_c0b=k9_ca_z;  // 
  key_z_0_00b=k9_da_z;  // 
   
  key_z_1_c0b=k10_ca_z; // 
  key_z_1_00b=k10_da_z;  // 
    
   q_key_z(); 
/***********************************************************/ 
   c_138=0;b_138=1;a_138=1; //011 
   delay(2200);   
  key_z_0_c0b=k5_ca_z;  // 
  key_z_0_00b=k5_da_z;  // 
   
  key_z_1_c0b=k6_ca_z;  // 
  key_z_1_00b=k6_da_z;   // 
    
   q_key_z(); 
/***********************************************************/ 
   c_138=1;b_138=0;a_138=0; //100 
   delay(2200);   
    
  key_z_0_c0b=k20_ca_z; 
  key_z_0_00b=k20_da_z; 
   
  key_z_1_c0b=k19_ca_z; 
  key_z_1_00b=k19_da_z;  
    
   q_key_z(); 
/***********************************************************/   
   c_138=1;b_138=0;a_138=1; //101 
   delay(2200); 
  key_z_0_c0b=k16_ca_z;  // 
  key_z_0_00b=k16_da_z;  // 
   
  key_z_1_c0b=k15_ca_z;  // 
  key_z_1_00b=k15_da_z;   // 
    
   q_key_z(); 
/***********************************************************/   
   c_138=1;b_138=1;a_138=0; //110 
   delay(2200); 
  key_z_0_c0b=k12_ca_z;   // 
  key_z_0_00b=k12_da_z;   // 
   
  key_z_1_c0b=k11_ca_z;   // 
  key_z_1_00b=k11_da_z;    // 
    
   q_key_z(); 
/***********************************************************/   
   c_138=1;b_138=1;a_138=1; //111 
   delay(2200); 
   
  key_z_0_c0b=k8_ca_z; // 
  key_z_0_00b=k8_da_z; // 
   
  key_z_1_c0b=k7_ca_z; // 
  key_z_1_00b=k7_da_z;  // 
    
   q_key_z(); 
/**************************************************************/   
   switch(key_z){ 
     case k20_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string20c);break; 
     case k20_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string20);break; 
   
  case k19_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string19c);break; 
     case k19_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string19);break; 
    
     case k18_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string18c);break; 
     case k18_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string18);break; 
     case k17_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string17c);break; 
     case k17_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string17);break; 
     case k16_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string16c);break; 
     case k16_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string16);break; 
     case k15_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string15c);break; 
     case k15_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string15);break; 
     case k14_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string14c);break; 
     case k14_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string14);break; 
     case k13_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string13c);break; 
     case k13_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string13);break; 
     case k12_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string12c);break; 
     case k12_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string12);break; 
     case k11_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string11c);break; 
     case k11_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string11);break; 
      
  case k10_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string10c);break; 
     case k10_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string10);break; 
     case k9_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string9c);break; 
     case k9_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string9);break; 
     case k8_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string8c);break; 
     case k8_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string8);break; 
     case k7_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string7c);break; 
     case k7_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string7);break; 
     case k6_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string6c);break; 
     case k6_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string6);break; 
     case k5_ca_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string5c);break; 
     case k5_da_z: LR_LCD_ScreenClear(0); LR_LCD_ShowString(string5);break;     
    
       default:   key_z=0xff; 
  }}} 
/******************************************************************************/  |   
 
 
 
 |