
由于我购买的最小的系统开发板只有一个按钮,因此调试和从事其他工作并不方便,因此我从宝库购买了4 * 4矩阵键盘来扩展按钮。能力是有限的。我基于之前学习的51个微控制器例程编写了一个简单而粗鲁的按键扫描程序。如果您需要在大型项目中使用它,最好使用中断来处理它〜
点击下载源代码
矩阵键盘的物理原理图



制造商在图片中给出的图片应标有错误的序列号。从左到右依次是S1-S4、S5-S8、S9-S12、S13-S16,请您自己照顾。


一般思想:首先将低电平输出到矩阵的4行,然后检测4列的输入,如果为“ 0”,则按下该列;然后将高电平输出到该列以检测行输入,如果它是'1',则该行是按钮在列中的位置,以便确定按钮所在的特定行。 (也可以先检测行,然后检测列)
void KEY1_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);//使能GPIOA、B
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//上拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_10|GPIO_Pin_11;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_ResetBits(GPIOA,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); //行输出低电平,扫描列
}
void KEY2_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_10;
GPIO_Init(GPIOB,&GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_10|GPIO_Pin_11); //扫描行
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; //下拉输入
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
u8 KeyScan(void)
{
u8 column=0,KeyValue=0;
KEY1_Init(); //行输入低电平,扫描列
while(1)
{
if(PBin(0)==0)
{
delay_ms(50);
if(PBin(0)==0)
{
column=1; //第一列
}
}
if(PBin(1)==0)
{
delay_ms(50);
if(PBin(1)==0)
{
column=2; //第二列
}
}
if(PBin(10)==0)
{
delay_ms(50);
if(PBin(10)==0)
{
column=3; //第三列
}
}
if(PBin(11)==0)
{
delay_ms(50);
if(PBin(11)==0)
{
column=4; //第四列
}
}
if(column==1)
{
KEY2_Init(); //列输出高电平,扫描行
if(PAin(7)==1) //第一列第一行
{
KeyValue=1;
break;
}
if(PAin(6)==1) //第一列第二行
{
KeyValue=5;
break;
}
if(PAin(5)==1) //第一列第三行
{
KeyValue=9;
break;
}
if(PAin(4)==1) //第一列第四行
{
KeyValue=13;
break;
}
}
if(column==2)
{
KEY2_Init(); //以下同理
if(PAin(7)==1)
{
KeyValue=2;
break;
}
if(PAin(6)==1)
{
KeyValue=6;
break;
}
if(PAin(5)==1)
{
KeyValue=10;
break;
}
if(PAin(4)==1)
{
KeyValue=14;
break;
}
}
if(column==3)
{
KEY2_Init();
if(PAin(7)==1)
{
KeyValue=3;
break;
}
if(PAin(6)==1)
{
KeyValue=7;
break;
}
if(PAin(5)==1)
{
KeyValue=11;
break;
}
if(PAin(4)==1)
{
KeyValue=15;
break;
}
}
if(column==4)
{
KEY2_Init();
if(PAin(7)==1)
{
KeyValue=4;
break;
}
if(PAin(6)==1)
{
KeyValue=8;
break;
}
if(PAin(5)==1)
{
KeyValue=12;
break;
}
if(PAin(4)==1)
{
KeyValue=16;
break;
}
}
}
return KeyValue;
}

效果图片




注意:
①选择开发板的IO端口时,请务必查看原理图或数据表以确保这8个IO端口可用(编辑器最初使用PB2引脚,但在调试后使用很长时间以来,我没有得到正确的结果。我检查了N次程序,没问题。最后,我回到硬件上,发现只有PB2连接到BOOT1和GND,所以大多数结果是错误的。我希望其他朋友不要走进去。坑哈哈)
②关于IO端口输入和输出模式的选择。输出模式通常为推挽输出,因为它可以直接输出0或1;否则,输出为0。对于输入模式,按钮的一侧输出0(1),然后检查是否有按钮按下,另一侧应选择上拉输入将此引脚设置为1(下拉输入将此引脚设置为0)。
③该程序没有编写按钮释放检测程序,因此可以在不释放按钮的情况下进行检测;想要检测按钮释放的朋友可以将静态变量设置为按钮释放符号。
这里使用的方法相对简单易懂,但是占用了MCU资源。如果您有很好的推荐,欢迎交流! ! !如果要下载源代码,可以在邮箱中留言(设置了0C,几天后价格会自动上涨)。
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/bofangqi/article-336935-1.html
但是必须提高井惕识破诱敌