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

STC15单片机-按键检测单击或长按(外部中断)

按键检测(外部中断)

STC15外部中断说明

在这里插入图片描述

程序

文件结构

在这里插入图片描述

main.c -> 主函数文件,包含 main 函数等,当用外部中断翻转指示灯时 ,则不用调用函数,否则调用按键扫描函数翻转指示灯;

Public.c -> 公共函数文件,包含 Delay 延时函数等;

Sys_init -> 系统初始化函数,包含 GPIO 初始化函数等;

LED.c -> LED 外设函数,包含 LED 打开、关闭函数等;

Timer0.c -> 定时器函数,包含定时器初始化,中断函数等;

KEY.c -> 按键函数,包含按键检测,中断函数等。

外部中断0配置

在LED闪烁(定时器)的工程中加上 KEY.c 和 KEY.h 文件,在Sys_Init.c文件中初始化外部中断0,在KEY.c中定义外部中断0中断处理函数,按键检测也是在KEY.c文件中实现

配置方法跟STC89C52一样

/*
* @name   IE_Init
* @brief  中断初始化
* @param  None
* @retval None   
*/
static void IE_Init()
{
    IT0 = 1;     //外部中断0选择下降沿触发
    EX0 = 1;     //打开外部中断0
    
    EA = 1;      //打开总中断
}

外部中断0中断处理函数

/*
* @name   INT0_isr
* @brief  外部中断0处理函数
* @param  None
* @retval None   
*/
void INT0_isr() interrupt 0
{
    KEY.KEY_Flag = 1;
    //Run_LED.Run_LED_Flip();		//运行指示灯翻转
}

使用外部中断就可实现按键按下运行指示灯翻转的效果

然后再实现按键检测,实现单击和长按的不同效果

KEY.c:

/* Includes ------------------------------------------------------------------*/
#include <main.h>

/* Private define-------------------------------------------------------------*/

/* Private variables----------------------------------------------------------*/
static void KEY_Detect();
/* Public variables-----------------------------------------------------------*/
KEY_t KEY1 = {FALSE,FALSE,FALSE,FALSE,KEY_Detect};
/* Private function prototypes------------------------------------------------*/

/*
* @name   KEY_Detect
* @brief  按键检测
* @param  None
* @retval None   
*/
static void KEY_Detect()
{
    uint8_t i;
    //单击检测
    if(KEY1.KEY_Flag == TRUE)        //外部中断改变标志位的值,说明按键被按下
    {
        KEY1.KEY_Flag = FALSE;       //标志位重新置0,为下次按键准备
        EX0 = 0;                    //关闭中断
        if(KEY1_State == 0)
        {
            Public.Delay_ms(5);         //虽然硬件已经有消抖功能,软件再做一次
            if(KEY1_State == 0)
            {
                KEY1.Click = TRUE;       //单击标志位置1
            }
        }
    }
    //长按检测
    if(KEY1.Click == TRUE)
    {
        KEY1.Press = TRUE;               //如果有按键按下,默认会进行长按
        for(i = 0;i<200;i++)            //每次循环延时10ms,即延时2秒
        {
            Public.Delay_ms(10);
            if(KEY1_State == 1)          //如果这期间按键松开了,则达不到长按的条件
            {
                KEY1.Press = FALSE;      //长按标志位清0
                break;                  //提前结束延时
            }
        }
    }

    //按键功能
    //单击 -> 运行指示灯翻转
    //长按 -> 运行指示灯闪一下
    if(KEY1.Press == TRUE)
    {
        Run_LED.Run_LED_Flip();
        Public.Delay_ms(100);
        Run_LED.Run_LED_Flip();
    }
    else
    {
        if(KEY1.Click == TRUE)
        {
            Run_LED.Run_LED_Flip();
        }
    }
    KEY1.Click = FALSE;
    KEY1.Press = FALSE;
    EX0 = 1;                        //打开中断
}

/*
* @name   INT0_isr
* @brief  外部中断0中断处理函数
* @param  None
* @retval None   
*/
void INT0_isr() interrupt 0
{
    KEY1.KEY_Flag = TRUE;
    //Run_LED.Run_LED_Flip();
}

/********************************************************
  End Of File
********************************************************/

为什么在标志位清0后要关闭外部中断?

因为在标志位清0时外部中断可能还会被触发,这可能是按键抖动引起的,标志位会重新被置1,在按键检测时会被重复判断

KEY.h:

头文件主要是按键引脚定义,结构体变量定义

#ifndef __KEY_H_
#define __KEY_H_

//定义按键引脚
#define KEY1_State P32

//定义结构体类型
typedef struct 
{
    uint8_t volatile KEY_Flag;      //按键标志位
    uint8_t Click;                  //单击
    uint8_t Double_Click;           //双击
    uint8_t Press;                  //长按
    void (*KEY_Detect)();
}KEY_t;

/* extern variables-----------------------------------------------------------*/
extern KEY_t KEY1;
/* extern function prototypes-------------------------------------------------*/ 

#endif
/********************************************************
  End Of File
********************************************************/

main.c:

主函数中调用KEY_Detect函数一直检测按键

/******************************************************************************
  * @file    main.c 
  * @author  
  * @version V1.0
  * @date    2022-xx-xx
  * @Conpany 
  * @project STC15实战项目
*******************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include <main.h>

/* Private define-------------------------------------------------------------*/

/* Private variables----------------------------------------------------------*/

/* Public variables-----------------------------------------------------------*/

/* Private function prototypes------------------------------------------------*/

/*
	* @name   main
	* @brief  主函数
	* @param  void	
	* @retval int      
*/
int main(void)
{	
	//系统初始化
	Hradware.Sys_Init();
	//系统主循环
	while(1)
	{
		//按键检测
		KEY1.KEY_Detect();
	}
}
/********************************************************
  End Of File
********************************************************/

相关文章:

  • 卷积神经网络工作原理图,图卷积神经网络原理
  • 猿创征文 |【C++】C向C++知识的过度(下)
  • 期货行业首批信创试点单位转型实践|信创专题
  • Ambari升级Atlas1.1.0到2.2.0
  • 公众号搜题平台系统
  • 【PTHREAD】线程退出与取消
  • 组件命名报错 “Component name “XXX“ should always be multi-word”的解决方法
  • 离职前一定要删除这几个文件,不然你的微信聊天记录全被别人看了
  • Vue(模板语法1)
  • 银行利率bp是什么意思,bp是什么意思贷款利率
  • 暗月项目四
  • 目标检测——关键点检测学习记录(三):人体骨骼点检测——自底向上
  • 隐私计算+区块链原生融合之后平台开放、提升性能,蚂蚁链隐私协作平台FAIR重磅架构升级
  • Loki 收集Nginx日志以 grafana 可视化展示
  • 异常与错误处理高级用法
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • 【Leetcode】104. 二叉树的最大深度
  • Android 控件背景颜色处理
  • IndexedDB
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • JavaScript设计模式与开发实践系列之策略模式
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • UMLCHINA 首席专家潘加宇鼎力推荐
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 模型微调
  • 浅谈web中前端模板引擎的使用
  • 区块链技术特点之去中心化特性
  • 如何借助 NoSQL 提高 JPA 应用性能
  • 如何设计一个比特币钱包服务
  • 深度学习在携程攻略社区的应用
  • 使用parted解决大于2T的磁盘分区
  • 思维导图—你不知道的JavaScript中卷
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • raise 与 raise ... from 的区别
  • Salesforce和SAP Netweaver里数据库表的元数据设计
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • #《AI中文版》V3 第 1 章 概述
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (9)STL算法之逆转旋转
  • (LeetCode 49)Anagrams
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (一)80c52学习之旅-起始篇
  • (已解决)报错:Could not load the Qt platform plugin “xcb“
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)EOS中账户、钱包和密钥的关系
  • (转)iOS字体
  • (转)mysql使用Navicat 导出和导入数据库
  • (转)人的集合论——移山之道
  • .libPaths()设置包加载目录
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET MVC、 WebAPI、 WebService【ws】、NVVM、WCF、Remoting
  • .NET 中使用 TaskCompletionSource 作为线程同步互斥或异步操作的事件
  • .NET/C# 使窗口永不获得焦点