蓝桥杯单片机按键进阶

news2025/12/15 13:31:17

蓝桥杯单片机按键进阶

——基于柳离风老师模板及按键进阶教程

文章目录

  • 蓝桥杯单片机按键进阶
    • 1、按键测试-按下生效
    • 2、按键进阶-松手生效
    • 3、按键进阶-按键禁用(未完待续)

1、按键测试-按下生效

key.c

#include "key.h"


/**
 * @brief 独立按键扫描函数
 * 
 * @return uchar 键值对应的元件位号
 */
uchar key_scan1(void)
{
    uchar key = 0;                      //按键值
    static bit key_up = 1;              //按键松开标志,1松开0按下
    if((key_up == 1) && (P30 == 0 || P31 == 0 || P32 == 0 || P33 == 0))
    {
        key_up = 0;
        if(P30 == 0)          key = 7;
        else if(P31 == 0)     key = 6;
        else if(P32 == 0)     key = 5;
        else if(P33 == 0)     key = 4;
        return key;
    }
    else if(P30 == 1 && P31 == 1 && P32 == 1 && P33 == 1)
        key_up = 1;
    return 0;
}


/**
 * @brief 矩阵键盘扫描函数
 * 
 * @return uchar 键值对应的元件位号
 */
uchar key_scan2(void)
{
    uchar key = 0;                      //按键值
    static bit key_up = 1;              //按键松开标志,1松开0按下
    P44 = P42 = 1;                      //列扫描
    P32 = P33 = 0;
    if((key_up == 1)&&(P44 == 0 || P42 == 0))
    {
        
        if(P44 == 0)        key = 7;
        else if(P42 == 0)   key = 11;
        else                return 0;
        key_up = 0;                     //标志按下
        P44 = P42 = 0;
        P32 = P33 = 1;                  //行扫描
        if(P32 == 0)   key = key - 2;
        else if(P33 == 0)   key = key - 3;
        return key;
    }
    else if(P44 == 1 && P42 == 1)
        key_up = 1;                     //松开
    return 0;
}


main.c

//按键处理任务
void key_task(void)
{
    uchar key_num;
    if(key_dly<10)return;
    key_dly = 0;
//    key_num = key_scan1();
    key_num = key_scan2();
    switch (key_num)
    {
        /* 独立按键 */
//        case 4:  num++;
//            break;
//        case 5:  num--;
//            break;
//        case 6:  flag_L1 ^= 1;
//            break;
//        case 7:  state_display = (state_display+1)%2;
//            break;
        
        /* 矩阵键盘 */
        case 4:  num++;
            break;
        case 5:  num--;
            break;
        case 8:  flag_L1 ^= 1;
            break;
        case 9:  state_display = (state_display+1)%2;
            break;
    }
}

2、按键进阶-松手生效

key.c

#include "key.h"


/**
 * @brief 独立按键扫描函数
 * 
 * @return uchar 键值对应的元件位号
 */
uchar key_scan1(void)
{
    uchar key = 0;                      //按键值
    static bit key_up = 1;              //按键松开标志,1松开0按下
    static bit flag_s4 = 0;             //按键4按下标志
    if((key_up == 1) && (P30 == 0 || P31 == 0 || P32 == 0 || P33 == 0))
    {
        key_up = 0;
        if(P30 == 0)          key = 7;
        else if(P31 == 0)     key = 6;
        else if(P32 == 0)     key = 5;
        else if(P33 == 0)
        {
            flag_s4 = 1;                //标记按下
            key = 4;
        }
        return key;
    }
    else if(P30 == 1 && P31 == 1 && P32 == 1 && P33 == 1)
    {
        key_up = 1;
        if(flag_s4 == 1)
        {
            flag_s4 = 0;
            return 40;                  //松手生效
        }
    }
    return 0;
}


/**
 * @brief 矩阵键盘扫描函数
 * 
 * @return uchar 键值对应的元件位号
 */
uchar key_scan2(void)
{
    uchar key = 0;                      //按键值
    static bit key_up = 1;              //按键松开标志,1松开0按下
    static bit flag_s4 = 0;             //按键4按下标志
    P44 = P42 = 1;                      //列扫描
    P32 = P33 = 0;
    if((key_up == 1)&&(P44 == 0 || P42 == 0))
    {
        
        if(P44 == 0)        key = 7;
        else if(P42 == 0)   key = 11;
        else                return 0;
        key_up = 0;                     //标志按下
        P44 = P42 = 0;
        P32 = P33 = 1;                  //行扫描
        if(P32 == 0)   key = key - 2;
        else if(P33 == 0)
        {
            key = key - 3;
            if(key == 4) flag_s4 = 1;   //标记按下,这里判断键值是因为有两种可能s8,s4
        }
        return key;
    }
    else if(P44 == 1 && P42 == 1)
    {
        key_up = 1;                     //松开
        if(flag_s4 == 1)
        {
            flag_s4 = 0;
            return 40;                  //松手生效
        }
    }
    return 0;
}


main.c

//按键处理任务
void key_task(void)
{
    uchar key_num;
    if(key_dly<10)return;
    key_dly = 0;
//    key_num = key_scan1();
    key_num = key_scan2();
    switch (key_num)
    {
        /* 独立按键 */
//        case 4:  state_display = 1;//按下显示界面1
//            break;
//        case 5:  num--;
//            break;
//        case 6:  num++;
//            break;
//        case 7:  flag_L1 ^= 1;
//            break;
//        case 40:  state_display = 0;//松手显示界面0
//            break;
        
        /* 矩阵键盘 */
        case 4:  state_display = 1;//按下显示界面1
            break;
        case 5:  num--;
            break;
        case 8:  num++;
            break;
        case 9:  flag_L1 ^= 1;
            break;
        case 40:  state_display = 0;//松手显示界面0
            break;
    }
}

3、按键进阶-按键禁用(未完待续)

key.c


main.c


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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS- 4.3 绝对定位(position: absolute)学校官网导航栏实例

本系列可作为前端学习系列的笔记&#xff0c;代码的运行环境是在HBuilder中&#xff0c;小编会将代码复制下来&#xff0c;大家复制下来就可以练习了&#xff0c;方便大家学习。 HTML系列文章 已经收录在前端专栏&#xff0c;有需要的宝宝们可以点击前端专栏查看&#xff01; 点…

Seata源码—6.Seata AT模式的数据源代理一

大纲 1.Seata的Resource资源接口源码 2.Seata数据源连接池代理的实现源码 3.Client向Server发起注册RM的源码 4.Client向Server注册RM时的交互源码 5.数据源连接代理与SQL句柄代理的初始化源码 6.Seata基于SQL句柄代理执行SQL的源码 7.执行SQL语句前取消自动提交事务的源…

计算机科技笔记: 容错计算机设计05 n模冗余系统 TMR 三模冗余系统

NMR&#xff08;N-Modular Redundancy&#xff0c;N 模冗余&#xff09;是一种通用的容错设计架构&#xff0c;通过引入 N 个冗余模块&#xff08;N ≥ 3 且为奇数&#xff09;&#xff0c;并采用多数投票机制&#xff0c;来提升系统的容错能力与可靠性。单个模块如果可靠性小于…

Spring Boot 与 RabbitMQ 的深度集成实践(一)

引言 ** 在当今的分布式系统架构中&#xff0c;随着业务复杂度的不断提升以及系统规模的持续扩张&#xff0c;如何实现系统组件之间高效、可靠的通信成为了关键问题。消息队列作为一种重要的中间件技术&#xff0c;应运而生并发挥着举足轻重的作用。 消息队列的核心价值在于其…

黑马程序员2024新版C++笔记 第2章 语句

1.if逻辑判断语句 语法主体&#xff1a; if(要执行的判断&#xff0c;结果是bool型){判断结果是true会执行的代码; } 2.AI大模型辅助编程 在Clion中搜索并安装对应插件&#xff1a; 右上角齿轮点击后找到插件(TRONGYI LINGMA和IFLYCODE)安装后重启ide即可。 重启后会有通义登…

前端动画库 Anime.js 的V4 版本,兼容 Vue、React

前端动画库 Anime.js 更新了 V4 版本&#xff0c;并对其官网进行了全面更新&#xff0c;增加了许多令人惊艳的效果&#xff0c;尤其是时间轴动画效果&#xff0c;让开发者可以更精确地控制动画节奏。 这一版本的发布不仅带来了全新的模块化 API 和显著的性能提升&#xff0c;还…

用 PyTorch 从零实现简易GPT(Transformer 模型)

用 PyTorch 从零实现简易GPT&#xff08;Transformer 模型&#xff09; 本文将结合示例代码&#xff0c;通俗易懂地拆解大模型&#xff08;Transformer&#xff09;从数据预处理到推理预测的核心组件与流程&#xff0c;并通过 Mermaid 流程图直观展示整体架构。文章结构分为四…

【通用大模型】Serper API 详解:搜索引擎数据获取的核心工具

Serper API 详解&#xff1a;搜索引擎数据获取的核心工具 一、Serper API 的定义与核心功能二、技术架构与核心优势2.1 技术实现原理2.2 对比传统方案的突破性优势 三、典型应用场景与代码示例3.1 SEO 监控系统3.2 竞品广告分析 四、使用成本与配额策略五、开发者注意事项六、替…

Spring3+Vue3项目中的知识点——JWT

全称&#xff1a;JOSN Web Token 定义了一种简洁的、自包含的格式&#xff0c;用于通信双方以json数据格式的安全传输信息 组成&#xff1a; 第一部分&#xff1a;Header&#xff08;头&#xff09;&#xff0c;记录令牌类型、签名算法等。 第二部分&#xff1a;Payload&am…

python3GUI--智慧交通分析平台:By:PyQt5+YOLOv8(详细介绍)

文章目录 一&#xff0e;前言二&#xff0e;效果预览1.目标识别与检测2.可视化展示1.车流量统计2. 目标类别占比3. 拥堵情况展示4.目标数量可视化 3.控制台4.核心内容区1.目标检测参数2.帧转QPixmap3.数据管理 5.项目结构 三&#xff0e;总结 平台规定gif最大5M&#xff0c;所以…

Linux任务管理与守护进程

一、任务管理 &#xff08;一&#xff09;进程组、作业、会话概念 &#xff08;1&#xff09;进程组概念&#xff1a;进程组是由一个或多个进程组成的集合&#xff0c;这些进程在某些方面具有关联性。在操作系统中&#xff0c;进程组是用于对进程进行分组管理的一种机制。每个…

C#里与嵌入式系统W5500网络通讯(2)

在嵌入式代码里,需要从嵌入式的MCU访问W5500芯片。 这个是通过SPI通讯来实现的,所以要先连接SPI的硬件通讯线路。 接着下来,就是怎么样访问这个芯片了。 要访问这个芯片,需要通过SPI来发送数据,而发送数据又要有一定的约定格式, 于是芯片厂商就定义下面的通讯格式: …

EMQX开源版安装指南:Linux/Windows全攻略

EMQX开源版安装教程-linux/windows 因最近自己需要使用MQTT&#xff0c;需要搭建一个MQTT服务器&#xff0c;所以想到了很久以前用到的EMQX。但是当时的EMQX使用的是开源版的&#xff0c;在官网可以直接下载。而现在再次打开官网时发现怎么也找不大开源版本了&#xff0c;所以…

【计算机视觉】OpenCV实战项目:GraspPicture 项目深度解析:基于图像分割的抓取点检测系统

GraspPicture 项目深度解析&#xff1a;基于图像分割的抓取点检测系统 一、项目概述项目特点 二、项目运行方式与执行步骤&#xff08;一&#xff09;环境准备&#xff08;二&#xff09;项目结构&#xff08;三&#xff09;执行步骤 三、重要逻辑代码解析&#xff08;一&#…

MySQL 数据库备份与还原

作者&#xff1a;IvanCodes 日期&#xff1a;2025年5月18日 专栏&#xff1a;MySQL教程 思维导图 备份 (Backup) 与 冗余 (Redundancy) 的核心区别: &#x1f3af; 备份是指创建数据的副本并将其存储在不同位置或介质&#xff0c;主要目的是在发生数据丢失、损坏或逻辑错误时进…

Kubernetes控制平面组件:Kubelet详解(四):gRPC 与 CRI gRPC实现

云原生学习路线导航页&#xff08;持续更新中&#xff09; kubernetes学习系列快捷链接 Kubernetes架构原则和对象设计&#xff08;一&#xff09;Kubernetes架构原则和对象设计&#xff08;二&#xff09;Kubernetes架构原则和对象设计&#xff08;三&#xff09;Kubernetes控…

javax.servlet.Filter 介绍-笔记

1.javax.servlet.Filter 简介 javax.servlet.Filter 是 Java Servlet API 中的一个核心接口&#xff0c;用于在请求到达目标资源&#xff08;如 Servlet 或 JSP&#xff09;之前或响应返回给客户端之前执行预处理或后处理操作。它常用于实现与业务逻辑无关的通用功能&#xff…

Win 11开始菜单图标变成白色怎么办?

在使用windows 11的过程中&#xff0c;有时候开始菜单的某些程序图标变成白色的文件形式&#xff0c;但是程序可以正常打开&#xff0c;这个如何解决呢&#xff1f; 这通常是由于快捷方式出了问题&#xff0c;下面跟着操作步骤来解决吧。 1、右键有问题的软件&#xff0c;打开…

入门OpenTelemetry——应用自动埋点

埋点 什么是埋点 埋点&#xff0c;本质就是在你的应用程序里&#xff0c;在重要位置插入采集代码&#xff0c;比如&#xff1a; 收集请求开始和结束的时间收集数据库查询时间收集函数调用链路信息收集异常信息 这些埋点数据&#xff08;Trace、Metrics、Logs&#xff09;被…

C语言链表的操作

初学 初学C语言时&#xff0c;对于链表节点的定义一般是这样的&#xff1a; typedef struct node {int data;struct node *next; } Node; 向链表中添加节点&#xff1a; void addNode(Node **head, int data) {Node *newNode (Node*)malloc(sizeof(Node));newNode->dat…