理论上可以实现42键无冲检测
KEY_H1,KEY_H2,KEY_H3,KEY_H4,KEY_H5,KEY_H6,KEY_H7接单片机普通端口且需要带上拉功能。
KEY_L1,KEY_L2,KEY_L3,KEY_L4,KEY_L5,KEY_L6接单片机普通端口且需要带上拉功能。
一共6*7=42个按键
按键检测子函数:
#define KEY_H1 P53
#define KEY_H2 P23
#define KEY_H3 P04
#define KEY_H4 P35
#define KEY_H5 P34
#define KEY_H6 P51
#define KEY_H7 P50
#define KEY_L1 P26
#define KEY_L2 P10
#define KEY_L3 P25
#define KEY_L4 P24
#define KEY_L5 P57
#define KEY_L6 P56
#define KEY_H1_OUTPUT_MODE GPIO_SetMode(P5,BIT3,GPIO_MODE_OUTPUT); //KEY_H1设置成输出模式
#define KEY_H1_QUASI_MODE GPIO_SetMode(P5,BIT3,GPIO_MODE_QUASI); //KEY_H1设置成准双向模式
#define KEY_H2_OUTPUT_MODE GPIO_SetMode(P2,BIT3,GPIO_MODE_OUTPUT); //KEY_H2设置成输出模式
#define KEY_H2_QUASI_MODE GPIO_SetMode(P2,BIT3,GPIO_MODE_QUASI); //KEY_H2设置成准双向模式
#define KEY_H3_OUTPUT_MODE GPIO_SetMode(P0,BIT4,GPIO_MODE_OUTPUT); //KEY_H3设置成输出模式
#define KEY_H3_QUASI_MODE GPIO_SetMode(P0,BIT4,GPIO_MODE_QUASI); //KEY_H3设置成准双向模式
#define KEY_H4_OUTPUT_MODE GPIO_SetMode(P3,BIT5,GPIO_MODE_OUTPUT); //KEY_H4设置成输出模式
#define KEY_H4_QUASI_MODE GPIO_SetMode(P3,BIT5,GPIO_MODE_QUASI); //KEY_H4设置成准双向模式
#define KEY_H5_OUTPUT_MODE GPIO_SetMode(P3,BIT4,GPIO_MODE_OUTPUT); //KEY_H5设置成输出模式
#define KEY_H5_QUASI_MODE GPIO_SetMode(P3,BIT4,GPIO_MODE_QUASI); //KEY_H5设置成准双向模式
#define KEY_H6_OUTPUT_MODE GPIO_SetMode(P5,BIT1,GPIO_MODE_OUTPUT); //KEY_H6设置成输出模式
#define KEY_H6_QUASI_MODE GPIO_SetMode(P5,BIT1,GPIO_MODE_QUASI); //KEY_H6设置成准双向模式
#define KEY_H7_OUTPUT_MODE GPIO_SetMode(P5,BIT0,GPIO_MODE_OUTPUT); //KEY_H7设置成输出模式
#define KEY_H7_QUASI_MODE GPIO_SetMode(P5,BIT0,GPIO_MODE_QUASI); //KEY_H7设置成准双向模式
//每4ms调用一次
void Keyscan()
{
static _u16 Kcount;
static _u8 Key_num_old,Flag_key,en;
_u8 i;
//首先所有端口全部开上拉
GPIO_SetMode(P2,BIT6|BIT5|BIT4|BIT3,GPIO_MODE_QUASI);
GPIO_SetMode(P5,BIT6|BIT7|BIT3|BIT1|BIT0,GPIO_MODE_QUASI);
GPIO_SetMode(P0,BIT4,GPIO_MODE_QUASI);
GPIO_SetMode(P1,BIT0,GPIO_MODE_QUASI);
GPIO_SetMode(P3,BIT4|BIT5,GPIO_MODE_QUASI);
P0->DOUT|=0x00000010;
P1->DOUT|=0x00000001;
P2->DOUT|=0x00000078;
P5->DOUT|=0x000000CB;
P3->DOUT|=0x00000030;
Key_mum=0; //Key_mum 按下按键的数量
for(i=0;i<42;i++)
{
Key_n[i]=0; //Key_n[i] 是储存按键编号用,如果检测到有n个按键按下,则Key_n前n个数据储存的是按键编号。
if(i<7)
{
Key_data[i]=0; //把42个按键按行分为7组,每一组有6个按键,如果有按键按下相应的组的对应位就置1
}
}
KEY_H1_OUTPUT_MODE;
KEY_H1=0; //KEY_H1设置成输出,并输出0
Keydata_load(0); //检测在KEY_L的6个端口上是否有被拉低
KEY_H1_QUASI_MODE;
KEY_H1=1;
KEY_H2_OUTPUT_MODE;
KEY_H2=0;
Keydata_load(1);
KEY_H2_QUASI_MODE;
KEY_H2=1;
KEY_H3_OUTPUT_MODE;
KEY_H3=0;
Keydata_load(2);
KEY_H3_QUASI_MODE;
KEY_H3=1;
KEY_H4_OUTPUT_MODE;
KEY_H4=0;
Keydata_load(3);
KEY_H4_QUASI_MODE;
KEY_H4=1;
KEY_H5_OUTPUT_MODE;
KEY_H5=0;
Keydata_load(4);
KEY_H5_QUASI_MODE;
KEY_H5=1;
KEY_H6_OUTPUT_MODE;
KEY_H6=0;
Keydata_load(5);
KEY_H6_QUASI_MODE;
KEY_H6=1;
if(Compar_keydata())
{
Kcount=0;
Key_data_old[0]=Key_data[0];
Key_data_old[1]=Key_data[1];
Key_data_old[2]=Key_data[2];
Key_data_old[3]=Key_data[3];
Key_data_old[4]=Key_data[4];
Key_data_old[5]=Key_data[5];
Key_data_old[6]=Key_data[6];
Key_num_old=Key_num;
Flag_key_en=0;
}
else
{
if(Key_num_old==2)
{
if(!Flag_key_en)
{
Kcount++;
if(Kcount>=500) //如果同事按下两个按键,且长按
{
Kcount=0;
Flag_key_en=1;
Flag_key_long=1;
}
}
}
else if(Key_num_old==1) //如果只有1个按键按下 //消抖
{
if(!Flag_key_en)
{
Kcount++;
if(Kcount>=10) //消抖40ms
{
Kcount=0;
Flag_key_en=1;
Flag_key_short=1;
}
}
}
else
{
Kcount=0;
}
}
}
void Key_deal()
{
_u8 i;
if(Flag_key_short)
{
Flag_key_short=0;//只有1个按键按下
//根据Key_n[0]的值判定是哪个按键,进行相应处理
}
if(Flag_key_long)
{
Flag_key_long=0;
//根据Key_n[0],Key_n[1]的值判定是哪两个键,进行相应处理
}
}
uint8_t Compar_keydata()
{
uint8_t i;
for(i=0;i<7;i++)
{
if(Key_data[i]!=Key_data_old[i]) //如果按键有有变化
{
return 1;
}
}
return 0;
}
void Keydata_load(uint8_t i)
{
if(!KEY_L1)
{
Key_data[i]|=0x01;
Key_n[Key_num]=i*6+1; //储存按键编号
Key_num++;
}
if(!KEY_L2)
{
Key_data[i]|=0x02;
Key_n[Key_num]=i*6+2;
Key_num++;
}
if(!KEY_L3)
{
Key_data[i]|=0x04;
Key_n[Key_num]=i*6+3;
Key_num++;
}
if(!KEY_L4)
{
Key_data[i]|=0x08;
Key_n[Key_num]=i*6+4;
Key_num++;
}
if(!KEY_L5)
{
Key_data[i]|=0x10;
Key_n[Key_num]=i*6+5;
Key_num++;
}
if(!KEY_L6)
{
Key_data[i]|=0x20;
Key_n[Key_num]=i*6+6;
Key_num++;
}
}