首先感谢 江科大 的stm32入门课程 受益匪浅。推荐有兴趣的朋友去看看。

先看看我用的矩阵键盘是啥样的(很常见的一种)

接线如图(其他型号根据自己需求接上GPIO口)

代码基于stm大善人的代码修改而来,讲的很详细,非常感谢。

直接上代码:

头文件Key4x4.h

#ifndef __KEY4x4_H
#define __KEY4x4_H void KEY_4x4_Init(void);
void KEY_Scan(void);
u16 Key_Read(void); #endif

主体文件Key4x4.c

#include "stm32f10x.h"
#include "Delay.h" u8 anxia = 0;
u8 key = 1;
u16 line[4] = {0x00fe , 0x00fd , 0x00fb ,0x00f7};
u16 off = 0x00ff; // 全部引脚置为1
u16 keys[16] = {
49, 50, 51, 65,
52, 53, 54, 66,
55, 56, 57, 67,
42, 48, 35, 68,
}; void KEY_4x4_Init(void){ GPIO_InitTypeDef GPIO_InitStructre;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE); // 使能 GPIOA 的时钟 // 第一组
GPIO_InitStructre.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructre.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructre.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA , &GPIO_InitStructre);
GPIO_SetBits(GPIOA , GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
// 第二组数据
GPIO_InitStructre.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructre.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA , &GPIO_InitStructre);
GPIO_SetBits(GPIOA , GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7); } void Do_Click(uint16_t gpio_pin_x , u8 num){
anxia = 1;
key = num;
while(!GPIO_ReadInputDataBit(GPIOA , gpio_pin_x));
} void KEY_Click_Listener(u8 num){
if((GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_4)==0)||(GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_5)==0)||(GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_6)==0)||(GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_7)==0)){
Delay_ms(10);
if(0 == GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_4)){
Do_Click(GPIO_Pin_4 , num+0);
}else if(0 == GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_5)){
Do_Click(GPIO_Pin_5 , num+1);
}else if(0 == GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_6)){
Do_Click(GPIO_Pin_6 , num+2);
}else if(0 == GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_7)){
Do_Click(GPIO_Pin_7 , num+3);
}else {
anxia = 0;
GPIO_Write(GPIOA , off);
}
}
} void KEY_Scan(){
// 第一行 1111 1110
GPIO_Write(GPIOA , line[0]);
KEY_Click_Listener(1);
// 第二行
GPIO_Write(GPIOA , line[1]);
KEY_Click_Listener(5);
// 第三行
GPIO_Write(GPIOA , line[2]);
KEY_Click_Listener(9);
// 第四行
GPIO_Write(GPIOA , line[3]);
KEY_Click_Listener(13);
} u16 Key_Read(){
return keys[key-1];
}

主要代码说明:

初始化配置 (KEY_4x4_Init):

  • 使能GPIOA模块的时钟。
  • 配置GPIOA的前四个引脚(GPIO_Pin_0至GPIO_Pin_3)为推挽输出模式,用于键盘行线的扫描。
  • 设置GPIOA的后四个引脚(GPIO_Pin_4至GPIO_Pin_7)为上拉输入模式,用于检测键盘列线的状态。
// 第一组
GPIO_InitStructre.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructre.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructre.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA , &GPIO_InitStructre);
GPIO_SetBits(GPIOA , GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
// 第二组数据
GPIO_InitStructre.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructre.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA , &GPIO_InitStructre);
GPIO_SetBits(GPIOA , GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);

按键检测 (KEY_Click_Listener):

  • 检测列线状态,如果有键按下,则调用Do_Click函数记录按键信息并等待按键释放。
  • 使用延时函数Delay_ms来消除抖动。
void KEY_Click_Listener(u8 num){
if((GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_4)==0)||(GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_5)==0)
||(GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_6)==0)||(GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_7)==0)){
Delay_ms(10);
if(0 == GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_4)){
Do_Click(GPIO_Pin_4 , num+0);
}else if(0 == GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_5)){
Do_Click(GPIO_Pin_5 , num+1);
}else if(0 == GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_6)){
Do_Click(GPIO_Pin_6 , num+2);
}else if(0 == GPIO_ReadInputDataBit(GPIOA , GPIO_Pin_7)){
Do_Click(GPIO_Pin_7 , num+3);
}else {
anxia = 0;
GPIO_Write(GPIOA , off);
}
}
}
void Do_Click(uint16_t gpio_pin_x , u8 num){
anxia = 1;
key = num;
while(!GPIO_ReadInputDataBit(GPIOA , gpio_pin_x));
}

扫描过程 (KEY_Scan):

  • 循环扫描每一行,通过改变行线的状态来检测是否有键按下。
  • 调用KEY_Click_Listener函数来处理每一行的按键检测。

读取按键值 (Key_Read):

  • 返回当前按下的键对应的数值。

补充说明:

u16 line[4] = {0x00fe , 0x00fd , 0x00fb ,0x00f7};
u16 off = 0x00ff; // 全部引脚置为1
u16 keys[16] = {
49, 50, 51, 65,
52, 53, 54, 66,
55, 56, 57, 67,
42, 48, 35, 68,
};

line 定义 了4个16进制的数值分别转成二进制 
0000 0000 1111 1110  0x00fe

0000 0000 1111 1101 0x00fd

0000 0000 1111 1011 0x00fb

0000 0000 1111 0111 0x00f7

低4位为行 高四位为列

设置0就是给对应行设置低电平

这样我们在scan的代码就能看出来 扫描的做法就是先给传入的行line[x] 设置低电平

所有列都是高电平当扫描到某一列为低电平时就说明这一列被点击了。

循环从第一列到第四列设置低电平直到检测到某一列也变成低电平

假设1被点击 则1这一列也是低电平

就变成第一行 第一列低电平

这样就能确定1被点击。给对应参数赋值1即可

再根据定义的keys (askII 码表对应数值 )

主要代码就是上面这些,其他代码只要复制 江科大OLED的课件源码即可

使用方式 man.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Key4x4.h" int main(void)
{ /*模块初始化*/
OLED_Init(); //OLED初始化
KEY_4x4_Init(); /*OLED显示*/
OLED_ShowString(1, 1, "in put:"); //1行1列显示字符A
u8 num = 0;
while (1)
{
KEY_Scan();
num = Key_Read();
OLED_ShowChar(1 ,8 ,num);
}
}

stm32 F103C8T6 4x4矩阵键盘使用的更多相关文章

  1. Win10 IoT C#开发 6 - 4x4矩阵键盘扫描

    Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 上一章我 ...

  2. 4x4矩阵键盘扫描

    4x4矩阵键盘扫描 Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架 ...

  3. 基于FPGA的4x4矩阵键盘驱动调试

    好久不见,因为博主最近两个月有点事情,加上接着考试,考完试也有点事情要处理,最近才稍微闲了一些,这才赶紧记录分享一篇博文.FPGA驱动4x4矩阵键盘.这个其实原理是十分简单,但是由于博主做的时候遇到了 ...

  4. 4X4矩阵键盘扫描程序

    4X4矩阵键盘扫描: 1. 4根行线的GIO均设为Output,根列线的GIO均设为Input: 2. 4根行线的GIO分别置为0111.1011.1101.1110,读逐一读取列线GIO的值,可确定 ...

  5. 「雕爷学编程」Arduino动手做(26)——4X4矩阵键盘模块

    37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...

  6. 4x4矩阵键盘 扫描程序

    一:不排除第四位异常处理 uchar JuzhenkeyScan() { // P3=0xfe; // temp=P3; // while(temp!=0xfe) // { // temp=P3; / ...

  7. MCU软件最佳实践——矩阵键盘驱动

    1.矩阵键盘vs独立按键 在mcu应用开发过程中,独立按键比较常见,但是在需要的按键数比较多时,使用矩阵键盘则可以减少io占用,提高系统资源利用率.例如,某mcu项目要求有16个按钮,如果采用独立按键 ...

  8. 【STM32学习笔记】STM32f407 使用4*4矩阵键盘

    作者:李剀 出处:https://www.cnblogs.com/kevin-nancy/ 欢迎转载,但也请保留上面这段声明.谢谢! 写在前面: 这是本人第一次开始写博客,可能写的不是很好,也请大家谅 ...

  9. STM32 实现 4*4 矩阵键盘扫描(HAL库、标准库 都适用)

    本文实现的代码是基于STM32HAL库的基础上的,不过标准库也可以用,只是调用的库函数不同,逻辑跟配置是一样的,按我这里的逻辑来配置即可. 1.键盘原理图: 原理举例:先把 F0-F7 内部拉高,这样 ...

  10. ARM开发(3)基于STM32的矩阵键盘控制蜂鸣器

    一 矩阵键盘控制蜂鸣器原理:  1.1 本实验实现8*7矩阵键盘上按键控制蜂鸣器响.  1.2 实验思路:根据电路图原理,找出矩阵键盘行列所对应的引脚,赋予对应的按键值,然后控制蜂鸣器响.  1.3 ...

随机推荐

  1. java.sql.SQLException: Connection is read-only. Queries leading to data modification are not

    java.sql.SQLException: Connection is read-only. Queries leading to data modification are not 产生的原因:事 ...

  2. NetMvc通过亚马逊方式服务器端和客户端上传MinIO顺利解决

    前言: 1.由于项目是.NET Framework 4.7 MVC LayUI,所以需要找一个资源站点存放项目中静态资源文件: 2.需要支持服务端和客户端都支持上传文件方式: 3.调用简单,涉及库越少 ...

  3. 算法金 | 一个强大的算法模型:t-SNE !!

    大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 t-SNE(t-Distributed Stochastic Neighbor Emb ...

  4. 如何使用csproj构建C#源代码组件NuGet包?

    一般我们构建传统的NuGet包,都是打包和分发dll程序集文件. 至于打包和分发C#源代码文件的做法,比较少见. 那么这种打包源代码文件的做法,有什么优点和缺点呢? 优点: 方便阅读源代码. 方便断点 ...

  5. 写给rust初学者的教程(二):所有权、生存期

    这系列RUST教程一共三篇.这是第二篇,介绍RUST语言的关键概念,主要是所有权和生存期等. 第一篇:写给rust初学者的教程(一):枚举.特征.实现.模式匹配 在写第一篇中的练习代码时,不知道你有没 ...

  6. BigDecimal加减乘除、比较

    // 加 a+b a.add(b); // 减 a-b a.subtract(b); // 乘 a*b a.multiply(b); // 除 a/b a.divide(b); // 绝对值 a.ab ...

  7. Blazor Server App Cannot find the fallback endpoint specified by route values

    github官方issues中提到的解决方案,CreateBuilder时指定项目绝对路径可以解决. 1 // 指定项目路径,也可以用Assembly.GetCallingAssembly获取 2 c ...

  8. Nginx性能调优5招35式不可不知的策略实战

    Nginx是一个高性能的HTTP和反向代理服务器,它在全球范围内被广泛使用,因其高性能.稳定性.丰富的功能以及低资源消耗而受到青睐.今天V哥从5个方面来介绍 Nginx 性能调优的具体策略,希望对兄弟 ...

  9. yb课堂之用户注册登陆模块《六》

    用户注册功能接口开发 注册接口开发 MD5加密工具类封装 UserMapper.xml <?xml version="1.0" encoding="UTF-8&qu ...

  10. [oeasy]python0097_苹果诞生_史蒂夫_乔布斯_沃兹尼亚克_apple_I

    苹果诞生 回忆上次内容 上次时代华纳公司 凭借手中的影视ip和资本 吞并了雅达利公司 此时 雅达利公司 曾经开发过pong的 优秀员工 乔布斯 还在 印度禅修 寻找自我 看到游戏行业 蓬勃发展 乔布斯 ...