矩阵按键外设

并入传出芯片(IO口更少的情况)

行列反转方式

在这里插入图片描述

a. 将PA0PA3设置为上拉输入,PA4PA7设置为推挽输出(底电平) 确定列

PA3~PA0效果
1111(0xF)
1110(0xE)第一列
1101(0xD)第二列
1011(0xB)第三列
0111(0x7)第四列

b. 将PA4-PA7设置为上拉输入,PA0-PA3设置为推挽输出(底电平) 确定行

PA7~PA4效果
1111(0xF0)
1110(0xE0)第一行
1101(0xD0)第二行
1011(0xB0)第三行
0111(0x70)第四行

根据扫描结果来确定键值

键值 = (4 * (列数 - 1)) + 行数

// 设计一个函数,实现返回按下按键的键值
### 伪代码

1. 开启PA端口的时钟
2. 将PA0~PA3设置为上拉输入,PA4~PA7设置为推挽输出(底电平)
3. 读取PA0~PA3的电平状态
	if (PA0~PA3 != 0xf)
	{
		// 消抖
		if (PA0~PA3 != 0xf)
		{
			switch(PA0~PA3)
			{
				case 0xE: num = 0;
				case 0xD: num = 4;
				case 0xB: num = 8;
				case 0x7: num = 12;
			}
		}
	}
	else 
	{
		return 0;
	}
4. 电平反转  将PA4-PA7设置为上拉输入,PA0-PA3设置为推挽输出(底电平)
5. 读取PA4~PA7的电平状态
	if (PA4~PA7 != 0xf)
	{
		// 消抖
		if (PA0~PA3 != 0xf)
		{
			switch(PA0~PA3)
			{
				case 0xE: num += 1;
				case 0xD: num += 2;
				case 0xB: num += 3;
				case 0x7: num += 4;
			}
		}
	}
	else 
	{
		return 0;
	}
	
//RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 将这个放到Main中,防止重复
int Matrix_Key_Scan(void)
{	
	GPIO_InitTypeDef GPIO_InitStructure;
	u8 key, val = 0;
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_WriteBit(GPIOA, GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7, Bit_RESET);
	
    // GPIO_ReadOutputDataBit 库函数
	if((GPIOA->IDR & 0xF) != 0xF) // 寄存器操作
	{
		Delay_us(1000); // 消抖
		key = GPIOA->IDR & 0xF;
		if(key != 0xF)
		{
			switch(key)
			{
				case 0xE: val = 0; break;
				case 0xD: val = 4; break;
				case 0xB: val = 8; break;
				case 0x7: val = 12; break;
				default: break;
			}
		}
		else
			return 0;
		
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //修改的地方
		GPIO_Init(GPIOA, &GPIO_InitStructure);
		
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
		GPIO_Init(GPIOA, &GPIO_InitStructure);
		
		GPIO_WriteBit(GPIOA, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3, Bit_RESET);
		
		if((GPIOA->IDR & 0xF0) != 0xF0)
		{
			Delay_us(1000);
			key = GPIOA->IDR & 0xF0;
			if(key != 0xF0)
			{
				switch(key)
				{
					case 0xE0: val += 1; break;
					case 0xD0: val += 2; break;
					case 0xB0: val += 3; break;
					case 0x70: val += 4; break;
					default: break;
				}
			}
			else
				return 0;
		}
		else
			return 0;
		
		while((GPIOA->IDR & 0xF0) != 0xF0);
		return val;
	}
	else
		return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值