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综合应用实现温度控制系统
发布了46 篇原创文章 · 获赞 59 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/Nirvana_6174/article/details/104304682