蓝桥杯——单片机学习(5(1)——按键(独立按键))

2023-05-16

注:此单片机型号为 STC15F2K60S2.

目录标题

  • 独立按键
    • 原理
      • 按键原理
      • 消抖
    • 代码
      • 入门代码
      • 进阶代码
      • 消抖改进(按一下只执行一次,长按也一样)
    • 补充

独立按键

原理

来源:我自己:)
这是一个矩阵按键的电路图,要使得其进入独立按键模式,就要把跳线帽连接2、3.
来源:我自己:)
(注:跳线帽是外部可移动的元件。)

此时,即为独立按键模式。
来源:我自己:)

按键原理

以 S7 按键为例,其左端连接接地,右端连接 P30,由于一开始所有 P 口都默认为高电平,则只要检测到 P30 为低电平,则说明按键 S7 被按下。

消抖

在这里插入图片描述

当按键被按下的时候,电路导通接地,I/O口为低电平;
当按键未被按下时,电路断开,I/O口保持高电平。

但一般的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,假如不加以处理,会导致按键被识别为按下多次。为了不产生这种现象而作的措施就是按键消抖。

消抖有硬件消抖和软件消抖两种方法,但我们不可能去更换硬件,所以主要采用软件消抖 —— 写一个延迟 5ms 左右的函数。

参考资料:@我要糖 —— 单片机之按键消抖

代码

入门代码

//key.c

/**************************************************************************** 
* Copyright (C), 2022,Moqim
* 文件名: main.c 
* 内容简述:检测独立按键被按下的键值 
* 
* 文件历史: 
* 版本号      日期       作者     说明 
*   01a    2022-05-18   Moqim   创建该文件
*/

#include "key.h"

//为方便使用,重新定义管脚名
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

/**************************************************************************** 
* 函数名: Key_Scan() 
* 功 能: 按键检测
* 输 入: 无        
* 输 出: unsigned char类型的数值,表示键值
*/
unsigned char Key_Scan(void)
{
	if (S4 == 0)
	{
		Key_Delay(10);
		if (S4 == 0)
			return 4;
	}
	
	else if (S5 == 0)
	{
		Key_Delay(10);
		if (S5 == 0)
			return 5;
	}
	
	else if (S6 == 0)
	{
		Key_Delay(10);
		if (S6 == 0)
			return 6;
	}
	
	else if (S7 == 0)
	{
		Key_Delay(10);
		if (S7 == 0)
			return 7;
	}
	
	return 0;
}

/**************************************************************************** 
* 函数名: Key_Delay() 
* 功 能: 延时
* 输 入: unsigned int num:延时num毫秒        
* 输 出: 无 
*/
void Key_Delay(unsigned int num)
{
	int i, j;
	for (i = 0; i<num; i++)
	  for(j = 0; j<625; j++);
}

//key.h

#ifndef __KEY_H
#define __KEY_H

#include "stc15f2k60s2.h"

unsigned char Key_Scan(void);
void Key_Delay(unsigned int num);

#endif /*__KEY_H*/

//main.c

/**************************************************************************** 
* Copyright (C), 2022,Moqim
* 文件名: main.c 
* 内容简述:实现LED和SEG显示按键对应数值 
* 
* 文件历史: 
* 版本号      日期       作者     说明 
*   01a    2022-05-18   Moqim   创建该文件
*/

//头文件调用区
#include "stc15f2k60s2.h"
#include "led.h"
#include "seg.h"
#include "key.h"

//变量定义区


//函数声明区
void Delay_ms(unsigned int num);
void Key_Disp(void);

//Main Body
int main(void)
{
	LED_Init();                      //关闭LED
	SEG_Init();                      //关闭数码管
	
	while (1)
	{
		Key_Disp();                    //执行按键函数
	}
	
}

/**************************************************************************** 
* 函数名: Key_Disp() 
* 功 能: 按下按键,LED和SEG显示对应数值
* 输 入: 无       
* 输 出: 无 
*/
void Key_Disp(void)
{
	static unsigned char Key_Val = 0;           //定义无符号字符型的静态变量,表示当前键值
	static int i = 0;                                  //一个用于调用LED和SEG的参数
	
	Key_Val = Key_Scan();                       //获取当前键值
	
	switch (Key_Val)                            //判断键值,执行内容
	{
		case 4:i = 4;break;
		case 5:i = 5;break;
		case 6:i = 6;break;
		case 7:i = 7;break;
		default:i = 0;break;
	}
	
	if (i > 0)                     
	{
		LED_Ctrl(0x01 << i - 1);                  //点亮对应序号的LED
		smg1 = i;                                 //数码管显示对应键值
	}
	else
	{
		LED_Ctrl(0x00);                          //LED全灭
		smg1 = 0;                                //数码管显示0
	}
	SEG_Scan();                                //数码管显示
	Delay_ms(200);                             //增加显示时间
}

/**************************************************************************** 
* 函数名: Delay_ms() 
* 功 能: 延时
* 输 入: unsigned int num:延时num毫秒        
* 输 出: 无 
*/
void Delay_ms(unsigned int num)              //软件延时不精确,凑合用吧
{
	int i, j;
	for(i = 0; i<num; i++)
	{
		for(j = 0; j<625; j++);
	}
}

LED 和 SEG 代码请参考之前博客。

进阶代码

void key_press(int* p)   //设定一个变量,可返回至数码管以检查代码是否正确执行;
{                     
	if (P30 == 0) {      //当检测到P30为低电平时;
		delay(5);        //消抖;
		if (P30 == 0)    //若仍为低电平,说明按键被按下;
			(*p)++;      //执行需要的程序;
		while (P30 == 0);//一直执行程序,直到P30!=0,即按键被松开;
	}
}

但上述代码有一个缺点,即长按按键会一直执行程序,
所以,改进代码如下——

void key_press(int* p)                //设定一个变量,可返回至数码管以检查代码是否正确执行;
{   
	bit S7 = 0;                       //设定一个位标量,令其为0;
	if ((P30 == 0)&&(S7 == 0)) {      //当检测到P30为低电平且S7为0时;
		delay(5);                     //消抖
		if ((P30 == 0) && (S7 == 0))  //若仍为低电平且S7为0,说明按键被按下;
			S7 = 1;                   //令S7为1;
	}

	if ((P30 == 1) && (S7 == 1)) {    //当检测到P30为高电平且S7为1时,说明已被按下过,且现在处于抬起状态;
		(*p)++;                       //执行需要的程序;
		S7 = 0;                       //复位S7;
	}
}

这样,每次按完一次才会执行一次,长按则不会影响。

参考资料:bilibili@一蓑烟雨任平生 a—— 基于蓝桥杯单片机的 STC15 学习教程。

消抖改进(按一下只执行一次,长按也一样)

来源:上课认真听讲。

//前提条件:按下一个键(S4为例),该变量读到的是4(已经通过key_read()函数获取按键数值了)
//按下为4,抬起为0

//way 1,设置一个参考变量
u8 flag = 0;
if(key_read == 4 && flag == 0){//读取S4
  flag = 1;
  //按键按一下执行的代码
}
if(flag == 1 && key_read() != 4){
  flag = 0;
}

//way 2
//比较当前值和前一次值,

u8 last_key_value = 0;//上一次的值
u8 current_key_value = key_read();//当前值

if(current_key_value > last_key_value && current_key_value == 4){//如果当前值大于上一次的值,且当前值为4
   //执行语句
}
last_key_value = current_key_value;//把当前值赋给上一次的值


//way 3
//用异或

u8 key_val = 0;//结果值
u8 last_key_value = 0;//上一次的值
u8 current_key_value = 0;//当前值

current_key_value = key_read();//当前值赋值
key_val = current_key_value ^ last_key_value  & current_key_value;
//异或完后(相异为1),若按下(当前值为4),与上当前值后不变;若抬起(当前值为0),与上后为0;
//若长按,则异或结果为0,0与上任何数都是0;
last_key_value = current_key_value;

switch(key_val){
   case 4:if(++ work_state == 4)work_state = 1;break;
   case 5:
   case 6:
   case 7:
}

补充

2022.04.04
我现在常用的:

void Key_Proc(void){
  static unsigned char ucKey_Val = 0;
  static unsigned char ucKey_Down = 0;  
  static unsigned char ucKey_Old = 0;

  ucKey_Val = Key_Scan();//从按键判断函数中获取键值
  ucKey_Down = ucKey_Val & (ucKey_Val ^ ucKey_Old);//当前键值与上一次键值异或,若相同则为0,则ucKey_Down为0;相异则反之。
  ucKey_Old = ucKey_Val;
    
  switch(ucKey_Down){//短按用ucKey_Down,长按用ucKey_Old
      case 4:break;
      default:break;   
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

蓝桥杯——单片机学习(5(1)——按键(独立按键)) 的相关文章

  • linux持久化

    linux持久化后门 添加超级用户SUID shellalias 后门inetdcrontab后门ssh公钥免密ssh软连接SSH wrapper后门PAM隐身登录隐藏文件Git hooksPROMPT COMMAND后门PROMPT CO
  • linux恶意进程隐藏

    https mp weixin qq com s 6Z4tErcnusYHTqiSUSVz3A https blog csdn net nzjdsds article details 82919100
  • 图图图图图

  • windows提权总结

    windows提权总结 内核溢出提权Windows系统配置错误提权系统服务权限配置错误注册表键AlwaysInstallElevated可信任服务路径漏洞自动安装配置文件计划任务 Windows组策略首选项提权 SYSVOL GPP SYS
  • 运行Intel realsense L515相机

    运行Intel realsense L515相机 首先去官 https www intelrealsense com sdk 2 xff0c 按照上面的提示安装各种文件 xff0c 然后输入realsense viewer出现可视化窗口 下
  • python的shellcode_loader解释

    python的shellcode loader解释 代码 loader传到主机执行 xff0c shellcode传到自己的服务器上 简单的python shellcode加载器 xff0c 直接上代码 xff0c 注释都在代码里 代码 s
  • 「网络工程师必会技能」-路由器介绍和路由器基本配置

    网络工程师必会技能 路由器介绍和路由器基本配置 xff0c 这是每个网络必须会的技能 xff0c 不是你有证书就一个网络工程师了哦 xff01 以Cisco路由器为例说明 xff1a xff08 1 xff09 访问路由器 访问路由器与访问
  • 英飞凌微控制器,驱动物联网的关键“大脑”

    英飞凌微控制器 xff0c 驱动物联网的关键 大脑 英飞凌各种各样的传感器以及基于它们的创新应用 xff0c 可谓是打开了传感器的 兵器库 xff0c 令人大开眼界 今天 xff0c 我们将进入 计算 这一环节 xff0c 看看唯样商城代理
  • EMC对策产品:TDK扩大了内置ESD保护功能的陷波滤波器阵容

    EMC对策产品 xff1a TDK扩大了内置ESD保护功能的陷波滤波器阵容 新的陷波滤波器同时实现了ESD保护和最大频率为5 3 GHz频段噪声抑制抑制无线通信中产生的TDMA噪声 xff0c 提高无线信号接收灵敏度强大的静电保护能力 xf
  • 这27个电源符号,别再分不清 快收藏起来学习

    这27个电源符号 xff0c 别再分不清 xff01 快收藏起来学习 以下的V代表Volatge的意思 电源符号 解析 VCC C可以理解为三极管的集电极Collector或者电路Circuit xff0c 指电源正极 VDD D可以理解为
  • 74ls160引脚图引脚图和功能真值表

    74ls160引脚图管脚图及功能真值表 xff0c 74ls160引脚图管脚图74LS160的功能真值表 综合电路图 74ls160引脚图管脚图 74LS160的功能真值表 唯样商城是本土元器件目录分销商 xff0c 采用 小批量 现货 样
  • 最全74HC04六反相器中文资料|引脚图及功能表|应用电路图

    最全74HC04六反相器中文资料 引脚图及功能表 应用电路图 最全74HC04六反相器中文资料 引脚图及功能表 应用电路图 xff0c 该74HC04 74HCT04是高速CMOS器件 xff0c 低功耗肖特基的TTL LSTTL 电路 功
  • 房卡一插就有电 酒店插卡取电原理解析

    房卡一插就有电 酒店插卡取电原理解析 酒店插卡取电的原理是什么 xff0c 入住酒店只需用房卡一插就有电 xff0c 原理是什么呢 xff1f 只是一张塑料片不能导电的啊 导读 xff1a 酒店插卡取电的原理是什么 xff0c 入住酒店只需
  • SiC MOSFET驱动电压的分析及探讨

    SiC设计干货分享 xff08 一 xff09 xff1a SiC MOSFET驱动电压的分析及探讨 随着制备技术的进步 xff0c 在需求的不断拉动下 xff0c 碳化硅 xff08 SiC xff09 器件与模块的成本逐年降低 相关产品
  • EM-500储能网关的AI采集性能实测

    EM 500储能网关的AI采集性能实测 EM 500是致远电子面向工商储能应用推出的高性价比储能网关产品 为满足采集外部传感器数据需要 xff0c EM 500设计内置了多通道高性能AI采集接口 xff0c 本文将对其进行一次实测 EM 5
  • 【IoT开发】UART通信高频测试

    测试所使用芯片 STM32F103RCT6 UART收发的极限频率 xff1a bytes s 1 发送频率 主程序循环发送一字节u8整型 xff0c 记录次数 while 1 t 43 43 if t 61 61 255 t 61 0 p
  • 560V输入、无光隔离反激式转换器

    560V输入 无光隔离反激式转换器 在传统的隔离式高压反激式转换器中 xff0c 使用光耦合器将稳压信息从副边基准电压源电路传输到初级侧 xff0c 从而实现严格的稳压 问题在于 xff0c 光耦合器大大增加了隔离设计的复杂性 xff1a
  • 用于DC-DC转换器的MIL-SPEC COTS EMC输入滤波器

    用于DC DC转换器的MIL SPEC COTS EMC输入滤波器 DC DC转换器的开关动作可能会引起不良的共模和差模噪声 xff0c 在频谱的许多点上创建不可接受的干扰 前端 xff08 或电力线 xff09 滤波器旨在在DC DC转换
  • C语言中调用nop();解决办法

    C语言中调用 nop 解决办法 可在头文件中添加 include lt intrins h gt 或是直接删去 nop intrins h一般用在keilC51单片机编程中 xff0c 一般程序中需要使用到空指令 nop 字符循环移位指令
  • rosrun teleop_twist_keyboard teleop_twist_keyboard.py

    rospack Error package teleop twist keyboard not found 解决方案 xff1a 1 cd catkin ws src xff08 如果没有这个目录先在工作目录下创建工作空间 xff1a mk

随机推荐

  • ubuntu20.04安装ros配置秘钥时出现gpg: keyserver receive failed: Connection timed out

    gpg keyserver receive failed Connection timed out也是从公钥服务器接收失败 xff1a 连接超时 解决方案1 换自己的手机热点 解决方案2 切换网络配置 xff1a 这大多数是网络的问题 xf
  • rosbag的命令使用以及代码编写

    概念 xff1a rosbag是用于录制和回放 ROS 主题的一个工具集 作用 实现了数据的复用 xff0c 方便调试 测试 本质 xff1a rosbag本质也是ros的节点 xff0c 当录制时 xff0c rosbag是一个订阅节点
  • 格式化串漏洞

    格式化字符串漏洞本身并不算缓冲区溢出漏洞 xff0c 这里作为比较典型的一类漏洞进行简单介绍 为了能够将字符串 变量 地址等数据按照指定格式输出 xff0c 通常使用包含格式化控制符的常量字符串作为格式化串 xff0c 然后指定用相应变量来
  • 单链表的遍历

    1 什么是遍历 遍历就是把单链表的各个节点挨个拿出来 xff0c 一个不能少 xff0c 也不能重复 xff0c 追求效率 2 如何遍历单链表 xff08 1 xff09 分析数据结构的本身特点 xff0c 然后根据根据它本身的特点制定相应
  • 单链表之删除节点

    1 删除节点的步骤 xff08 1 xff09 找到要删除的这个节点 xff1a 通过遍历来查找节点 xff0c 从头指针 43 头节点开始 xff0c 顺着链表依次将各个节点拿出来 xff0c 按照一定的方法比对 xff0c 找到我们要删
  • lssek函数的用法及作用

    1 lseek函数的介绍 xff08 1 xff09 文件指针 xff1a 当我们对一个文件读写时 xff0c 一定需要打开这个文件 xff0c 所以我们操作的都是动态文件 xff0c 动态文件在内存中的形态就是流的形式 xff08 2 x
  • ubuntu20.04安装arduino IDE(亲测可用)

    步骤一 xff1a 在官网下载arduino安装包选择相应的版本 下载链接 步骤二 xff1a 解压下载的安装包在相应的目录下执行下面语句 tar xvf 安装包名 步骤三 xff1a 将解压后的安装包移动到 opt目录下 sudo mv
  • px4无人机常识介绍(固件,px4等)

    专业名词解释 aircraft 任何可以飞或者可以携带物品还是搭载旅客的飞行器统称为飞机 航空器 uav 无人驾驶飞机 vehicle 飞行器 airplane plane aero plane 有机翼和一个或多个引擎的飞行器统称为飞机 D
  • 在运行ros的Python文件时报找不到路径

    1 第一行解释器声明 xff0c 可以使用绝对路径定位到 python3 的安装路径 usr bin python3 xff0c 但是不建议 2 建议使用 usr bin env python 但是会抛出异常 usr bin env pyt
  • ros文件架构

    WorkSpace span class token operator span span class token operator span 自定义的工作空间 span class token operator span span cla
  • 用C语言和汇编给寄存器赋值

    1 用汇编 要根据目标CPU的体系 xff0c 用对应的汇编类型编写 ldr r0 61 0X020C4068 CCGR0 ldr r1 61 0XFFFFFFFF str r1 r0 2 用C语言 要知道相关寄存器地址 官方会提供参考手册
  • 商人过河--广度优先搜索--matlab实现

    进行了代码优化 目录 应用背景 xff1a 模型求解 xff1a 模型建立 xff1a 模型实现 xff1a 源代码 xff1a 运行结果 xff1a 附 xff1a 应用背景 xff1a M个商人与N个仆从过河 xff0c 小船一次可载k
  • C++---全局对象、局部对象、静态对象

    1 全局对象 xff0c 程序一开始 xff0c 其构造函数就先被执行 xff08 比程序进入点更早 xff09 xff1b 程序即将结束前其析构函数将被执行 2 局部对象 xff0c 当对象生成时 xff0c 其构造函数被执行 xff1b
  • 2011年B题交通巡警第一问的练习与实现

    题目要求 xff1a 试就某市设置交巡警服务平台的相关情况 xff0c 建立数学模型分析研究下面的问题 xff1a xff08 1 xff09 附件1中的附图1给出了该市中心城区A的交通网络和现有的20个交巡警服务平台的设置情况示意图 xf
  • 利用最大流最小割算法matlab割图

    目录 练习思路 matlab绘图 噪音 坐标编码 邻接矩阵 最大流最小割算法 对最大流最小割算法求解结果转换为图像 源代码 运行实例 TIPS 最近学习了最大流和最小割算法 xff0c 可以把图看成是一些点的集合 xff0c 色彩差值的倒数
  • 关于将一个数分解成四个数平方和的算法matlab

    目录 理论基础 拉格朗日四平方数和定理 高斯恒等式 操作步骤 分解质因数 求解四平方数 应用高斯恒等式 小结 高斯恒等式输出代码 输出结果 运行结果 怎么把一个大数分解成四个小数的平方和呢 xff1f 理论基础 拉格朗日四平方数和定理 每个
  • 寻找较大素数,简易实现RSA密码系统matlab

    目录 RSA密码系统 随机寻找两个较大的素数 欧拉筛的算法函数 寻找随机素数的代码 生成公钥和私钥 加密解密方式 实现代码 运行结果 小结 首先来了解一下什么是RSA算法 RSA密码系统 RSA是被研究得最广泛的公钥算法 xff0c 从提出
  • 关于返回一个矩阵中为0元素个数及位置的matlab自定义函数实现以及用到的matlab基本操作

    目录 练习例题 题目要求 代码呈现 运行结果 基础操作 返回矩阵的行数列数 生成矩阵函数 取整取余函数 自定义函数参数缺省下的默认值以及输入参数为空集下替换为默认值的情况 find函数大观 对于find函数的改善调用 练习例题 题目要求 编
  • 蓝桥杯——单片机学习(3——点亮LED灯)

    注 xff1a 此单片机型号为 STC15F2K60S2 原理 如图 xff0c 发光二极管L1 L8 共阳接法 xff0c VCC为电源正极 xff0c 高电平 已知发光二极管正向导通反向截至 xff0c 要使得二极管发光 xff0c 就
  • 蓝桥杯——单片机学习(5(1)——按键(独立按键))

    注 xff1a 此单片机型号为 STC15F2K60S2 目录标题 独立按键原理按键原理消抖 代码入门代码进阶代码消抖改进 xff08 按一下只执行一次 xff0c 长按也一样 xff09 补充 独立按键 原理 这是一个矩阵按键的电路图 x