目录
一、矩阵键盘的原理图、PCB图
二、矩阵键盘的初始化
- PF0到PF3固定为推挽输出,PF12到PF15固定为下拉输入。
- 即,无键按下时,对应PF12到PF15为0,有键按下时,PF12到PF15中,对应的引脚为高。
/**
******************************************************************************
* @file main.c
* @author Sumjess
* @version V1.0
* @date 2019-05-xx
* @brief 按键应用bsp(扫描模式)
******************************************************************************
* @attention
*
* 实验平台 :STM32 F429
* CSDN Blog :https://blog.csdn.net/qq_38351824
* 微信公众号 :Tech云
*
******************************************************************************
*/
/**
* @brief 配置矩阵按键用到的I/O口
* @param 无
* @retval 无
* @explain PF0到PF3固定为推挽输出,PF12到PF15固定为下拉输入。即,无键按下时,对应PF12到PF15为0,有键按下时,PF12到PF15中,对应的引脚为高。
*/
void Key4X4_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/*开启按键GPIO口的时钟*/
RCC_AHB1PeriphClockCmd(KEY_OUT_GPIO_CLK|KEY_IN_GPIO_CLK,ENABLE);
/*---------定义PF0到PF3为推挽输出---------*/
GPIO_InitStructure.GPIO_Pin = KEY_OUT_PIN; /*选择按键的引脚*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; /*设置引脚为输出模式*/
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; /*设置引脚的输出类型为推挽输出*/
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; /*设置引脚不上拉也不下拉*/
GPIO_Init(KEY_OUT_GPIO_PORT, &GPIO_InitStructure); /*使用上面的结构体初始化按键*/
/*---------定义PF4到PF7为下拉输入---------*/
GPIO_InitStructure.GPIO_Pin = KEY_IN_PIN; /*选择按键的引脚*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; /*设置引脚为输入模式*/
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; /*设置引脚下拉*/
GPIO_Init(KEY_IN_GPIO_PORT, &GPIO_InitStructure); /*使用上面的结构体初始化按键*/
}
三、扫描函数详解
解释说明在下面。
/
**
* @brief 矩阵键盘循环扫描
* @param 无
* @retval 返回键值
* @explain
*/
//实现矩阵键盘。返回值为,各按键的键值,此键值由用户自己定义。.
int KEY_Scan(void) //实现矩阵键盘。返回值为,各按键的键值,此键值由用户自己定义。
{
u8 KeyVal; //keyVal为最后返回的键值。
GPIO_Write(KEY_OUT_GPIO_PORT,((KEY_OUT_GPIO_PORT->ODR & 0xfff0) | 0x000f)); //先让PF0到PF3全部输出高。
if((KEY_IN_GPIO_PORT->IDR & 0xf000)==0x0000) //如果PF12到PF15全为0,则没有键按下。此时返回值为-1.
return -1;
else
{
Delay_ms(5); //延时消抖。
if((KEY_IN_GPIO_PORT->IDR & 0xf000)==0x0000)//如果延时5ms后,PF12到PF15又全为0,刚才引脚的电位变化是抖动产生的.
return -1;
}
//注意:如果程序能运行到下面,证明已经保证有按键按下了
GPIO_Write(KEY_OUT_GPIO_PORT,((KEY_OUT_GPIO_PORT->ODR & 0xfff0) | 0x0001)); //让PF3到PF0输出二进制的0001. ===> PF0为高电平,其余为低电平
switch(KEY_IN_GPIO_PORT->IDR & 0xf000) //对PF12到PF15的值进行判断,以输出不同的键值。
{
case 0x1000: KeyVal=15; break;
case 0x2000: KeyVal=11; break;
case 0x4000: KeyVal=7; break;
case 0x8000: KeyVal=3; break;
}
GPIO_Write(KEY_OUT_GPIO_PORT,((KEY_OUT_GPIO_PORT->ODR & 0xfff0) | 0x0002)); //让PF3到PF0输出二进制的0010. ===> PF1为高电平,其余为低电平
switch(KEY_IN_GPIO_PORT->IDR & 0xf000) //对PF12到PF15的值进行判断,以输出不同的键值。
{
case 0x1000: KeyVal=14; break;
case 0x2000: KeyVal=10; break;
case 0x4000: KeyVal=6; break;
case 0x8000: KeyVal=2; break;
}
GPIO_Write(KEY_OUT_GPIO_PORT,((KEY_OUT_GPIO_PORT->ODR & 0xfff0) | 0x0004)); //让PF3到PF0输出二进制的0100. ===> PF2为高电平,其余为低电平
switch(KEY_IN_GPIO_PORT->IDR & 0xf000) //对PF12到PF15的值进行判断,以输出不同的键值。
{
case 0x1000: KeyVal=13; break;
case 0x2000: KeyVal=9; break;
case 0x4000: KeyVal=5; break;
case 0x8000: KeyVal=1; break;
}
GPIO_Write(KEY_OUT_GPIO_PORT,((KEY_OUT_GPIO_PORT->ODR & 0xfff0) | 0x0008)); //让PF3到PF0输出二进制的1000. ===> PF3为高电平,其余为低电平
switch(KEY_IN_GPIO_PORT->IDR & 0xf000) //对PF12到PF15的值进行判断,以输出不同的键值。
{
case 0x1000: KeyVal=12; break;
case 0x2000: KeyVal=8; break;
case 0x4000: KeyVal=4; break;
case 0x8000: KeyVal=0; break;
}
return KeyVal;
}
GPIO_Write(KEY_OUT_GPIO_PORT,((KEY_OUT_GPIO_PORT->ODR & 0xfff0) | 0x000f)); //先让PF0到PF3全部输出高。
只解释这一句,一通百通。
1、说明
运算顺序:-> & |
0xfff0 后面的括号可以不加,但是由于总显示警告,还是加上了。
0xfff0 = 1111111111110000
0x000f = 0000000000001111
ODR:GPIO端口输出数据寄存器
& :两个数都为1,结果才是1
| :有一个1,结果就是1
--------------------------------------------------
2、作用
GPIOF->ODR : GPIOF端口输出数据寄存器
& 0xfff0 : 保证除了第0位~第3位以外的其他位,不会因下一步操作而受改变
| 0x000f : 使得第0位~第3位变为高电平
--------------------------------------------------
3、举例
例如 引脚F的各个引脚状态依次为1000 1001 0101 1100 ,我现在想使第0位~第3位变成1111,同时让其他位不受影响。
① 1000100101011100 = 0x895c
② 0x895c & 0xfff0 | 0x000f 这就是答案
③ 验证:
(1) 0x895c & 0xfff0 ===> 1000100101011100 & 1111111111110000 计算答案为 1000100101010000
(2) 不难发现,将第0位~第3位,变为0了
(3) 1000100101010000 | 0x000f ===> 1000100101010000 | 0000000000001111 计算答案为 1000100101011111
④ 1000100101011111 与之前的 1000100101011100
评论(0)
您还未登录,请登录后发表或查看评论