这是自己写的扫描第一行按键的程序代码。
PE的位8~位11设置为下拉输入。
PE的位12~位15设置为推挽输出
其中PE的位11是4*4键盘的第一列,PE的为键盘的第一行。
先将第一行设置为高电平,检测列中是否有高电平
u8 KEY_Scan(u8 mode)
{
staticu8 key_up=1;//按键按松开标志
if(mode)key_up=1; //支持连按
GPIO_SetBits(GPIOE,GPIO_Pin_15);
if(key_up&&( (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_8))
||(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_9))
||(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_10))
||(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_11)) ) )
{
delay_ms(10);//去抖动
key_up=0;
if(GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_8) )return 10;
elseif( GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_9) )return 3;
elseif( GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_10) )return 2;
elseif( GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_11) )return 1;
}elseif( (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_8))==0
&&(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_9))==0
&&(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_10))==0
&&(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_11))==0 )key_up=1;
return 0;// 无按键按下
}
写好扫描一行后,对比网上别人写的代码,发现写的十分冗长,原因:调用了库函数的位操作函数对4位进行操作。而不是进行整理处理。然后改写如下:
GPIO_Write(GPIOE,0x8000);
if((key_up) && (GPIOE->IDR & 0x0f00) )
{
delay_ms(10);//去抖动
key_up=0;
switch(GPIOE->IDR & 0x0f00 )
{
case 0x0100: KeyVal=10; break;
case 0x0200: KeyVal=3; break;
case 0x0400: KeyVal=2; break;
case 0x0800: KeyVal=1; break;
}
}
elseif ( ( GPIOE->IDR & 0x0f00) ) ;key_up=1; //若松开按键,则将key_up置一。
改写成功后,自己就以为4*4键盘只要将代码复制,改动一下GPIO_Write(GPIOE, 0x8000);中的数值。
结果发现只有最后一行的按键不支持连按。其他的若一直按着,就会一直刷新按键值(自己在串口中观察,相关代码未贴出来)。不符合自己设计的要求,即按键不支持连按。
于是进入Debug模式。逐行调试,观察GPIOE的输入数据寄存器(GPIOx_IDR),由于是if语句判断,当没松开后就程序就会运行扫描第二行的代码时,写GPIO_Write(GPIOE,0x4000)时候,(GPIOx_IDR) 的值就改变了,因此后面的if语句就会将key_up就会被置一,而非等到自己按键松开了。长按自然会反复刷新按键值。
只要将if语句改为while语句即可。即按键送下来之前不进行后面的扫描!
这个问题很简单,自己在写的时候都没有发现。不过最终还是调试出来了。
自己写程序会犯各种低级错误,比如自己甚至连 & 和 &&都未区分开来,后面自己在编译器写了一段测试代码才区分开来。
这会让在上面浪费很多时间。上面说的小问题,就耗费了自己数个小时,因为自己之前都是在脑袋中想象代码的的执行流程。。。
但是我还是要坚持这种学习方法,问题虽然会很多,但也正是如此才能发现自己的缺陷,自己去思考,去写了代码,对知识的理解也会更深。