赞
踩
4x4 矩阵键盘是一种常见的输入设备,通常由 16 个按键组成,排列成一个 4 行 4
列的矩阵。每个按键在按下时会连接某一行和某一列,通过扫描矩阵中的行和列,可以确定用户按下的是哪一个按键。
在使用这个模块的时候,最简单的方法是需要8个引脚,其中4个分别代表4行,另外4个代表4列。
代表行的引脚需要设置成推挽输出模式,代表列的引脚需要设置成上拉输入模式.。
当然你反着去设置也是完全没有问题的,即:
代表行的引脚需要设置成上拉输入模式,代表列的引脚需要设置成推挽输出模式.。
只不过这样的话,程序要稍微更改或者你直接把行作为列去使用。
我使用的是行设置成推挽输出模式,列设置成上拉输入模式。
然后,我们让行的4个引脚其中一个输出低电平,其他输出高电平,此时在循环中去不断循环等待,当我们按下一个在当前低电平引脚对应行的按键的时候,被设置为上拉输入模式的列引脚就会因为当前行是低电压而被拉低,这样我们就可以判断这个行上面哪个列引脚被拉下了。
接下来就是一个循环,让4个行引脚分别1个输出低电平,3个输出高电平。芯片的循环速度很快,所以你完全不用怀疑这种做法的可行性。
int main(void) { uint8_t regval = 0x07; while (1) { /* 4X4矩阵键盘程序 硬件连线: PA0 - R1 控制 S13~16 PA1 - R2 控制 S9~12 PA2 - R3 控制 S5~8 PA3 - R4 控制 S0~4 PA4 - C4 控制 S0~13 PA5 - C3 控制 S2~14 PA6 - C2 控制 S3~15 PA7 - C1 控制 S4~16 */ /*置位 0x07->0x0B->0x0D->0x0E->0x07 循环*/ GPIOA->BSRR |= regval; /**/ uint8_t temp = GPIOA->IDR & 0xF0; /*消抖*/ HAL_Delay(10); /*当有按键按下时*/ if(temp != 0xF0) { temp = GPIOA->IDR & (0xF0 + regval); switch(temp & 0xF0) { case 0xE0: printf("%d\r\n",(int)(1 + (3 - log2(~temp&0x0F))*4)); break; case 0xD0: printf("%d\r\n",(int)(2 + (3 - log2(~temp&0x0F))*4)); break; case 0xB0: printf("%d\r\n",(int)(3 + (3 - log2(~temp&0x0F))*4)); break; case 0x70: printf("%d\r\n",(int)(4 + (3 - log2(~temp&0x0F))*4)); break; } } GPIOA->BSRR |= regval << 16;/*置零寄存器数据位*/ /*0x07 0x0B 0x0D 0x0E 循环*/ regval = (~((~regval& 0x0F) >> 1))& 0x0F; /* 如果regval在0x0E之后继续进上一行的代码运算,就会变成0X0F 即0000 1110 ~ -> 1111 0001 & 0x0F-> 0001 >> 1 -> 0000 0000 ~-> 1111 1111 &0x0F -> 0000 1111 所以,我们让他置为0x07初始值来完成这个循环*/ if((regval & 0x0F) == 0x0F) regval = 0x07; } }
这个逻辑我直接写在主函数里面,当然你完全可以封装他为一个函数,我这样操作也只是为了方便测试和使用。
printf通过串口输出程序:
#if 1
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//重定向fputc函数
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
#endif
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。