蓝桥杯单片机开发及应用-基础模块06-矩阵键盘

这篇具有很好参考价值的文章主要介绍了蓝桥杯单片机开发及应用-基础模块06-矩阵键盘。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、先前知识

使用到的74HC138译码器、74HC573锁存器和数码管模块等,在前面的基础模块的介绍中都有简单介绍,这里就不再介绍了。

  1. 按键之矩阵键盘模块

蓝桥杯板子上按键部分的右下角有个J5模块,用跳帽来进行独立按键和矩阵键盘之间的切换。此次使用矩阵键盘的时候需要把跳帽接到1~2引脚。

矩阵键盘就是4×4,一共16个按键。其工作原理是,用跳帽将四行按键的左边都与单片机的引脚相连,那么电平就为单片机引脚输出电平。按键在没有按下的时候按键下方的两个触点是没有接在一起的,也就是说原理图上按键的左边脚始终是与单片机引脚输出的电平相同。当按键按下,按键下方的金属垫片接触时,两个触点接通,那么按键右边的脚(也是单片机其他的引脚)就会检测到与按键左边引脚相同的电平。就是依据此特征来判断按键是否被按下。

我们看到蓝桥杯板子上的按键是有四个脚的,而上篇文章中的独立按键和此次的矩阵键盘,似乎都只用到了两个脚,那么是不是错误的呢?

其实不是,按键虽然有四个端口,但是按键内部有两个脚是短接的,另外两个脚是引出脚,一个作为输入,一个作为输出。

蓝桥杯单片机板子,# 蓝桥杯基础模块,蓝桥杯,单片机,51单片机,c语言,Powered by 金山文档

图一、按键模块

  1. 部分代码解释

就第一行按键部分的代码而言(其他行按键的代码类似):

在矩阵键盘中要判断哪一个按键按下需要用到扫描的思想,从上到下依次给每一行低电平,当某一列检测到低电平的时候,就可以用坐标的思想,找到是哪一个按键被按下。一次只能把一行给低电平,扫哪一行哪一行就是低电平。

    R1 = 0;                // 先检测第一行按键是否被按下,那么就给第一行低电平
    R2 = R3 = R4 = 1;      // 其他行给高电平
    C1 = C2 = C3 = C4 = 1; // 先初始化默认每一列的按键都没有被按下
    if( C1 == 0 )                // 第一行第一列被按下,S7
    {
        while( C1 == 0 );
        Key_Num = 7;
    }
    else if( C2 == 0 )          // 第一行第二列被按下,S11
    {
        while( C2 == 0 );
        Key_Num = 11;
    }
    else if( C3 == 0 )          // 第一行第三列被按下,S15
    {
        while( C3 == 0 );
        Key_Num = 15;
    }
    else if( C4 == 0 )          // 第一行第四列被按下,S19
    {
        while( C4 == 0 );
        Key_Num = 19;
    }

二、模块控制实现过程简述

先把按键的跳帽接到1~2引脚上,然后定义输出行和输入行,再用扫描的方法控制矩阵键盘。

三、所要实现的功能

首先上电之后数码管的后两位显示00,然后根据板子上矩阵键盘的每个按键的名称,当按键被按下后在数码管上显示相应的数字。(也就是如果某个按键上标的数是S07,那么该按键按下后数码管的后两位就显示07,如果某个按键上标的数是S16,那么该按键按下后数码管的后两位就显示16)程序循环实现上述功能。

四、代码实现

①引脚以及参数定义

// 矩阵键盘定义输入行
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;


// 矩阵键盘定义输出列
sbit C1 = P4^4;
sbit C2 = P4^2;
sbit C3 = P3^5;
sbit C4 = P3^4;


// 参数定义
unsigned char Key_Num;    // 按键角标

②数码管段码

// 数码管段码
unsigned char code SMG_Duanma[18] = 
{
    0xc0 , 0xf9 , 0xa4 , 0xb0 , 0x99 , 0x92 , 0x82 , 0xf8 , 0x80 ,
    0x90 , 0x88 , 0x80 , 0xc6 , 0xc0 , 0x86 , 0x8e , 0xbf , 0x7f
};    // 0~F - .

③138译码器通道选择函数

// 通道选择
void HC138_Init( unsigned char channel )
{
    switch( channel )
    {
        case 0:
            P2 = (P2 & 0x1f) | 0x00;    // 0
        break;
        case 4:
            P2 = (P2 & 0x1f) | 0x80;    // Y4C
        break;
        case 5:
            P2 = (P2 & 0x1f) | 0xa0;    // Y5C
        break;
        case 6:
            P2 = (P2 & 0x1f) | 0xc0;    // Y6C
        break;
        case 7:
            P2 = (P2 & 0x1f) | 0xe0;    // Y7C
        break;
    }
}

④初始化系统-关闭目前不需要的蜂鸣器和继电器

// 初始化系统
void Init_System(void)
{
    // 关闭LED灯
    HC138_Init( 4 );
    P0 = 0xff
    
    // 关闭蜂鸣器和继电器
    HC138_Init( 5 );
    P0 = 0xaf;          // 1010 1111

    HC138_Init( 0 );    // 关闭通道选择
}

⑤单个数码管点亮函数

// 单个数码管点亮
void SMG_Light( unsigned char pos , unsigned char dat )
{
    HC138_Init( 6 );
    P0 = 0x01 << pos;    // 某个数码管处于准备阶段
    
    HC138_Init( 7 );
    P0 = dat;            // 显示数值
}

⑥数码管显示函数

// 数码管显示
void SMG_Show( unsigned char num )
{
    SMG_Light( 0 , 0xff );    // 不用的数码管就关闭
    Delay_tms( 10 );
    SMG_Light( 1 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 2 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 3 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 4 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 5 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 6 , SMG_Duanma[ num / 10 ] );
    Delay_tms( 10 );
    SMG_Light( 7 , SMG_Duanma[ num % 10 ] );
    Delay_tms( 10 );
}

⑦按键扫描函数

// 按键扫描
void Key_Scan(void)
{
    // 第一行
    R1 = 0;
    R2 = R3 = R4 = 1;
    C1 = C2 = C3 = C4 = 1;
    if( C1 == 0 )                // S7
    {
        while( C1 == 0 );
        Key_Num = 7;
    }
    else if( C2 == 0 )          // S11
    {
        while( C2 == 0 );
        Key_Num = 11;
    }
    else if( C3 == 0 )          // S15
    {
        while( C3 == 0 );
        Key_Num = 15;
    }
    else if( C4 == 0 )          // S19
    {
        while( C4 == 0 );
        Key_Num = 19;
    }
    
    // 第二行
    R2 = 0;
    R1 = R3 = R4 = 1;
    C1 = C2 = C3 = C4 = 1;
    if( C1 == 0 )                // S6
    {
        while( C1 == 0 );
        Key_Num = 6;
    }
    else if( C2 == 0 )          // S10
    {
        while( C2 == 0 );
        Key_Num = 10;
    }
    else if( C3 == 0 )          // S14
    {
        while( C3 == 0 );
        Key_Num = 14;
    }
    else if( C4 == 0 )          // S18
    {
        while( C4 == 0 );
        Key_Num = 18;
    }
    
    // 第三行
    R3 = 0;
    R2 = R1 = R4 = 1;
    C1 = C2 = C3 = C4 = 1;
    if( C1 == 0 )                // S5
    {
        while( C1 == 0 );
        Key_Num = 5;
    }
    else if( C2 == 0 )          // S9
    {
        while( C2 == 0 );
        Key_Num = 9;
    }
    else if( C3 == 0 )          // S13
    {
        while( C3 == 0 );
        Key_Num = 13;
    }
    else if( C4 == 0 )          // S17
    {
        while( C4 == 0 );
        Key_Num = 17;
    }
    
    // 第四行
    R4 = 0;
    R2 = R3 = R1 = 1;
    C1 = C2 = C3 = C4 = 1;
    if( C1 == 0 )                // S4
    {
        while( C1 == 0 );
        Key_Num = 4;
    }
    else if( C2 == 0 )          // S8
    {
        while( C2 == 0 );
        Key_Num = 8;
    }
    else if( C3 == 0 )          // S12
    {
        while( C3 == 0 );
        Key_Num = 12;
    }
    else if( C4 == 0 )          // S16
    {
        while( C4 == 0 );
        Key_Num = 16;
    }
}

⑧延时函数

void Delay_tms( unsigned int t )
{
    int i;
    while( t-- )
    {
        for( i=115 ; i>0 ; i-- )
        {
            
        }
    }
}

⑨整个函数展示文章来源地址https://www.toymoban.com/news/detail-775463.html


#include <STC15F2K60S2.H>
#include "Delay_ms.h"


// 矩阵键盘定义输入行
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;


// 矩阵键盘定义输出列
sbit C1 = P4^4;
sbit C2 = P4^2;
sbit C3 = P3^5;
sbit C4 = P3^4;


// 参数定义
unsigned char Key_Num;    // 按键角标


// 数码管段码
unsigned char code SMG_Duanma[18] = 
{
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,
    0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f
};    // 0~F - .


// 通道选择
void HC138_Init( unsigned char channel )
{
    switch( channel )
    {
        case 0:
            P2 = (P2 & 0x1f) | 0x00;    // 0
        break;
        case 4:
            P2 = (P2 & 0x1f) | 0x80;    // Y4C
        break;
        case 5:
            P2 = (P2 & 0x1f) | 0xa0;    // Y5C
        break;
        case 6:
            P2 = (P2 & 0x1f) | 0xc0;    // Y6C
        break;
        case 7:
            P2 = (P2 & 0x1f) | 0xe0;    // Y7C
        break;
    }
}


// 初始化系统
void Init_System(void)
{
    // 关闭LED灯
    HC138_Init( 4 );
    P0 = 0xff
    
    // 关闭蜂鸣器和继电器
    HC138_Init( 5 );
    P0 = 0xaf;          // 1010 1111

    HC138_Init( 0 );    // 关闭通道选择
}


// 单个数码管点亮
void SMG_Light( unsigned char pos , unsigned char dat )
{
    HC138_Init( 6 );
    P0 = 0x01 << pos;    // 某个数码管处于准备阶段
    
    HC138_Init( 7 );
    P0 = dat;            // 显示数值
}


// 数码管显示
void SMG_Show( unsigned char num )
{
    SMG_Light( 0 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 1 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 2 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 3 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 4 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 5 , 0xff );
    Delay_tms( 10 );
    SMG_Light( 6 , SMG_Duanma[ num / 10 ] );
    Delay_tms( 10 );
    SMG_Light( 7 , SMG_Duanma[ num % 10 ] );
    Delay_tms( 10 );
}


// 按键扫描
void Key_Scan(void)
{
    // 第一行
    R1 = 0;
    R2 = R3 = R4 = 1;
    C1 = C2 = C3 = C4 = 1;
    if( C1 == 0 )                // S7
    {
        while( C1 == 0 );
        Key_Num = 7;
    }
    else if( C2 == 0 )          // S11
    {
        while( C2 == 0 );
        Key_Num = 11;
    }
    else if( C3 == 0 )          // S15
    {
        while( C3 == 0 );
        Key_Num = 15;
    }
    else if( C4 == 0 )          // S19
    {
        while( C4 == 0 );
        Key_Num = 19;
    }
    
    // 第二行
    R2 = 0;
    R1 = R3 = R4 = 1;
    C1 = C2 = C3 = C4 = 1;
    if( C1 == 0 )                // S6
    {
        while( C1 == 0 );
        Key_Num = 6;
    }
    else if( C2 == 0 )          // S10
    {
        while( C2 == 0 );
        Key_Num = 10;
    }
    else if( C3 == 0 )          // S14
    {
        while( C3 == 0 );
        Key_Num = 14;
    }
    else if( C4 == 0 )          // S18
    {
        while( C4 == 0 );
        Key_Num = 18;
    }
    
    // 第三行
    R3 = 0;
    R2 = R1 = R4 = 1;
    C1 = C2 = C3 = C4 = 1;
    if( C1 == 0 )                // S5
    {
        while( C1 == 0 );
        Key_Num = 5;
    }
    else if( C2 == 0 )          // S9
    {
        while( C2 == 0 );
        Key_Num = 9;
    }
    else if( C3 == 0 )          // S13
    {
        while( C3 == 0 );
        Key_Num = 13;
    }
    else if( C4 == 0 )          // S17
    {
        while( C4 == 0 );
        Key_Num = 17;
    }
    
    // 第四行
    R4 = 0;
    R2 = R3 = R1 = 1;
    C1 = C2 = C3 = C4 = 1;
    if( C1 == 0 )                // S4
    {
        while( C1 == 0 );
        Key_Num = 4;
    }
    else if( C2 == 0 )          // S8
    {
        while( C2 == 0 );
        Key_Num = 8;
    }
    else if( C3 == 0 )          // S12
    {
        while( C3 == 0 );
        Key_Num = 12;
    }
    else if( C4 == 0 )          // S16
    {
        while( C4 == 0 );
        Key_Num = 16;
    }
}




int main(void)
{
    Init_System();              // 初始化系统
    while(1)
    {
        Key_Scan();             // 按键扫描
        SMG_Show( Key_Num );    // 数码管显示
    }
}

五、运行图片

蓝桥杯单片机板子,# 蓝桥杯基础模块,蓝桥杯,单片机,51单片机,c语言,Powered by 金山文档

到了这里,关于蓝桥杯单片机开发及应用-基础模块06-矩阵键盘的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 蓝桥杯 单片机原理及应用-试题汇总及答案

    单片机原理及应用-试题汇总及答案 1、单片机是将微处理器、一定容量的 RAM 和ROM以及 I/O 口、定时器等电路集成在一块芯片上而构成的微型计算机。 2、单片机89C51片内集成了 4 KB的FLASH ROM,共有 5 个中断源。 3、两位十六进制数最多可以表示 256 个存储单元。 4、89C51是以下哪

    2024年02月07日
    浏览(45)
  • 蓝桥杯单片机零基础到国二经验分享

    蓝桥杯单片机零基础到国二经验分享

             我参加的是第十三届蓝桥杯大赛,从最开始的零基础,毫无头绪,到拿下国二,颇有体会,在这里将我的备赛经验分享给大家,希望可以帮到一些正在备赛的蓝桥杯er 目录 一. 蓝桥杯-单片机组介绍 二 . 零基础到国二历程         客观题:         程序题:

    2024年02月03日
    浏览(45)
  • 蓝桥杯-单片机设计与开发组-(1)经验分享

    蓝桥杯-单片机设计与开发组-(1)经验分享

            首先,我先自我介绍一下,本人是一名大二小菜。在2023年十四届蓝桥杯中获得了省级二等奖,虽然谈不上优秀,不过在备赛过程中也有了自已的一套心得与看法,在两个月备赛过程中,我已经把16年到22真题全部独立完成了。因此,有了一个想法想要在CSDN分享一下

    2024年02月05日
    浏览(46)
  • 蓝桥杯单片机—— PCF8591的基本原理及A/D转换应用(14)

    蓝桥杯单片机—— PCF8591的基本原理及A/D转换应用(14)

    一、原理分析 1、基本概念 PCF8591是一个单片集成、单独供电、低功耗、 8-bit CMOS数据获取器件 。PCF8591具有 4个模拟输入、1个模拟输出和1个串行I²C总线接口 。PCF8591的3个地址引脚 A0, A1和A2可用于硬件地址编程 ,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在

    2023年04月14日
    浏览(14)
  • 【蓝桥杯单片机】工厂灯光控制系统案例解析(小蜜蜂老师基础综合实训)

    【蓝桥杯单片机】工厂灯光控制系统案例解析(小蜜蜂老师基础综合实训)

    设备检测——移位 L1~L8在板子上是从左至右,但是在对P0口赋值时是16进制从 高位(L8)—低位(L0) 根据原理图,LED赋值 0亮1灭 为了方便赋值,可以把板子转一下,让LED排序与赋值顺序相同 左移 右移 控制移位补0 ,使LED依次点亮、依次熄灭 unsigned char i 作为下文表格中的循环变量

    2023年04月09日
    浏览(10)
  • C51单片机基础之4G模块

    C51单片机基础之4G模块

    EC03-DNC是亿佰特公司推出的 LTE CAT1 数传模块产品, 该产品软件功能完善, 覆盖绝大多数常规应用场景, EC03-DNC 是为实现串口设备与网络服务,通过网络相互传输数据而开发的产品 , 该产品是一款带分集接收功能 的LTE-FDD/LTE-TDD 无线通信数传模块, 支持 LTE-FDD , LTE-TDD 网络

    2023年04月08日
    浏览(11)
  • 蓝桥杯STC15F2K60S2单片机 CCP/PCA/PWM模块的学习与使用

    蓝桥杯STC15F2K60S2单片机 CCP/PCA/PWM模块的学习与使用

    有道是 “一花独放不是春,万紫千红春满园” 我们不能只满足于 眼前所谓的 “够用、能用” 的少量知识,而不去深入学习探究,进而不慎封锁了自己的见识 和 更多 创新开发上的可能性。 曾经仅满足于学习了蓝桥杯单片机的三个外部晶振 定时器: 定时器0、1、2. 就认为完

    2024年02月08日
    浏览(11)
  • 第十四届蓝桥杯(电子类)单片机开发——赛题源代码分享

    第十四届蓝桥杯(电子类)单片机开发——赛题源代码分享

          需要源代码一键三联,私聊我哦

    2024年02月05日
    浏览(50)
  • 单片机开发---ESP32-S3模块上手

    单片机开发---ESP32-S3模块上手

    想起来之前做的半成品单片机游戏机,又想继续做一个,不过之前那个单片机驱动屏幕速率太低,已经无法改进了。所以这次斥巨资购买了一款顶配的ESP32S开发板,做个简单的游戏机,没问题。 完整介绍链接 这花花绿绿的介绍,看着让人甚是喜欢呢。 参考乐鑫官网的方式,

    2024年01月23日
    浏览(9)
  • STM32F103RCT6开发板M3单片机教程06--定时器中断

    STM32F103RCT6开发板M3单片机教程06--定时器中断

    除非特别说明,本章节描述的模块应用于整个 STM32F103xx 微控制器系列,因为我们使用是 STM32F103RCT6开发板是mini最小系统板。 本教程使用是( 光明谷SUN_STM32mini开发板 )   首先了解一下是STM32F10X定时器(Timer)   注: 小容量产品是指闪存存储器容量在16K至32K字节之间的STM32F101

    2024年02月04日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包