//write by dragonbao 2011-9-16.
这是硬件上的键盘规划
// | 1 | 2 | 3 | 4 | ---line 1 PE6 //
// --------------------------- //
// | 5 | 6 | 7 | 8 | ---line 2 PE5 //
// --------------------------- //
// | 9 | 10| 11| 12| ---line 3 PE4 //
// --------------------------- //
// | 13| 14| 15| 16| ---line 4 PE3 //
// --------------------------- //
// | 17| 18| 19| 20| ---line 5 PE2 //
// --------------------------- //
// | | | | //
// col1 col2 col3 col4 //
// PE0 PB5 PB8 PB9 //
//_________________________________________________//
参考了下基于avr的矩阵键盘程序,耐着性子移植到符合上面硬件规划的stm32板子上。
volatile uint8_t key_flag = 0;
void key_init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
//key output
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOE,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_9;
GPIO_Init(GPIOB,&GPIO_InitStructure);
//key input
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
GPIO_Init(GPIOE,&GPIO_InitStructure);
}
//判断是否有键按下函数,对键盘进行一次扫描
//返回键盘接口状态,有键按下时返回键值;没有键按下返回无效标志位
uint8_t Is_Key_PressOn(void)
{
volatile uint8_t i,ScanCode;
for(i=0;i<4;i++)
{
switch(i) //扫描信号产生
{
case 0:
GPIOE->BSRR = 0x00010000;//PE0 = 0;
GPIOB->BSRR = 0x00000320;//PB5 = 1; PB8 = 1; PB9 = 1;
key_flag = 1;
break;
case 1:
GPIOE->BSRR = 0x00000001;//PE0 = 1;
GPIOB->BSRR = 0x00200300;//PB5 = 0; PB8 = 1; PB9 = 1;
key_flag = 2;
break;
case 2:
GPIOE->BSRR = 0x00000001;//PE0 = 1;
GPIOB->BSRR = 0x01000220;//PB5 = 1; PB8 = 0; PB9 = 1;
key_flag = 3;
break;
case 3:
GPIOE->BSRR = 0x00000001;//PE0 = 1;
GPIOB->BSRR = 0x02000120;//PB5 = 1; PB8 = 1; PB9 = 0;
key_flag = 4;
break;
default: key_flag = 0; break;
}
if((((uint8_t)GPIOE->IDR)|0x83)!=0xff)
return ((uint8_t)GPIOE->IDR | 0x83);
}
return(PRESS_INVALID);
}
//找到闭合键,判断延时前后两次键值是否相同,如果相同则返回键值
uint8_t Find_Key_PressOn(uint8_t KeyCode_before,uint8_t KeyCode_after)
{
if(KeyCode_before==KeyCode_after) return(KeyCode_after);
else return(PRESS_INVALID);
}
//计算键值,根据返回的键值计算相应的返回值
uint8_t Calc_Key_PressOn(uint8_t KeyCode)
{
uint8_t TempNum;
switch(KeyCode)
{
case 0xBF:
if(1==key_flag)
{
TempNum = 1;break;
}
else if(2==key_flag)
{
TempNum = 2;break;
}
else if(3==key_flag)
{
TempNum = 3;break;
}
else if(4==key_flag)
{
TempNum = 4;break;
}
else break;
case 0xDF:
if(1==key_flag)
{
TempNum = 5;break;
}
else if(2==key_flag)
{
TempNum = 6;break;
}
else if(3==key_flag)
{
TempNum = 7;break;
}
else if(4==key_flag)
{
TempNum = 8;break;
}
else break;
case 0xEF:
if(1==key_flag)
{
TempNum = 9;break;
}
else if(2==key_flag)
{
TempNum = 10;break;
}
else if(3==key_flag)
{
TempNum = 11;break;
}
else if(4==key_flag)
{
TempNum = 12;break;
}
else break;
case 0xF7:
if(1==key_flag)
{
TempNum = 13;break;
}
else if(2==key_flag)
{
TempNum = 14;break;
}
else if(3==key_flag)
{
TempNum = 15;break;
}
else if(4==key_flag)
{
TempNum = 16;break;
}
else break;
case 0xFB:
if(1==key_flag)
{
TempNum = 17;break;
}
else if(2==key_flag)
{
TempNum = 18;break;
}
else if(3==key_flag)
{
TempNum = 19;break;
}
else if(4==key_flag)
{
TempNum = 20;break;
}
else break;
default : TempNum=0;break; //发生错误时返回,无效标志
}
return(TempNum); //正常返回值为1~16
}
//键盘扫描主程序
uint8_t Keyboard(void)
{
uint8_t key_temp; //暂存键值的变量
key_temp=Is_Key_PressOn(); //判断是否有键闭合
// PORTC=key_temp; 调试过程中使用,正常运行时没用可以删除
if (key_temp==PRESS_INVALID) //判断该次扫描中是否有键按下
return(PRESS_INVALID); //没有闭合则建立无效标志
else
delay_nus(100); //闭合则延时
key_temp=Find_Key_PressOn(key_temp,((uint8_t)GPIOE->IDR | 0x83)); //找到闭合键
if (key_temp==PRESS_INVALID)
return(key_temp); //若延时前后键值不相等则返回无效标志
else
key_temp=Calc_Key_PressOn(key_temp); //有效则计算键值
while((((uint8_t)GPIOE->IDR)|0x83)!=0xff)//等待键放。。。看实际情况使用
{
delay_nus(10);
}
return(key_temp); //返回键值
}
。。。。。。。
有更好建议或意见的请不吝指出。。。。
用户377235 2013-9-20 23:36
用户1630203 2012-12-14 09:31
用户1614644 2012-4-18 15:59