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];
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/948262.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

电子邮件对网络安全的需求

( 1)机密性:传输过程中不被第三方阅读到邮件内容,只有真正的接收方才可以阅读邮件。( 1.5 分) ( 2)完整性:支持在邮件传输过程中不被篡改,若发生篡改&#…

vue路由模式面试题

vue路由模式 1.路由的模式有哪些?有什么区别? history和hash模式 区别: 1.表现的形态不同: 在地址栏url中:hash模式中带有**#**号,history没有 2.请求错误时表现不同: 在hash模式中,对于404地址请求时,不会进行请求 但是在history模式中,对于404请求时,仍然会进行请求…

电子应用设计方案86:智能 AI背景墙系统设计

智能 AI 背景墙系统设计 一、引言 智能 AI 背景墙系统旨在为用户创造一个动态、个性化且具有交互性的空间装饰体验,通过融合先进的技术和创意设计,提升室内环境的美观度和功能性。 二、系统概述 1. 系统目标 - 提供多种主题和风格的背景墙显示效果&…

Python爬虫 - 豆瓣图书数据爬取、处理与存储

文章目录 前言一、使用版本二、需求分析1. 分析要爬取的内容1.1 分析要爬取的单个图书信息1.2 爬取步骤1.2.1 爬取豆瓣图书标签分类页面1.2.2 爬取分类页面1.2.3 爬取单个图书页面 1.3 内容所在的标签定位 2. 数据用途2.1 基础分析2.2 高级分析 3. 应对反爬机制的策略3.1 使用 …

西安电子科技大学初/复试笔试、面试、机试成绩占比

西安电子科技大学初/复试笔试、面试、机试成绩占比 01通信工程学院 02电子工程学院 03计算机科学与技术学院 04机电工程学院 06经济与管理学院 07数学与统计学院 08人文学院 09外国语学院 12生命科学与技术学院 13空间科学与技术学院 14先进材料与纳米科技学院 15网络与信息安…

多模态论文笔记——CogVLM和CogVLM2(副)

大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本文详细介绍多模态模型的LoRA版本——CogVLM和CogVLM2。在SD 3中使用其作为captioner基准模型的原因和优势。 文章目录 CogVLM论文背景VLMs 的任务与挑战现有方法及…

智慧工地信息管理与智能预警平台

建设背景与政策导向 智慧工地信息管理与智能预警平台的出现,源于工地管理面临的诸多挑战,如施工地点分散、危险区域多、监控手段落后等。随着政府对建筑产业现代化的积极推动,各地纷纷出台政策支持智慧工地的发展,旨在通过信息技…

【从零开始入门unity游戏开发之——C#篇42】C#补充知识——随机数(Random)、多种方法实现string字符串拼接、语句的简写

文章目录 一、随机数1、Random.Next()生成随机整数示例:生成一个随机整数生成指定范围内的随机整数 2、Random.NextSingle生成随机浮点数示例:生成随机浮点数 3、 生成随机字母或字符示例:生成随机字母示例:生成随机小写字母 二、…

「Mac畅玩鸿蒙与硬件54」UI互动应用篇31 - 滑动解锁屏幕功能

本篇教程将实现滑动解锁屏幕功能,通过 Slider 组件实现滑动操作,学习事件监听、状态更新和交互逻辑的实现方法。 关键词 滑动解锁UI交互状态管理动态更新事件监听 一、功能说明 滑动解锁屏幕功能包含以下功能: 滑动解锁区域:用…

VScode SSH 错误:Got bad result from install script 解決

之前vscode好好的,某天突然连接报错如下 尝试1. 服务器没有断开,ssh可以正常连接 2. 用管理员权限运行vscode,无效 3. 删除服务器上的~/.vscode-server 文件夹,无效 试过很多后,原来很可能是前一天anaconda卸载导致注册表项 步…

[论文笔记]Representation Learning with Contrastive Predictive Coding

引言 今天带来论文 Representation Learning with Contrastive Predictive Coding的笔记。 提出了一种通用的无监督学习方法从高维数据中提取有用表示,称为对比预测编码(Contrastive Predictive Coding,CPC)。使用了一种概率对比损失, 通过使用负采样使…

【C#深度学习之路】如何使用C#实现Yolo5/8/11全尺寸模型的训练和推理

【C#深度学习之路】如何使用C#实现Yolo5/8/11全尺寸模型的训练和推理 项目背景项目实现调用方法项目展望写在最后项目下载链接 本文为原创文章,若需要转载,请注明出处。 原文地址:https://blog.csdn.net/qq_30270773/article/details/1449186…

如何很快将文件转换成另外一种编码格式?编码?按指定编码格式编译?如何检测文件编码格式?Java .class文件编码和JVM运行期内存编码?

如何很快将文件转换成另外一种编码格式? 利用VS Code右下角的"选择编码"功能,选择"通过编码保存"可以很方便将文件转换成另外一种编码格式。尤其,在测试w/ BOM或w/o BOM, 或者ANSI编码和UTF编码转换,特别方便。VS文件另…

[Python学习日记-74] 面向对象实战2——选课系统

[Python学习日记-74] 面向对象实战2——选课系统 简介 开发要求 实现:选课系统 简介 在前面的《年会答题系统》当中我们介绍了面向对象软件开发的一些流程,当然这一流程只是涵括了大部分的,目前在业界也没有一个统一的标准,每个…

游泳溺水识别数据集,对25729张图片进行YOLO,COCO JSON, VOC XML 格式的标注,溺水平均识别率在89.9%

游泳溺水识别数据集,对25729张图片进行YOLO,COCO JSON, VOC XML 格式的标注,溺水识别率在92% 训练结果 数据集和标签 验证 游泳测试视频 根据测试的视频来获取检测结果: 游泳测试视频的置信度设置60% 检测结果如下&…

性能测试03|JMeter:断言、关联、web脚本录制

目录 一、断言 1、响应断言 2、json断言 3、持续时间断言 二、关联 1、正则表达式介绍 2、正则表达式提取器 3、Xpath提取器 4、JSON提取器 5、JMeter属性 三、web脚本录制 一、断言 定义:让程序自动判断实际的返回结果是否与预期结果保持一致 自动校验…

MetaGPT - 多Agent框架

文章目录 一、关于 MetaGPT功能介绍快速开始的演示视频教程 二、安装Pip安装Docker安装 一、关于 MetaGPT MetaGPT 为GPTs分配不同的角色,以形成一个协作实体来完成复杂的任务。 github : https://github.com/geekan/MetaGPTtwitter : https://twitter.com/MetaGP…

Qt窗口获取Tftpd32_svc服务下载信息

前言 一个由Qt开发的Windows小工具需要布置Tftp协议服务端来支持设备下载数据,并显示下载列表(进度、下载源等)。 考虑开发方便,优先使用了Qtftp方案,经测试发现,不够稳定,会有下载超时的情况&a…

xml格式化(3):增加头部声明

前言 这篇文章&#xff0c;是用来增加头部声明。 正文 from lxml import etreedef pretty_print(element, level0, indent" "):result ""# 判断元素是否为注释节点if isinstance(element, etree._Comment):result f"{indent * level}<!--{el…

python +tkinter绘制彩虹和云朵

python tkinter绘制彩虹和云朵 彩虹&#xff0c;简称虹&#xff0c;是气象中的一种光学现象&#xff0c;当太阳光照射到半空中的水滴&#xff0c;光线被折射及反射&#xff0c;在天空上形成拱形的七彩光谱&#xff0c;由外圈至内圈呈红、橙、黄、绿、蓝、靛、紫七种颜色。事实…