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

51单片机实验四:键盘检测原理及应用实现

目录

 

一、实验环境与实验器材

二、实验内容及实验步骤

1.独立键盘检测

2.独立键盘(简易版本)

3.矩阵键盘检测

4.矩阵键盘(简单版,单数码管):


 

一、实验环境与实验器材

 

环境:KeliSTC-ISP烧写软件,Proteus.        

器材:TX-1C单片机(STC89C52RC)、电脑。

图1.1 工具 

 

二、实验内容及实验步骤

1.独立键盘检测

用数码管的前两位显示一个十进制数,变化范围为00~59,开始时显示00,每按下S2一次,数值加1;每按下S3键一次,数值减1;每按下S4键一次;数值归零;按下S5一次,利用定时器功能使数值开始自动每秒加1,再次按下S5键,数值停止自动加1

#include "reg52.h"
#define uchar unsigned char
#define uint unsigned int 
sbit key1=P3^4;
sbit key2=P3^5;
sbit key3=P3^6;
sbit key4=P3^7;
sbit dula=P2^6;					// 申明U1锁存器的锁存端
sbit wela=P2^7;					// 申明U2锁存器的锁存端
uchar code table[]={  0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delayms(uint);uchar numt0,num;void display(uchar numdis)		// 显示子函数
{uchar shi,ge;					// 分离两个分别要显示的数shi=numdis/10;ge=numdis%10;dula=1;P0=table[shi];				// 送十位选段数据dula=0;P0=0xff;					// 送位选数据前关闭所有显示,防止打开位选锁存时wela=1;						// 原来段选数据通过位选锁存器造成混乱P0=0xfe;wela=0;delayms(100);				// 延时dula=1;P0=table[ge];				// 送个位段选数据dula=0;P0=0xff;wela=1;P0=0xfd;wela=0;delayms(100);
}void delayms(uint xms)
{uint i,j;for(i=xms;i>0;i--)          	// i=xms即延时约xms毫秒for(j=110;j>0;j--);
}void init()                    // 初始化函数
{TMOD=0x01;				// 设置定时器0为工作方式1(0000 0001)TH0=(65536-45872)/256;		// 初装值50ms一次中断TL0=(65536-45872)%256;EA=1;						// 开总中断ET0=1;						// 开定时器0中断
}void keyscan()
{if(key1==0){delayms(10);if(key1==0){num++;if(num==60)			 // 当到60时重新归0num=0;while(!key1); 		 // 等待按键释放}}if(key2==0){delayms(10);if(key2==0){if(num==0)			 // 当到0时重新归60num=60;num--;while(!key2);	}}if(key3==0){delayms(10);if(key3==0){num=0;				 // 清0while(!key3);}}if(key4==0){delayms(10);if(key4==0){while(!key4)TR0=~TR0;			// 停止或启动定时器0}}
}void main()
{init();						// 初始化函数while(1){keyscan();display(num);}
}void T0_time() interrupt 1
{TH0=(65536-45872)/256;		// 重装初值TL0=(65536-45872)%256;numt0++;if(numt0==20)				// 如果到了20次,说明1秒时间到{numt0=0;				// 然后把num清0重新再计20次num++;if(num==60)num=0; }
}

 

 图2.1.2 烧录

图2.1.3实体按键和数码管初始显示 

图2.1.4 实体按键功能说明 

Proteus因为延时原因,数码管第一位会闪。(截图不显示)按键从上到下依次为S1,S2,S3,S4,S5

图2.1.1 proteus仿真图

仿真视频:

独立键盘检测

2.独立键盘(简易版本)

现象:每按一次键盘数码管数值加1.

代码:

#include "reg52.h"
sbit key0=P1^0;
unsigned char s[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; //共阴0-9
//unsigned char str[]={0x76,0x79,0x38,0x38,0x3F};	// HELLO
//unsigned char wei[]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07};
unsigned char num=0,flag=0;void delay(int n)
{int i=0,j=0;for (i=0;j<120;j++){for (j=0;j<120;j++);}
}void seg()
{P2=s[num];if(num==10){num=0;}
}/*void key()
{if(key0==0){delay(200);if(key0==0){num++;}}
}*/
void key()
{if(key0==0 && flag==0){flag=1;}if(flag==1 && key0==1){num++;flag=0;}
}void main()
{while(1){key();seg();}
}

图2.2.1 独立键盘简易仿真图

仿真视频:

独立键盘简易仿真

3.矩阵键盘检测

实验板上电时,数码管不显示,顺序按下矩阵键盘后,在数码管上依次显示0~F6个数码管同时静态显示。

#include"reg52.h"
#define uchar unsigned char
#define uint unsigned int 
sbit dula=P2^6;					// 申明U1锁存器的锁存端
sbit wela=P2^7;					// 申明U2锁存器的锁存端
uchar code table[]={  0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};void delayms(uint xms)
{uint i,j;for(i=xms;i>0;i--)			//i=xms即延时约xms毫秒for(j=110;j>0;j--);
}void display(uchar num)
{P0=table[num];			//显示函数只送段选数据dula=1;dula=0;
}void matrixkeyscan()
{uchar temp,key;P3=0xfe;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delayms(10);temp=P3;temp=temp&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xee:key=0;break;case 0xde:key=1;break;case 0xbe:key=2;break;case 0x7e:key=3;break;}while(temp!=0xf0)			//等待按键释放{temp=P3;temp=temp&0xf0;}display(key);		        // 显示}}P3=0xfd;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delayms(10);temp=P3;temp=temp&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xed:key=4;break;case 0xdd:key=5;break;case 0xbd:key=6;break;case 0x7d:key=7;break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}display(key);}}P3=0xfb;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delayms(10);temp=P3;temp=temp&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xeb:key=8;break;case 0xdb:key=9;break;case 0xbb:key=10;break;case 0x7b:key=11;break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}display(key);}}P3=0xf7;temp=P3;temp=temp&0xf0;if(temp!=0xf0){delayms(10);temp=P3;temp=temp&0xf0;if(temp!=0xf0){temp=P3;switch(temp){case 0xe7:key=12;break;case 0xd7:key=13;break;case 0xb7:key=14;break;case 0x77:key=15;break;}while(temp!=0xf0){temp=P3;temp=temp&0xf0;}display(key);}}
}void main()
{P0=0;			//关闭所有数码管段选dula=1;dula=0;P0=0xc0;			// 位选中所有数码管wela=1;wela=0;while(1){matrixkeyscan();	//不停调用键盘扫描程序}
}

 

图2.3.1 上电现象(实体)

图2.3.2  按第一个按钮现象(实体)

图2.3.3  最后一个按钮现象(实体)

 

 Proteus仿真:

图2.3.4 矩阵键盘仿真图 

仿真视频:

矩阵键盘

4.矩阵键盘(简单版,单数码管):

图2.4.1 简易版矩阵键盘仿真图 

#include "reg52.h"
unsigned char s[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴0-9
unsigned char num=99;void delay(unsigned int n)
{unsigned int i=0,j=0;for(i=0;i<n;i++){for(j=0;j<120;j++);}
}void key_scan()
{unsigned char temp0=0,temp1=0,temp=0;P1=0xf0;if(P1!=0xf0) //检测按键是否被按下{delay(20);temp0=P1;P1=0x0f;if(P1!=0x0f);{temp1=P1;}}temp=temp0+temp1;if(temp==0xEE){num=0;}if(temp==0xED){num=1;}if(temp==0xEB){num=2;}if(temp==0xE7){num=3;}if(temp==0xDE){num=4;}if(temp==0xDD){num=5;}if(temp==0xDB){num=6;}if(temp==0xD7){num=7;}if(temp==0xBE){num=8;}if(temp==0xBD){num=9;}if(temp==0xBB){num=10;}if(temp==0xB7){num=11;}if(temp==0x7E){num=12;}if(temp==0x7D){num=13;}if(temp==0x7B){num=14;}if(temp==0x77){num=15;}
}void display()
{P2=s[num];
}void main()
{while(1){key_scan();display();}
}

 这个代码冗余很高,if判断很多,明白逻辑即可。(仿真启动时间较长)

代码解释

在代码中,temp 的值是通过将 temp0 和 temp1 相加得到的。具体来说:

  1. temp0 的获取

    • 将 P1 端口的高 4 位设置为高电平(P1 = 0xF0)。
    • 如果有按键按下,P1 的值会改变,此时读取 P1 的值并存储到 temp0 中。
  2. temp1 的获取

    • 将 P1 端口的低 4 位设置为高电平(P1 = 0x0F)。
    • 再次读取 P1 的值并存储到 temp1 中。
  3. temp 的计算

    • temp = temp0 + temp1

按键矩阵的常见设计

在按键矩阵中,通常会有 4 行和 4 列,共 16 个按键。每个按键的位置可以通过行和列的交叉点来确定。假设按键矩阵的设计如下:

  • P1.4 到 P1.7(高 4 位)
  • P1.0 到 P1.3(低 4 位)

当某个按键被按下时,P1 的值会反映出行和列的状态。 

按键位置temp0(高 4 位)temp1(低 4 位)temp = temp0 + temp1
第 1 行第 1 列0xE00x0E0xEE
第 1 行第 2 列0xE00x0D0xED
第 1 行第 3 列0xE00x0B0xEB
第 1 行第 4 列0xE00x070xE7
第 2 行第 1 列0xD00x0E0xDE
第 2 行第 2 列0xD00x0D0xDD
第 2 行第 3 列0xD00x0B0xDB
第 2 行第 4 列0xD00x070xD7
第 3 行第 1 列0xB00x0E0xBE
第 3 行第 2 列0xB00x0D0xBD
第 3 行第 3 列0xB00x0B0xBB
第 3 行第 4 列0xB00x070xB7
第 4 行第 1 列0x700x0E0x7E
第 4 行第 2 列0x700x0D0x7D
第 4 行第 3 列0x700x0B0x7B
第 4 行第 4 列0x700x070x77

表2.4.1 temp值计算 

 仿真视频:

矩阵键盘(简易版)

 

 

相关文章:

  • Linux工具学习之【gcc/g++】
  • 二月公开赛 宝塔搭建Web-ssrfme环境以及漏洞复现
  • 认知,信息技术
  • CSS伪元素
  • C++ 网络层接口设计与实现:基于 Socket 编程
  • IE之路专题11.IS-IS专题
  • 第五章、SpringBoot与消息通信(一)
  • 【Spring Boot】把jar包导入本地系统
  • Java学习手册:Java并发编程最佳实践
  • 代码学习总结(五)
  • spring中如何在一个插入操作执行成功后在执行另一个操作
  • Word 中“母版页”的等效机制
  • pip list | grep paho-mqtt 如何查看这个包的保存路径
  • C++学习:六个月从基础到就业——面向对象编程:接口设计
  • 新手避坑+高效入门:用 DeepSeek 从零攻克编程与网站搭建
  • Docker容器虚拟化存储架构
  • 数据结构之稀疏矩阵与三元组表示法
  • 树莓派超全系列教程文档--(31)config.txt常用选项介绍
  • 游戏一:俄罗斯方块简易版
  • vue3+element-ui-plus+el-table样式
  • 著名电化学家、我国工业电化学奠基人之一郭鹤桐逝世
  • 特朗普亲自介入美日关税谈判:以势压人还是给对手“送助攻”
  • 从南宋遗韵到海派风情,解码江南服饰美学基因
  • 北京理工大学解除宫某聘用关系,该教师被指涉嫌骚扰猥亵学生
  • 张宝亮任山东临沂市委书记
  • “走进电影”:虚拟现实电影产业有新进展