当前位置: 首页 > news >正文

51单片机——按键实验

由于机械点的弹性作用,按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开,因而在闭合和断开的瞬间均伴随着一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms,为了确保 CPU 对按键的一次闭合仅作一次处理,必须进行消抖

普中开发板是采用软件消抖,一般来说一个简单的按键消抖就是先读取按键的状态,如果得到按键按下之后,延时 10ms,再次读取按键的状态,如果按键还是按下状态,那么说明按键已经按下。其中延时10ms 就是软件消抖处理 

1、独立按键实验

P3.1控制K1, P3.0控制K2, P3.2控制K3, P3.3控制K4

软件去抖动方法:

(1)先设置 IO 口为高电平(由于开发板 IO 都有上拉电阻,所以默认 IO 为高电平)

(2)读取 IO 口电平确认是否有按键按下

(3)如有 IO 电平为低电平后,延时几个毫秒

(4)再读取该 IO 电平,如果仍然为低电平,说明按键按下

(5)执行按键控制程序

要实现的功能是:通过开发板上的独立按键K1控制D1指示灯亮灭 

#include "reg51.h"
typedef unsigned int u16;
typedef unsigned char u8;
void delay(u16 time){
    while(time--);
}
//控制D1-D4指示灯
sbit LED1=P2^0;
sbit LED2=P2^1;
sbit LED3=P2^2;
sbit LED4=P2^3;
//使用宏定义的方法定义独立按键的键值
#define KEY1_PRESS 1
#define KEY2_PRESS 2
#define KEY3_PRESS 3
#define KEY4_PRESS 4
#define KEY_UNPRESS 0
//定义按键对应的管脚口
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
//封装一个函数,按键返回一个键值
u8 key_scan(u16 mode){  //mode:模式,有0和1操作,如果操作0,单次扫描;如果操作1,连续扫描
    //打一个标志
    static u16 key=1;
    if(mode==1){
        key=1;
    }
    if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0)){
        //消抖处理,需要延时5ms-10ms
        delay(1000);
        key=0;
        //如果仍是按下,信号稳定
        if(KEY1==0){
            return KEY1_PRESS;
        }else if(KEY2==0){
            return KEY2_PRESS;
        }else if(KEY3==0){
            return KEY3_PRESS;
        }else if(KEY4==0){
            return KEY4_PRESS;
        }
    }else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1){
        key=1;
        return KEY_UNPRESS;
    }
}
void main(){
    u8 key=0;
    while(1){
        key=key_scan(0);
        if(key==KEY1_PRESS){
            LED1=!LED1; 

            delay(1000);  //加一下延时可以验证单次扫描和连续扫描的情况
        }else if(key==KEY2_PRESS){
            LED2=!LED2;
        }else if(key==KEY3_PRESS){
            LED3=!LED3;
        }else if(key==KEY4_PRESS){
            LED4=!LED4;
        }
    }
}

2、矩阵按键实验

 

P1端控制矩阵键盘 

P1.7连接矩阵键盘的第1行,P1.6连接矩阵键盘的第2行,P1.5连接矩阵键盘的第3行,P1.4连接矩阵键盘的第4行

P1.3连接矩阵键盘的第1列,P1.2连接矩阵键盘的第2列,P1.1连接矩阵键盘的第3列,P1.0连接矩阵键盘的第4列

  0          0         0          0          0         0         0         0

--------------------------------------------------------------------------

P1.7    P1.6    P1.5    P1.4    P1.3    P1.2    P1.1    P1.0  

        独立键盘有一端固定为低电平,此种方式编程比较简单。 而矩阵键盘两端都与单片机 I/O 口相连,因此在检测时需编程通过单片机 I/O 口送出低电平

单片机 I/O 口送出低电平检测方法有多种,最常用的是行列扫描和线翻转法:

        (1)行列扫描法:先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的

        (2)线翻转法:就是使所有行线为低电平时,检测所有列线是否有低电平,如果有,就记录列线值;然后再翻转,使所有列线都为低电平,检测所有行线的值,由于有按键按下,行线的值也会有变化,记录行线的值。从而就可以检测到全部按键

 2.1 行列扫描法

行列扫描法:先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的

#include "reg51.h"
typedef unsigned int u16;
typedef unsigned char u8;
void delay(u16 time){
    while(time--);
}
//使用宏定义定义矩阵按键的管脚
#define KEY_MATRIX_PORT P1
//数码管:静态数码管操作
#define SMG_A_DP_PORT P0
//0-F
u16 gmsg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

u16 key_matrix_scan(){
    //定义一个变量返回
    u16 key_value=0;
    //给第一列赋值0,其余全为1
    KEY_MATRIX_PORT=0xf7;
    if(KEY_MATRIX_PORT!=0xf7){
        //消抖
        delay(1000);
        //检测行
        switch(KEY_MATRIX_PORT){
            case 0x77:
                key_value=1;
                break;
            case 0xb7:
                key_value=5;
                break;
            case 0xd7:
                key_value=9;
                break;
            case 0xe7:
                key_value=13;
                break;
        }
    }
    //等待按键松开
    while(KEY_MATRIX_PORT!=0xf7);
    
    
    //给第二列赋值0,其余全为1
    KEY_MATRIX_PORT=0xfb;
    if(KEY_MATRIX_PORT!=0xfb){
        //消抖
        delay(1000);
        //检测行
        switch(KEY_MATRIX_PORT){
            case 0x7b:
                key_value=2;
                break;
            case 0xbb:
                key_value=6;
                break;
            case 0xdb:
                key_value=10;
                break;
            case 0xeb:
                key_value=14;
                break;
        }
    }
    //等待按键松开
    while(KEY_MATRIX_PORT!=0xfb);
    
    
    //给第三列赋值0,其余全为1
    KEY_MATRIX_PORT=0xfd;
    if(KEY_MATRIX_PORT!=0xfd){
        //消抖
        delay(1000);
        //检测行
        switch(KEY_MATRIX_PORT){
            case 0x7d:
                key_value=3;
                break;
            case 0xbd:
                key_value=7;
                break;
            case 0xdd:
                key_value=11;
                break;
            case 0xed:
                key_value=15;
                break;
        }
    }
    //等待按键松开
    while(KEY_MATRIX_PORT!=0xfd);
    
    
    //给第四列赋值0,其余全为1
    KEY_MATRIX_PORT=0xfe;
    if(KEY_MATRIX_PORT!=0xfe){
        //消抖
        delay(1000);
        //检测行
        switch(KEY_MATRIX_PORT){
            case 0x7e:
                key_value=4;
                break;
            case 0xbe:
                key_value=8;
                break;
            case 0xde:
                key_value=12;
                break;
            case 0xee:
                key_value=16;
                break;
        }
    }
    //等待按键松开
    while(KEY_MATRIX_PORT!=0xfe);
    
    //返回值
    return key_value;
}

void main(){
    u16 key=0;
    while(1){
        key=key_matrix_scan();
        if(key!=0){
            SMG_A_DP_PORT=gmsg_code[key-1];
        }
    }
}

2.2 线翻转法

线翻转法,就是使所有行线为低电平时,检测所有列线是否有低电平,如果有,就记录列线值;然后再翻转,使所有列线都为低电平,检测所有行线的值,由于有按键按下,行线的值也会有变化,记录行线的值。从而就可以检测到全部按键 

 #include "reg51.h"
typedef unsigned int u16;
typedef unsigned char u8;
void delay(u16 time){
    while(time--);
}
//使用宏定义定义矩阵按键的管脚
#define KEY_MATRIX_PORT P1
//数码管:静态数码管操作
#define SMG_A_DP_PORT P0
//0-F
u16 gmsg_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

u16 key_matrix_flip_scan(){
    u16 key_value=0;
    //使所有行线为低电平,列线为高电平
    KEY_MATRIX_PORT=0x0f;
    if(KEY_MATRIX_PORT!=0x0f){
        //消抖
        delay(1000);
        if(KEY_MATRIX_PORT!=0x0f){
            //测试列,使所有行线为低电平,列线为高电平
            KEY_MATRIX_PORT=0x0f;
            switch(KEY_MATRIX_PORT){
                case 0x07:
                    key_value=1;  //暂时赋一个值
                    break;
                case 0x0b:
                    key_value=2;
                    break;
                case 0x0d:
                    key_value=3;
                    break;
                case 0x0e:
                    key_value=4;
                    break;
            }
            //测试行,使所有列线为低电平,行线为高电平
            KEY_MATRIX_PORT=0xf0;
            switch(KEY_MATRIX_PORT){
                case 0x70:
                    key_value=key_value;
                    break;
                case 0xb0:
                    key_value=key_value+4;
                    break;
                case 0xd0:
                    key_value=key_value+8;
                    break;
                case 0xe0:
                    key_value=key_value+12;
                    break;
            }
            while(KEY_MATRIX_PORT!=0xf0);
        }else{
            key_value=0;
        }
        return key_value;
    }
}

void main(){
    u16 key=0;
    while(1){
        key=key_matrix_flip_scan();
        if(key!=0){
            SMG_A_DP_PORT=gmsg_code[key-1];
        }
    }
}

相关文章:

51单片机——按键实验

由于机械点的弹性作用,按键开关在闭合时不会马上稳定的接通,在断开时也不会一下子断开,因而在闭合和断开的瞬间均伴随着一连串的抖动。抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms,为了确保 CPU 对按键的…...

QT c++ 自定义按钮类 加载图片 美化按钮

如果你有需要利用图片美化按钮的情况&#xff0c;本文能帮助你。 鼠标左键按下按钮和松开&#xff0c;按钮显示不同的图片。 1.按钮类 //因为此类比较简单&#xff0c;1个头文件搞定&#xff0c;没有cpp文件 #ifndef CUSTOMBUTTON_H #define CUSTOMBUTTON_H #include <Q…...

Django:构建高效Web应用的强大框架

在当今快速发展的Web开发领域&#xff0c;选择一个合适的框架对于项目的成功至关重要。Django&#xff0c;作为Python编程语言中最受欢迎的Web框架之一&#xff0c;凭借其强大的功能、高度的可扩展性和简洁的语法&#xff0c;成为了众多开发者心中的首选。本文将深入探讨Django…...

代码随想录算法【Day11】

150. 逆波兰表达式求值 class Solution { public:int evalRPN(vector<string>& tokens) {// 力扣修改了后台测试数据&#xff0c;需要用longlongstack<long long> st; for (int i 0; i < tokens.size(); i) {if (tokens[i] "" || tokens[i] &…...

[SeaTunnel] [MySql CDC] Generate Splits for table db.table error

在使用 SeaTunnel 的 MySQL CDC 时报错&#xff1a; Caused by: org.apache.seatunnel.engine.common.exception.SeaTunnelEngineException: java.lang.RuntimeException: Generate Splits for table db.table error SeaTunnel 版本为 2.3.8 在 GitHub 上找到一种解决方法&am…...

Spring Boot | 基于MinIO实现文件上传和下载

关注&#xff1a;CodingTechWork 介绍 在现代的 web 应用中&#xff0c;文件上传和下载是常见的需求。MinIO 是一个开源的高性能分布式对象存储服务&#xff0c;可以用来存储和管理大量的非结构化数据&#xff0c;如图片、视频、日志文件等。本文将介绍如何在 Spring Boot 应用…...

企业手机号搜索API接口

每日免费每次消耗&#xff1a;按量每日限制&#xff1a;10 次每次请求积分消耗&#xff1a;50 积分 / 次总次数限制&#xff1a;10000 次每次请求间隔&#xff1a;0 秒&#xff0c;并发&#xff1a;50 请求地址 http(s)://api.aiqimao.com/index/apiphoneget/ 调试 请求方法…...

VirtualBox Main API 学习笔记

1. Philosophy 1.1 对于Python&#xff0c;推荐使用"WEBSERVICE"连接方式 Gemini 2.0 Flash Experimental: 对于 Java 和 Python&#xff1a; 文档建议您首先使用"WEBSERVICE"&#xff0c;因为它提供了一种更直观的方式来使用 API。 2. Configuration pi…...

[Linux]Mysql9.0.1服务端脱机安装配置教程(redhat)

前言 本教程适用于在yum源不可用的LInux主机上安装Mysql的场景。 以redhat系主机做操作示例&#xff0c;debian系主机可参照步骤&#xff0c;将对应的rpm -ivh命令换成dpkg -i。 1. 官网下载安装包 https://dev.mysql.com/downloads/mysql/ 1.1 版本分类 MySQL Enterprise…...

uniapp--HBuilder开发

提示&#xff1a;本文为学习内容&#xff0c;若有错误&#xff0c;请联系作者&#xff0c;谦虚受教。 文章目录 前言一、下载HBuilder二、添加modbus相关库1.下载nodejs2.下载modbus库3.项目添加modbus库 三、HBuilder相关功能语句1.文件夹说明2.消息信息框3.开关按钮4.选中按钮…...

计算机毕业设计学习项目-P10080 基于springboot+vue的社团管理系统的设计与实现

项目说明 本号所发布的项目均由我部署运行验证&#xff0c;可保证项目系统正常运行&#xff0c;以及提供完整源码。 如需要远程部署/定制/讲解系统&#xff0c;可以联系我。定制项目未经同意不会上传&#xff01; 项目源码获取方式放在文章末尾处 注&#xff1a;项目仅供学…...

with as提高sql的执行效率

实战sql with cte(UNIT_ID, UNIT_NAME, PARENT_UNIT_ID, UNIT_CODE ) as (select UNIT_ID, UNIT_NAME, PARENT_UNIT_ID , UNIT_CODEfrom HPFM_UNITunion allselect t.UNIT_ID, t.UNIT_NAME, t.PARENT_UNIT_ID, t.UNIT_CODEfrom HPFM_UNIT tjoin cte on t.PARENT_UNIT_ID cte.U…...

【银河麒麟高级服务器操作系统实例】tcp半链接数溢出分析及处理全过程

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://document.kylinos.cn 服务器环境以及配置 系统环境 物理机/虚拟机/云…...

计算机毕业设计Python中华古诗词知识图谱可视化 古诗词智能问答系统 古诗词数据分析 古诗词情感分析模型 自然语言处理NLP 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

分布式ID生成-雪花算法实现无状态

雪花算法这里不再赘述&#xff0c;其缺点是有状态&#xff08;多副本隔离时&#xff0c;依赖手动配置workId和datacenterId&#xff09;&#xff0c;代码如下&#xff1a; /*** 雪花算法ID生成器*/ public class SnowflakeIdWorker {/*** 开始时间截 (2017-01-01)*/private st…...

【问题】配置 Conda 与 Pip 源

通常情况下,使用 conda 命令或者 pip 命令都是从国外的服务器上下载需要的模块包的,这在网速不佳的情况下会消耗大量的时间。所以这里建议更换国内的源来进行模块下载,速度会大大提升。 具体方法如下: 打开命令行 cmd 工具,输入以下命令。 ① Conda 换源 conda config…...

Zookeeper是如何保证事务的顺序一致性的?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper是如何保证事务的顺序一致性的?】面试题。希望对大家有帮助&#xff1b; Zookeeper是如何保证事务的顺序一致性的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper 通过多个机制来保证事务的顺序一…...

东土科技参股广汽集团飞行汽车初创公司,为低空经济构建新型产业生态

近日&#xff0c;广汽集团旗下专注于飞行汽车领域的初创公司广东高域科技有限公司于2024年12月31日正式成立&#xff0c;在穿透后的股东信息中&#xff0c;东土科技通过广州瓴云科技投资合伙企业&#xff08;有限合伙&#xff09;赫然在列。 此前12月18日&#xff0c;广汽集团…...

Oracle 中的各种名称(*_name)参数的含义与作用

Oracle 中的各种名称&#xff08;*_name&#xff09;参数的含义与作用 目录 Oracle 中的各种名称&#xff08;*_name&#xff09;参数的含义与作用一、数据库名&#xff1a;db_name二、数据库所在的域&#xff1a;db_domain三、全局数据库名&#xff1a;global_name四、服务名&…...

前端页面的内容格式

TaskBuilder可以编辑的前端页面类型分为HTML和tfp&#xff08;Taskmsg Front Page&#xff09;两种格式&#xff0c;HTML格式只能用代码编辑器编辑&#xff0c;这种模式基本很少有人用&#xff0c;大家都用tfp格式&#xff0c;因为使用TaskBuilder向导创建的前端页面都是采用的…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

回溯算法学习

一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

PydanticAI快速入门示例

参考链接&#xff1a;https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...