stm32 F103C8T6 4x4矩阵键盘使用
首先感谢 江科大 的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矩阵键盘使用的更多相关文章
- Win10 IoT C#开发 6 - 4x4矩阵键盘扫描
Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架构上运行. 上一章我 ...
- 4x4矩阵键盘扫描
4x4矩阵键盘扫描 Windows 10 IoT Core 是微软针对物联网市场的一个重要产品,与以往的Windows版本不同,是为物联网设备专门设计的,硬件也不仅仅限于x86架构,同时可以在ARM架 ...
- 基于FPGA的4x4矩阵键盘驱动调试
好久不见,因为博主最近两个月有点事情,加上接着考试,考完试也有点事情要处理,最近才稍微闲了一些,这才赶紧记录分享一篇博文.FPGA驱动4x4矩阵键盘.这个其实原理是十分简单,但是由于博主做的时候遇到了 ...
- 4X4矩阵键盘扫描程序
4X4矩阵键盘扫描: 1. 4根行线的GIO均设为Output,根列线的GIO均设为Input: 2. 4根行线的GIO分别置为0111.1011.1101.1110,读逐一读取列线GIO的值,可确定 ...
- 「雕爷学编程」Arduino动手做(26)——4X4矩阵键盘模块
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器和模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里 ...
- 4x4矩阵键盘 扫描程序
一:不排除第四位异常处理 uchar JuzhenkeyScan() { // P3=0xfe; // temp=P3; // while(temp!=0xfe) // { // temp=P3; / ...
- MCU软件最佳实践——矩阵键盘驱动
1.矩阵键盘vs独立按键 在mcu应用开发过程中,独立按键比较常见,但是在需要的按键数比较多时,使用矩阵键盘则可以减少io占用,提高系统资源利用率.例如,某mcu项目要求有16个按钮,如果采用独立按键 ...
- 【STM32学习笔记】STM32f407 使用4*4矩阵键盘
作者:李剀 出处:https://www.cnblogs.com/kevin-nancy/ 欢迎转载,但也请保留上面这段声明.谢谢! 写在前面: 这是本人第一次开始写博客,可能写的不是很好,也请大家谅 ...
- STM32 实现 4*4 矩阵键盘扫描(HAL库、标准库 都适用)
本文实现的代码是基于STM32HAL库的基础上的,不过标准库也可以用,只是调用的库函数不同,逻辑跟配置是一样的,按我这里的逻辑来配置即可. 1.键盘原理图: 原理举例:先把 F0-F7 内部拉高,这样 ...
- ARM开发(3)基于STM32的矩阵键盘控制蜂鸣器
一 矩阵键盘控制蜂鸣器原理: 1.1 本实验实现8*7矩阵键盘上按键控制蜂鸣器响. 1.2 实验思路:根据电路图原理,找出矩阵键盘行列所对应的引脚,赋予对应的按键值,然后控制蜂鸣器响. 1.3 ...
随机推荐
- Apollo config配置中心 配置列表和map DEMO
Apollo config配置中心 配置列表和map DEMO#支持可扩展 Apollo配置 apollo中配置如下: defaultId = 100,200 chooseId = {"30 ...
- 幻想领域图床系统V1.2正式版发布
Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 幻想领域图床系统V1.2正式版发布 日期:2018-4-1 ...
- Sqlite windows11 安装与使用
首先进入Sqlite官方网址: https://www.sqlite.org/download.html 然后下载下面框起来的两个压缩文件 下载完成后解压 接下来去配置环境变量,右键此电脑->属 ...
- kylin的除法函数的坑
1.select 1/6 (整数相除除不过直接就为0) 解决办法:select cast(1 as double)/6 2.select round (0/6,2) (0除以任何数都是0,无法 ...
- 推荐一款基于业务行为驱动开发(BDD)测试框架:Cucumber!
大家好,我是狂师. 今天给大家介绍一款行为驱动开发测试框架:Cucumber. 1.介绍 Cucumber是一个行为驱动开发(BDD)工具,它结合了文本描述和自动化测试脚本.它使用一种名为Gherki ...
- python提取特定格式的数据
Excel Grid Data Converter 知识点总结 本文档总结了 ExcelGridConverter.py 脚本所涉及的关键 Python 知识点.该脚本用于从多个 Excel 文件中提 ...
- 关于tomcat中servlet的url-pattern匹配规则
首先需要明确几点容易混淆的规则: servlet容器中的匹配规则既不是简单的通配,也不是正则表达式,而是特定的规则.所以不要用通配符或者正则表达式的匹配规则来看待servlet的url-pattern ...
- 【ClickHouse】5:clickhouse集群部署
背景介绍: 有三台CentOS7服务器安装了ClickHouse HostName IP 安装程序 程序端口 centf8118.sharding1.db 192.168.81.18 clickhou ...
- 使用Nginx在80端口上代理多个.NET CORE网站
有两个.NET CORE3.1网站部署在CentOS7上(内网IP是192.168.2.32),现在想实现访问http://192.168.2.32时访问A网站,访问http://192.168.2. ...
- 面试官:Dubbo一次RPC请求经历哪些环节?
大家好,我是三友~~ 今天继续探秘系列,扒一扒一次RPC请求在Dubbo中经历的核心流程. 本文是基于Dubbo3.x版本进行讲解 一个简单的Demo 这里还是老样子,为了保证文章的完整性和连贯性,方 ...