STM32 cubemx GPIO应用之键盘使用

使用STM32 CubeMx 实现键盘使用 并将按键数值显示到数码管

GPIO的介绍已经在 上一篇写过了
下面直接讲 键盘使用
应用演示链接

键盘原理

电路连接如图

enter description here

  1. 反转法

先将 (将行设为output)行的GPIO设为高电平,(将列设为input)读取列GPIO的电位,如果某列存在低电平,说明该列有键值被按下
再将(将列设为output)列的GPIO设为低电平,(将行设为input)读取行GPIO的电位,如果某行存在低电平,说明该行有键值被按下,
通过两次的反转确定了行和列 就可以获取到按下的键值

  1. 扫描法
    将列所在GPIO设为input
    将行所在GPIO设为output

遍历所有行,先将一行设为高电平,其他行设为低电平,读取所有列的值。如果有列存在低电平,就可以根据所遍历到的该列和该行获取到按键所在的位置 。
按键消抖
为了确保对一次按键动作只确认一次按键有效,必须消除抖动期的影响
软件消抖:
利用软件延时实现消抖
在检测到有键按下时(对应的行线为低电平),延时5-15ms后,若该行线仍为低电平,则确认该行确实有键按下。否则可认为是扰动。(软件消抖)
硬件消抖:
采用相应硬件电路,消除信号的抖动。
硬件常见有2种:
采用专用的键盘/显示器接口芯片:芯片中有自动去抖动的硬件电路。
采用基本RS触发器消除抖动
有查询式和中断式的。查询式是一直运行或延时判断是否有键被按下,中断式是使用中断判断按键被按下。

配置cubemx

  1. 查看原理图
    找出按键的行和列 对应的GPIO口
    enter description here =700*600

可以看到列对应的GPIO口是 B0 B1 B13 B12
行对应的GPIO口是A6 A7 C4 C5
而且是共阳极 低电平有效 (大多元器件都是共阳极,可能是因为在数电中 非对应的也就是0更好用)
2. 配置相应GPIO口
这里示例使用 扫描法 (好处理)
将行所在引脚设置为input 列所在引脚设为output

enter description here =500*400

同时也需要将数码管的给配置了 (STM32 GPIO应用之led灯、数码管里面有)

  1. 保存导出
    配置项目名称,IDE等 合成代码
编写代码

使用扫描法 查询式
enter description here
这里的键盘处理子程序就是 显示到数码管上面去。
1.数码管部分代码
数码管原理等部分可以参考另外一篇文章
这里给出代码

struct GPIO_PACK{
		GPIO_TypeDef * port;
		uint16_t pin;
	};
	struct GPIO_PACK segs[8]= {
	{GPIOA,GPIO_PIN_15},
	{GPIOA,GPIO_PIN_11},
	{GPIOC,GPIO_PIN_9},
	{GPIOC,GPIO_PIN_7},
	{GPIOC,GPIO_PIN_8},
	{GPIOA,GPIO_PIN_12},
	{GPIOA,GPIO_PIN_8},
	{GPIOC,GPIO_PIN_6},
	}	;
	struct GPIO_PACK bits[4]={
	{GPIOD,GPIO_PIN_2},
	{GPIOB,GPIO_PIN_4},
	{GPIOB,GPIO_PIN_6},
	{GPIOB,GPIO_PIN_7},
	};
uint8_t shuzu[]={
	0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
	0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
};
void DisplayOnebit(uint8_t digtal,uint8_t bit){
		uint8_t i;
		for(i=0;i<8;i++){
			HAL_GPIO_WritePin(segs[i].port,segs[i].pin,(GPIO_PinState)(shuzu[digtal]&(0x01<<i)));
		}
		for(i=0;i<4;i++){
			HAL_GPIO_WritePin(bits[i].port,bits[i].pin,(GPIO_PinState)(i!=bit));
		}
}

void DisplayDigtal(uint16_t digtal){
	int a=0;
	while(a<10)
	{
	a++;
	DisplayOnebit(digtal%10,0);
	HAL_Delay(5);
	if (digtal>=10){
	DisplayOnebit(digtal/10%10,1);
	HAL_Delay(5);
	if (digtal>=100){
	DisplayOnebit(digtal/100%10,2);
	HAL_Delay(5);
	if (digtal>=1000){
	DisplayOnebit(digtal/1000%10,3);
	HAL_Delay(5);
		
				}
			}
		}
	}
}

代码讲解也参考那篇文章
2. 按键 扫描法代码
按键的结构数组
列的放到lie结构数组中 行的放到 hang中

struct GPIO_PACK lie[4]={   
   {GPIOB,GPIO_PIN_0},
   {GPIOB,GPIO_PIN_1},
   {GPIOB,GPIO_PIN_13},
   {GPIOB,GPIO_PIN_12}
};
struct GPIO_PACK hang[4]={
   {GPIOA,GPIO_PIN_6},
   {GPIOA,GPIO_PIN_7},
   {GPIOC,GPIO_PIN_4},
   {GPIOC,GPIO_PIN_5}
};

扫描法获取键值

void Displaykeying()
	{
		uint8_t i,j,s,key=0;uint8_t k=1;
		for(i=0;i<4;i++)
	{	 HAL_GPIO_WritePin(lie[i].port,lie[i].pin,GPIO_PIN_RESET);	
		for(s=0;s<4;s++){
		if(i!=s)
			HAL_GPIO_WritePin(lie[s].port,lie[s].pin,GPIO_PIN_SET);}
		for(j=0;j<4;j++)
	{	k=HAL_GPIO_ReadPin(hang[j].port,hang[j].pin);
		if(k==0)
			HAL_Delay(5);
			if(k==0)
			switch(j)
			{
				case 0:key=j+1+i;break;
				case 1:key=j+4+i;break;
				case 2:key=j+7+i;break;
				case 3:key=j+10+i;break;
			}			  	
		}		
	}	
	//if(key!=0)
		DisplayDigtal(key);
	}

首先 第一个for循环 遍历列 ,遍历的列置低电平,使用嵌套第一个for循环使不是遍历到的那列置高电平,使用嵌套第二个for循环读取每一行的电位。
如果读取到有电位为低电平,加上延时去抖,还是低电平则说明有键被按下,而该键的位置就是遍历的列和 此时的行。
根据每个键对应的值,使用switch 获取。

获取到的键值,使用DisDigtal函数(封装好的数码管显示数值),直接就能显示出当前按下的键值。

在main主函数 while循环中 添加扫描键盘的函数Displaykeying就可以了

Displaykeying();

使用反转法

  1. cubemx中配置 列和行所在位置 配置为output
  2. 将数码管部分代码也要粘贴过来
  3. 代码中 要将行设为输出 列设为输入 和行设为输入 列设为输出
    代码
void Loutput()
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.Pin = H1_Pin|H2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  HAL_GPIO_WritePin(GPIOB, L1_Pin|L2_Pin|L4_Pin|L3_Pin, GPIO_PIN_RESET);
  /*Configure GPIO pins : H3_Pin H4_Pin */
  GPIO_InitStruct.Pin = H3_Pin|H4_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
	GPIO_InitStruct.Pin = L1_Pin|L2_Pin|L4_Pin|L3_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
	
}
void Houtput(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GPIO_InitStruct.Pin = H1_Pin|H2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  HAL_GPIO_WritePin(GPIOA,H1_Pin|H2_Pin,GPIO_PIN_RESET);
  /*Configure GPIO pins : H3_Pin H4_Pin */
  GPIO_InitStruct.Pin = H3_Pin|H4_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
	HAL_GPIO_WritePin(GPIOC,H3_Pin|H4_Pin,GPIO_PIN_RESET);
	GPIO_InitStruct.Pin = L1_Pin|L2_Pin|L4_Pin|L3_Pin;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

根据反转法 读取键值

uint8_t keyread(void)
{
	Loutput();HAL_Delay(5);
	if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_5)==GPIO_PIN_RESET)line=4;
  else if(HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_4)==GPIO_PIN_RESET)line=3;
	else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_7)==GPIO_PIN_RESET)line=2;
	else if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6)==GPIO_PIN_RESET)line=1;
	else return 0;
	Houtput();HAL_Delay(5);
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET)row=1;
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET)row=2;
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_13)==GPIO_PIN_RESET)row=3;
	else if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_12)==GPIO_PIN_RESET)row=4;
	Loutput();HAL_Delay(5);
	return 1;
}

该函数如果有按键被按下则line 和row 值会直接发生变化,并返回1 没有检测到按键返回0
其中 line 和row是变量 需要在前面声明

while循环中需要添加部分代码

i = keyread();
if(i)
{
key = (line -1)*4 +row;
DisplayDigtal(key);
}

调用函数获取返回值,返回1则有键被按下,判断出键值,数码管显示键值。
在main函数之前定义变量

uint8_t line=0,row=0,i=0,key=0;

完成代码链接(使用的扫描法) GitHub

更多STM32学习教程
  1. STM32 cubemx keil5搭建学习环境
  2. 使用STM32 cubemx keil5实现led灯与数码管控制
  3. 基于STM32 CubeMx keil5实现键盘的应用
  4. 基于STM32 CubeMx keil5实现串口通信 I2C与GPIO综合应用
  5. 基于STM32 CubeMx keil5实现AD转换获取温度
  6. 基于STM32 CubeMx keil5 学习使用I2C
  7. 基于STM32 CubeMx keil5 学习使用串口通信
  8. 基于STM32 CubeMx keil5应用定时器
  9. 基于STM32 cubemx keil5学习使用中断
  10. 基于STM32 cubemx keil5综合应用实现温度控制系统
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32CubeMX支持矩阵键盘4x4的配置,可以通过STM32CubeMX工具进行设置。在工具中选择对应的GPIO引脚,设置为输入模式,并启用内部上拉电阻。然后选择矩阵键盘4x4的模式,并设置对应的行列映射关系。最后生成代码并下载到STM32芯片中即可使用。 ### 回答2: STM32CubeMX是一种由STMicroelectronics公司开发的嵌入式软件配置工具,可帮助软件开发人员更轻松地配置和生成STM32微控制器的初始化代码。其中,矩阵键盘是一种常见的外设,可用于实现用户和嵌入式系统之间的交互。接下来,我们将讨论STM32CubeMX在矩阵键盘4x4方案中的应用。 1. 硬件配置 首先,需要通过STM32CubeMX工具在芯片上配置GPIO引脚,将矩阵键盘的按键连接到特定引脚。在4x4矩阵键盘中,有16个按键需要连接。STM32CubeMX支持简单的拖放式界面,使硬件配置更加容易和直观。 2. 码率设置 在完成硬件配置后,需要设置矩阵键盘的扫描速率。这可以通过调整代码中的扫描周期来实现。通常情况下,使用50-100ms左右的扫描周期是比较合适的。在编写代码时,必须确保扫描周期足够长,以确保键盘上的每个按键都有足够的时间进行扫描,并且不会产生抖动。 3. 读取按键状态 在矩阵键盘4x4方案中,需要对按键进行扫描,并读取它们的状态。在代码中,可以使用轮询的方式来扫描按键状态,也可以使用中断方式来响应按键事件。在进行轮询时,通常使用一个循环语句实现,并使用if语句判断按键是否被按下。使用中断方式时,当按键被按下时,会触发一个中断,该中断将被捕获并用于执行相应操作。 4. 处理按键事件 一旦检测到按键事件,需要对其进行处理。在处理按键事件时,可以使用带有标志的变量来标记按键状态。也可以将按键事件添加到一个队列中,在主循环或另一个线程中处理它们。无论采用哪种方法,都需要提供适当的保护措施来防止竞争条件和其他多线程问题的出现。 综上所述,使用STM32CubeMX可以轻松地实现矩阵键盘4x4方案。为了实现有效的按键扫描和事件处理,需要在硬件配置、码率设置、读取按键状态和处理按键事件等方面进行仔细的规划和编程。这也需要开发人员具有嵌入式系统和硬件编程方面的知识和经验。 ### 回答3: STM32CubeMX是一种图形化的配置工具,适用于为STMicroelectronics的STM32微控制器生成初始化代码和配置文件。矩阵键盘是一种常见的输入外设,可以通过连接按键和一个控制器来实现输入的读取。STM32CubeMX支持矩阵键盘的配置,其中4x4是指这个矩阵键盘有4行和4列。 具体来说,STM32CubeMX可以生成代码来配置GPIO用作矩阵键盘的行和列。例如,可以选择四个GPIO引脚用于控制键盘的行,再选择另外四个GPIO引脚用于读取键盘的列。这些引脚需要在代码中被配置为输入或输出,并配置到正确的位置上。接下来,可以在代码中实现一个扫描算法,周期性地扫描键盘的每一行,并逐列检查该行上按下的按键。如果发现某个按钮被按下,则可以触发一个事件或者执行一个特定的操作。 STM32CubeMX还可以配置额外的细节,例如按键去抖动和输入电平的滤波等。可以选择不同的算法来处理这些问题,或者使用默认的选项。此外,还可以为矩阵键盘配置中断,以便在按键按下或释放时触发中断服务程序。这是一种高效的方式,以确保键盘操作被及时处理。 总之,STM32CubeMX提供方便易用的工具来配置矩阵键盘4x4,其代码生成功能可以减少开发时间,并且可以确保配置项正确、可靠。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值