更多单片机学习笔记:
单片机学习笔记 1. 点亮一个LED灯
单片机学习笔记 2. LED灯闪烁
单片机学习笔记 3. LED灯流水灯
单片机学习笔记 4. 蜂鸣器滴~滴~滴~
单片机学习笔记 5. 数码管静态显示
单片机学习笔记 6. 数码管动态显示
单片机学习笔记 7. 独立键盘


目录

0、实现的功能

1、Keil工程

1-1 矩阵键盘识别方法

1-2 swich语句

2、代码实现


0、实现的功能

        4*4矩阵键盘+独立键盘的按键检测,可拓展为四管显示

1、Keil工程

1-1 矩阵键盘识别方法

        主要采用列扫描(1111 0000)和行扫描(0000 1111)的方法。

        列扫描的初始操作是输入P3口为0xF0,当S6被按下时,P34由1会变为0,此时P3口为0xE0;同理,S10被按下时,P3也为0xE0。所以第一列被按下时,P3为1110 0000;第二列被按下时,P3为1101 0000;第三列被按下时,P3为1011 0000;第四列被按下时,P3为0111 0000。
所以P30--P33为行线,P34--P37为列线

        再做行扫描,P3初始为0x0F。当S6被按下时,P30会从1变为0,P3为0000 1110.最后再和列扫描的结果相加:1110 0000 + 0000 1110 = 1110 1110,得到确切的位置(第一列,第一行)

        所以P3的数据中,前四位为哪一列,后四位为哪一行。谁为0就是哪一行列

1-2 swich语句

        主要涉及到c语言中的switch语句

2、代码实现

        显示的按键序号和对应显示数字表如下: 
​       
        只要是涉及到按键的,都要进行软件消抖+松手检测。赋值P3=0xf0进行列扫描,找到是哪一列,KeyValue可以直接为0 1 2 3------赋值P3=0x0f进行行扫描,每行之间相差4,此时KeyValue对应的+4即可
        独立按键扫描的话,赋值P3=0xff,这样就不是列扫描和行扫描了。按下哪个,哪一位就为0,找到对应的显示数字即可

代码实现:

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

sbit WE = P2^7; //锁存器位选,U8的LE,选择哪个数码管
sbit DU = P2^6; //锁存器段选,U9的LE,控制亮什么数字

uchar KeyValue = 6;		//按键显示值

//共阴极数码管段选表0-9
uchar code table1[] = {
//0		1	  2		3	  4		5	  6		7	  8	
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 
//9		A	  B		C	  D		E	  F		H	  L
0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x76, 0x38,
//n		u	  -		熄灭
0x37, 0x3e, 0x40, 0x00} ;

//延时模块
void delay(uint z)
{
	uint x;
	uint y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0; y--);
}

void KeyScan()
{
	//4*4矩阵键盘扫描
	P3 = 0xf0;		//列扫描初始化
	if(P3 != 0xf0)		//判断按键是否被按下
	{
		delay(10);		//软件消抖10ms
		if(P3 != 0xf0)	//再判断是否真正被按下,有可能是误触
		{
			 switch(P3)		//判断哪一列被按下
			 {
			 	case 0xe0:	KeyValue = 0; break;	//第一列
				case 0xd0:	KeyValue = 1; break;	//第二列
				case 0xb0:	KeyValue = 2; break;	//第三列
				case 0x70:	KeyValue = 3; break;	//第四列
			 }

			 P3 = 0x0f;		//行扫描初始化
			 switch(P3)		//判断哪一行被按下
			 {
			 	case 0x0e:	KeyValue = KeyValue; break;	//第一行
				case 0x0d:	KeyValue = KeyValue + 4; break;	//第二行
				case 0x0b:	KeyValue = KeyValue + 8; break;	//第三行
				case 0x07:	KeyValue = KeyValue + 12; break;	//第四行
			 }
			 while(P3 != 0x0f);		//松手检测
		}
	}

	//独立按键扫描
	P3 = 0xff;
	if(P3 != 0xff)
	{
		delay(10);		//软件消抖10ms
		if(P3 != 0xff)
		{
			 switch(P3)		//判断哪一行被按下
			 {
			 	case 0xfe:	KeyValue = 16; break;	//S2
				case 0xfd:	KeyValue = 17; break;	//S3
				case 0xfb:	KeyValue = 18; break;	//S4
				case 0xf7:	KeyValue = 19; break;	//S5
			 }
			 while(P3 != 0xff);		//松手检测		
		}
	}
}

void main()
{
	//指定第一个数码管,不用放在循环里
	P0 = 0xff;//清除断码,让位锁存器哪个都不选
	WE = 1;//位选锁存打开
	P0 = 0xfe;//选第一个管
	WE = 0;	//进入锁存
	while(1)
	{
		KeyScan();		//20个按键扫描
		DU = 1;//段选锁存打开
		P0 = table1[KeyValue];
		DU = 0;//进入锁存
	}	
}

        可以结合数码管动态显示,弄点好玩的
 

#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

sbit WE = P2^7; //锁存器位选,U8的LE,选择哪个数码管
sbit DU = P2^6; //锁存器段选,U9的LE,控制亮什么数字

uchar KeyValue = 6;		//按键显示值

//共阴极数码管段选表0-9
uchar code table1[] = {
//0		1	  2		3	  4		5	  6		7	  8	
0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 
//9		A	  B		C	  D		E	  F		H	  K
0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71, 0x76, 0x76,
//n		u	  -	  熄灭
0x37, 0x3e, 0x40, 0x00} ;

//延时模块
void delay(uint z)
{
	uint x;
	uint y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0; y--);
}

void KeyScan()
{
	//4*4矩阵键盘扫描
	P3 = 0xf0;		//列扫描初始化
	if(P3 != 0xf0)		//判断按键是否被按下
	{
		delay(10);		//软件消抖10ms
		if(P3 != 0xf0)	//再判断是否真正被按下,有可能是误触
		{
			 switch(P3)		//判断哪一列被按下
			 {
			 	case 0xe0:	KeyValue = 0; break;	//第一列
				case 0xd0:	KeyValue = 1; break;	//第二列
				case 0xb0:	KeyValue = 2; break;	//第三列
				case 0x70:	KeyValue = 3; break;	//第四列
			 }

			 P3 = 0x0f;		//行扫描初始化
			 switch(P3)		//判断哪一行被按下
			 {
			 	case 0x0e:	KeyValue = KeyValue; break;	//第一行
				case 0x0d:	KeyValue = KeyValue + 4; break;	//第二行
				case 0x0b:	KeyValue = KeyValue + 8; break;	//第三行
				case 0x07:	KeyValue = KeyValue + 12; break;	//第四行
			 }
			 while(P3 != 0x0f);		//松手检测
		}
	}

	//独立按键扫描
	P3 = 0xff;
	if(P3 != 0xff)
	{
		delay(10);		//软件消抖10ms
		if(P3 != 0xff)
		{
			 switch(P3)		//判断哪一行被按下
			 {
			 	case 0xfe:	KeyValue = 16; break;	//S2
				case 0xfd:	KeyValue = 17; break;	//S3
				case 0xfb:	KeyValue = 18; break;	//S4
				case 0xf7:	KeyValue = 19; break;	//S5
			 }
			 while(P3 != 0xff);		//松手检测		
		}
	}
}


void main()
{
	while(1)
	{
		KeyScan();		//20个按键扫描

		P0 = 0xff;//清除断码,让位锁存器哪个都不选
		WE = 1;//位选锁存打开
		P0 = 0xfe;//选第一个管
		WE = 0;	//进入锁存
		

		DU = 1;//段选锁存打开
		P0 = table1[KeyValue];
		DU = 0;//进入锁存
		delay(5);

		P0 = 0xff;//清除断码,让位锁存器哪个都不选
		WE = 1;//位选锁存打开
		P0 = 0xfd;//选第2个管
		WE = 0;	//进入锁存

		DU = 1;//段选锁存打开
		P0 = table1[KeyValue+4];
		DU = 0;//进入锁存
		delay(5);

		P0 = 0xff;//清除断码,让位锁存器哪个都不选
		WE = 1;//位选锁存打开
		P0 = 0xfb;//选第3个管
		WE = 0;	//进入锁存

		DU = 1;//段选锁存打开
		P0 = table1[KeyValue-3];
		DU = 0;//进入锁存
		delay(5);

		P0 = 0xff;//清除断码,让位锁存器哪个都不选
		WE = 1;//位选锁存打开
		P0 = 0xf7;//选第4个管
		WE = 0;	//进入锁存

		DU = 1;//段选锁存打开
		P0 = table1[KeyValue+2];
		DU = 0;//进入锁存
		delay(5);
	}	
}

实物展示: 

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部