首页 > 其他分享 >单片机 键盘显示实验 实验二

单片机 键盘显示实验 实验二

时间:2024-11-07 16:49:38浏览次数:3  
标签:__ char unsigned 键盘 单片机 实验 按键 KeyValue

实验二    键盘显示实验

实验准备:软件Keil uVision5、Proteus 8 Professional

  • 实验目的

1、掌握矩阵键盘检测的原理和方法;

2、掌握按键消抖的方法;

3、再次熟悉数码管的显示。

  • 实验任务

从4×4矩阵键盘输入4位字符(如“15EF”),并显示于4位数码管。

  • 实验原理

在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,如图2-1所示。在矩阵键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。

图2-1 矩阵键盘

 矩阵键盘的按健识别方法很多,其中最常见的方法是行扫描法。行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法,下面介绍矩阵键盘的扫描过程。

(1)判断有无键按下

第一步:向所有的列输出口线输出低电平;

第二步:然后将行线的电平状态读入;

第三步:判断读入的行线值。若无键按下,所有的行线仍保持高电平状态;若有键按下,行线中至少应有一条线为低电平。

(2)去除按键的抖动

去抖原理:当判断到键盘上有键按下后,则延时一段时间再判断键盘的状态,若仍为有键按下状态,则认为有一个键按下,否则当作按键抖动来处理。

(3)按键识别(列或行扫描法)

在确认有键按下后,即可进入确定具体闭合键的过程。其方法是:依次将列(行)线置为低电平,即在置某根列(行)线为低电平时,其列(行)线为高电平,再逐行(列)检测各行(列)线的电平状态。若某行为低电平,则该行线与置为低电平的列线交叉处的按键就是闭合的按键。

(4)求按键的键值

根据闭合键的行值row和列值col采用计算法(如健值=行号×4+列号)或查表法将闭合键的行值和列值转换成所定义的键值。

电路原理图如下图所示。

图2-2 键盘显示实验电路

注释:上面的原理是课程设计给的模板,不是我写的,仅供参考,如有相同就是参考的,参考书:单片机原理与接口技术实验指导书、单片机原理与接口技术

  • 程序流程图

图一 程序流程图

  • 实验结果及分析总结

键盘显示实验测试结果

该电路图根据该实验指导书绘制,使用的软件Proteus 8 Professional,如图二所示,将编写好的代码(代码详情转附录)录入到该电路,从而实现键盘显示实验。(图中数码管输入的内容是本人学号后四位,如需需要输入其他内容可根据按键进行更改)。

图二 键盘显示电路仿真测试

编写数码管动态显示代码

本次实验实验代码模块化的内容,是根据本人在网络视频学习所得(江协科技——51单片机入门教程视频所得),本次实验模块化编程内容如图二所示。

附录中代码的顺序:main.c(主程序调用函数)、main.h(主程序的header文件)、keyScan.c(按键扫描函数)、keyScan.h、segDisplay.c(数码显示函数)、segDisplay.h、time0_int.c(定时器延迟函数)、time0_int.h。

图三 模块化代码编写内容

实验总结

本次实验运用之前偶然所学的模块编程的知识内容,首先,需要解决的问题是四个数码管输入问题。课程的学习只是一个数码管的编写,因此,使用数组keyValue完成四个数码管的定义,之后进行数码管的移位。其次,需要解决按键扫描的问题,再其次是需要解延时的问题,最后将编写好的程序在主函数中调用。本次的实验,需要结合学习过的知识点进行整合,修改合理的代码内容。在编写代码是需要先画出流程图,将程序模块化。处理的代码内容更加的清晰明了。

  • 程序附录

  • main.c程序

    #include"main.h" 
    							
    void main() 
    { 
     	unsigned char temp=0; 
     	unsigned char keyValue[4]={0};  //定义一个数组,用来存放四个数码管所显示的值
     	while(1){ 
        	temp=keyScan();  //keyScan()为矩阵按键扫描函数
          if(temp!=16) {  //因为矩阵按键所表示的值是0~15(在数码管上是显示0~F),所以要满足temp<16才执行下面滚显的指令
    				//当按键按了后,有新值进入数码管时,数码管的旧值都往左移一位,腾出一个位置给新值显示
    				keyValue[3]=keyValue[2];
    				keyValue[2]=keyValue[1];
    				keyValue[1]=keyValue[0];
    				keyValue[0]=temp;  
          } 
            segDisplay(keyValue);  //显示键值函数
      }  
    } 
     
    

    main.h

    #ifndef __MAIN_H__
    #define __MAIN_H__
    
    	#include"segDisplay.h"
    	#include"keyScan.h" 	
    
    #endif
    

    segDisplay.c

    #include"segDisplay.h"
    
    //显示0~F的值,采用共阳数码管
    //定义中的code代表的是把定义的数据表存储在flash存储器中,如去掉code则存储在RAM中
    unsigned char code sgmduan[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 
    	                            0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
    
    void segDisplay(unsigned char *value){ 
    	unsigned char i; 
        for(i=0;i<4;i++){ 
        	switch(i){           //位选,选择点亮的数码管,  
            	//数码管从右往左排序
    				  case(0): 
                LSA=0;LSB=0;LSC=0;LSD=1; break;//显示第 0 位 
              case(1): 
                LSA=0;LSB=0;LSC=1;LSD=0; break;//显示第 1 位 
              case(2): 
                LSA=0;LSB=1;LSC=0;LSD=0; break;//显示第 2 位 
              case(3): 
                LSA=1;LSB=0;LSC=0;LSD=0; break;//显示第 3 位  
          } 
    	    P0=sgmduan[value[i]];//发送段码 
            
    			//Delay(100); //间隔一段时间扫描 
    		  //定时器延时
    			timer0_init();
    		  while(~TF0);
    			TF0=0;		 
          P0=0xFF;//消隐上次显示的数字,使下次显示更清晰 
        }  
    } 

    segDisplay.h

  • #ifndef __SEGDISPLAY_H__
    #define __SEGDISPLAY_H__
    
    	#include"timer0_init.h"
    	sbit LSA=P1^3; 
    	sbit LSB=P1^2; 
    	sbit LSC=P1^1; 
    	sbit LSD=P1^0;
    	void segDisplay(unsigned char *value);
    
    #endif

    keyScan.c
     

    #include "keyScan.h"
    
    unsigned char keyScan() { 
        unsigned char a = 0;
        unsigned char t; 
        unsigned char KeyValue = 16;
        P2 = 0xF0;
        if (P2 != 0xF0) {
            for (t = 0; t < 10; t++) {
                timer0_init();
                while (~TF0);
                TF0 = 0;				
            }
            if (P2 != 0xF0) {
                P2 = 0xF0; 
                switch (P2) { 
                    case (0x70): KeyValue = 3; break;
                    case (0xB0): KeyValue = 2; break; 
                    case (0xD0): KeyValue = 1; break; 
                    case (0xE0): KeyValue = 0; break; 
                } 
                P2 = 0x0F; 
                switch (P2) { 
                    case (0x07): KeyValue = KeyValue + 12; break;
                    case (0x0B): KeyValue = KeyValue + 8; break; 
                    case (0x0D): KeyValue = KeyValue + 4; break; 
                    case (0x0E): KeyValue = KeyValue; break; 
                } 
                while ((a < 50) && (P2 != 0x0F)) { 
                    for (t = 0; t < 10; t++) {
                        timer0_init();
                        while (~TF0);
                        TF0 = 0;					
                    }
                    a++; 
                } 
            }   
        }
        return KeyValue;

    keyScan.h

    #ifndef __KEYSCAN_H__
    #define __KEYSCAN_H__
    
    	#include"timer0_init.h"
    	unsigned char keyScan();
    	extern unsigned char keyValue[4];  //外部变量声明
    
    #endif
    

    timer0_init.c

    #include"timer0_init.h"
    
    void timer0_init(){  //定时器初始化函数
    	EA=1;  //打开总中断
    	ET0=1;  //中断0控制允许位
    	TR0=1;  //开启中断0
    	TMOD=0x01;//定时器工作模式为1
    	TH0=0xfc;//定时器延时10ms(延时1ms为FC66H)
    	TL0=0x66;
    }
    

    timer0_init.h

    #ifndef __TIMER0_INIT_H__
    #define __TIMER0_INIT_H__
    
    	#include"reg52.h"
    	void timer0_init();
    
    #endif
    

    学习过程中,参考资料网上的,如有侵权删。如有需要自行下载源文件,里面code文件是程序代码,还有一个仿真文件。

标签:__,char,unsigned,键盘,单片机,实验,按键,KeyValue
From: https://blog.csdn.net/m0_64711058/article/details/143599703

相关文章

  • 实验3 类和对象_基础编程2
    1.实验任务1button.hpp源代码:1#pragmaonce23#include<iostream>4#include<string>56usingstd::string;7usingstd::cout;89//按钮类10classButton{11public:12Button(conststring&text);13stringget_label()......
  • # 20222326 2024-2025-1 《网络与系统攻防技术》实验四实验报告
    1.实验内容一、恶意代码文件类型标识、脱壳与字符串提取对提供的rada恶意代码样本,进行文件类型识别,脱壳与字符串提取,以获得rada恶意代码的编写作者,具体操作如下:(1)使用文件格式和类型识别工具,给出rada恶意代码样本的文件格式、运行平台和加壳工具;(2)使用超级巡警脱壳机等脱壳软件,......
  • 20222317 2024-2025-1 《网络与系统攻防技术》实验四实验报告
    1.实验内容1.1恶意代码文件类型标识、脱壳与字符串提取对提供的rada恶意代码样本,进行文件类型识别,脱壳与字符串提取,以获得rada恶意代码的编写作者,具体操作如下:(1)使用文件格式和类型识别工具,给出rada恶意代码样本的文件格式、运行平台和加壳工具;(2)使用超级巡警脱壳机等脱壳软件,......
  • 20222307 2024-2025-1 《网络与系统攻防技术》实验四实验报告
    1.实验内容1.1本周所学IDApro、ProcessExplorer、peid、超级巡警等软件的学习与使用PE文件、蜜罐技术、tcpdump等专业知识的学习对于wireshark的抓包的深入分析1.2实验环境主机kali虚拟机安装winXP虚拟机实现xp与主机的ping通,参照:关闭xp虚拟机防火墙1.3实践内容......
  • neutron-双网卡实验
    192.168.222.5(管理网络)双网卡的配置yum1.网络2.本地源的使用一、建虚拟机自定义(高级)稍后安装操作系统客户机操作系统:Linux版本:CentOS764位处理器数量:2内存:2GB默认(NAT)选推荐创建新虚拟磁盘最大磁盘大小:20GB将虚拟磁盘拆分为多个文件完......
  • 实验3
    task1.cpp1#pragmaonce23#include<iostream>4#include<string>56usingstd::string;7usingstd::cout;89//按钮类10classButton{11public:12Button(conststring&text);13stringget_label()const;14......
  • 实验3 类和对象_基础编程2
    test1:task1.cpp:#include"window.hpp"#include<iostream>usingstd::cout;usingstd::cin;voidtest(){Windoww1("newwindow");w1.add_button("maximize");w1.display();w1.close();}intmain(){......
  • 实验3
    #pragmaonce#include<iostream>#include<string>usingstd::string;usingstd::cout;//按钮类classButton{public:Button(conststring&text);stringget_label()const;voidclick();private:stringlabel;};Button:......
  • Linux 外设驱动 应用 6 摄像头采集实验
    摄像头采集实验1摄像头基础介绍1.1驱动介绍-V4L2简介1.2硬件介绍2代码编写2.1打开设备文件2.2取得设备的capability,看看设备具有什么功能,比如是否具有视频输入,或者音频输入输出等2.3选择视频输入,一个视频设备可以有多个视频输入。VIDIOC_S_INPUT,structv4l2......
  • 实验3 类和对象 基础编程
    实验一task1.cpp#include"window.hpp"#include<iostream>usingstd::cout;usingstd::cin;voidtest(){Windoww1("newwindow");w1.add_button("maximize");w1.display();w1.close();}intmain(){......