STC89C52单片机 独立键盘

STC89C52单片机 独立键盘独立键盘键盘介绍键盘是电子系统中人机对话的重要组成部分,是人向机器发出指令、输入信息的必须设备键盘在单片机应用系统中是使用最广泛的一种数据输入设备。键盘是由多个按键组成的。按键的工作原理按键通常是一种常开型开关,常态下按键的两个触点处于断开状态,按下按键时它们才闭合。以下是轻触开关和轻触按键图键盘类型通常键盘有编码键盘和非编码键盘两种。编码键盘通过硬件电路产生被按按键的键值码,这种键盘使用方便,所需程序简单,但硬件电路复杂,如计算机的键盘,单片机则通常不采用编码键盘。而软件编程来识

独立键盘

键盘介绍

键盘是电子系统中人机对话的重要组成部分,是人向机器发出指令、输入信息的必须设备

键盘在单片机应用系统中是使用最广泛的一种数据输入设备。键盘是由多个按键组成的。

按键的工作原理

按键通常是一种常开型开关,常态下按键的两个触点处于断开状态,按下按键时它们才闭合。
以下是 轻触开关和轻触按键 图
(img/touch_switch.png)]

键盘类型

通常键盘有编码键盘和非编码键盘两种。编码键盘通过硬件电路产生被按按键的键值码,这种键盘使用方便,所需程序简单,但硬件电路复杂,
如计算机的键盘,单片机则通常不采用编码键盘。

而软件编程来识别的称为非编码键盘,非编码键盘硬件电路简单。

在单片机组成的各种系统中,最常用的是非编码键盘。

独立键盘与矩阵键盘的特点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AbUzy3WA-1605375466054)(img/keyboard.png)]

非编码键盘分为独立键盘和矩阵键盘。
独立键盘特点:每个按键占用一个IO口,当按键数量较多时,IO口利用效率不高,但程序简单,适用于所需按键较少的场合。
矩阵键盘特点:电路连接复杂,但提高了IO口利用率,软件编程较复杂。适用于使用大量按键的场合。

相关原理图分析

在这里插入图片描述

按键一端与IO口连接,另外一端接地。通过控制IO口输出高电平即可检测按键是否按下,当按下时IO口会被拉低,松开后IO口回到高电平。

按键特性

机械按键在按下或松开时会存在抖动现象。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AmHQOBR9-1605375466061)(img/the_key_features.png)]

使用独立按键 S2 控制灯 LED1 亮灭;
#include <reg52.h>
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选
sbit key_s2 = P3^0;//独立按键S2
uchar num;//数码管显示的值
uchar count;

//共阴数码管段选表0-9
uchar  code tabel[]= { 
   0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};

//毫秒级延时函数定义
void delay(uint z){ 
   
	uint x,y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0 ; y--); 		
} 

void main()//main函数自身会循环
{ 
   
	while(1)
	{ 
   
		if(key_s2 == 0)//判断S2是否被按下
		{ 
   
			delay(20);//按键消抖
			if(key_s2 == 0)
			{ 
   
				if( count == 0){ 
     // 当 count = 0 的时候 点亮LED1灯
					P1 = 0XFE; // 点亮 LED1 灯
					count = 1; 
				}else if(count == 1){ 
      // 当 count = 1 的时候 关闭LED1灯
					P1 = 0xff;  // 关闭所有的LED 灯 
					count = 0;  	
				}
			}
				while(!key_s2);//松手检测
		}
	}	
}  
独立按键 S2 控制流水灯亮灭。
#include <reg52.h>
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选
sbit key_s2 = P3^0;//独立按键S2
sbit key_s3 = P3^1;//独立按键S3
uchar num;//数码管显示的值
uchar count;
uchar temp; // LED灯相关变量

//共阴数码管段选表0-9
uchar  code tabel[]= { 
   0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};


//毫秒级延时函数定义
void delay(uint z)
{ 
   
	uint x,y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0 ; y--); 		
} 

void main() { 
   //main函数自身会循环


	if(count == 0){ 
   
		temp = 0xfe;
		P1 = temp;  // 1111 1110
		delay(100);
	} else if(count == 1) { 
   
		P1 = 0xff;
	}


	while(1){ 
   
		
	if(count == 0){ 
   
	  	temp = _crol_(temp, 1);   // 循环左移
		P1 = temp;
		delay(100);
	} else if(count == 1) { 
   
		P1 = 0xff;
	}

	if(key_s2 == 0){ 
   //判断S2是否被按下
		
		delay(20);//按键消抖
		if(key_s2 == 0){ 
   
			if( count == 0){ 
   
				delay(100);	 // 延时 100毫秒 通过增加延时的时间或减少延时的时间,来控制流水灯的速度 
				count = 1;
			}else if(count == 1){ 
   
				P1 = 0xff;  // 关闭所有的LED 灯 
				count = 0;  	
			}
		}

	}
			while(!key_s2);//松手检测 
	}
}	

每次按动按键 S3,控制数码管显示数字加 1,当数码管数字变为 10 时, 按动按键 S3,会让数码管重新变为 00。

方法一:

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

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选
sbit key_s2 = P3^0;//独立按键S2
sbit key_s3 = P3^1;//独立按键S3
sbit key_s4 = P3^2;//独立按键S2
uchar num1 = 0, num2 = 0;//数码管显示的值
uchar count = 0;

//共阴数码管段选表0-9
uchar  code tabel[]= { 
   0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};


//毫秒级延时函数定义
void delay(uint z)
{ 
   
	uint x,y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0 ; y--); 		
} 


/*==================================== 描述 :两位共阴数码管动态显示 ====================================*/
void display(uchar num1, uchar num2)
{ 
   
												
	/*第一位显示*/ 		
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFE; //1111 1110
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num1];//
	DU = 0;//锁存段选数据
	delay(1);

	/*第二位显示*/
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFD; //1111 1101
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num2];//
	DU = 0;//锁存段选数据
	delay(1);
	
}

void main()//main函数自身会循环
{ 
   
	display(num1, num2); //数码管显示函数
	
	while(1)
	{ 
   
		if(key_s3 == 0)//判断S2是否被按下
		{ 
   
			delay(20);//按键消抖
			if(key_s3 == 0)
			{ 
   
				num2++; 
				if(num2 == 10){ 
   
					num1 = 1;
					num2 = 0;
					count++;
				} else if(count == 1){ 
   
					num1 = 0;
					num2 = 0;
					count = 0;
					display(num1, num2);
				}
				while(!key_s3);//松手检测 
			}	
		}
	   display(num1, num2); 
	}	
}  

方法二:

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

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选

sbit key_s3 = P3^1;//独立按键S3

uchar display_num = 0; // 对数码管显示的数值初始化
uchar num1 = 0, num2 = 0;//数码管显示的值

//共阴数码管段选表0-9
uchar  code tabel[]= { 
   0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};


//毫秒级延时函数定义
void delay(uint z)
{ 
   
	uint x,y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0 ; y--); 		
} 


/*==================================== 描述 :两位共阴数码管动态显示 ====================================*/
void display(uchar num1, uchar num2)
{ 
   
												
	/*第一位显示*/ 		
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFE; //1111 1110
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num1];//
	DU = 0;//锁存段选数据
	delay(1);

	/*第二位显示*/
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFD; //1111 1101
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num2];//
	DU = 0;//锁存段选数据
	delay(1);
	
}

void main()//main函数自身会循环
{ 
   
	display(num1, num2); //数码管显示函数
	
	while(1)
	{ 
   
		if(key_s3 == 0)//判断S2是否被按下
		{ 
   
			display_num++;	 // 每按一次独立按键,数码管显示的值加 1
			delay(20);//按键消抖
			if(key_s3 == 0)
			{ 
   
				switch(display_num){ 
   	// 通过 switch case 语句对 数码管的数值进行精准的管理
				    case 0 :
				       num1 = 0;
					   num2 = 0;
				       break; 
				    case 1 :
				       num1 = 0;
					   num2 = 1;
				       break;
					case 2 :
				       num1 = 0;
					   num2 = 2;
				       break;
					case 3 :
				       num1 = 0;
					   num2 = 3;
				       break;
					case 4 :
				       num1 = 0;
					   num2 = 4;
				       break;
					case 5 :
				       num1 = 0;
					   num2 = 5;
				       break;
					case 6 :
				       num1 = 0;
					   num2 = 6;
				       break;   
					case 7 :
				       num1 = 0;
					   num2 = 7;
				       break; 
					case 8 :
				       num1 = 0;
					   num2 = 8;
				       break;
					case 9 :
				       num1 = 0;
					   num2 = 9;
				       break;
					case 10 :
				       num1 = 1;
					   num2 = 0;
				       break;
					default : // 当display_num数值大于10的时候,display_num 重新赋值0,不能使 display_num 大于 10
						display_num = 0;
						num1 = 0;
					   	num2 = 0;      
				}
				while(!key_s3);//松手检测 
			}	
		}

	   display(num1, num2); 
	}	
}  

每次按动按键 S4,控制数码管显示数字减 1,当数码管数字变为 00 时, 按动按键 S4,会让数码管重新变为 10。

方法一:

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

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选
sbit key_s2 = P3^0;//独立按键S2
sbit key_s3 = P3^1;//独立按键S3
sbit key_s4 = P3^2;//独立按键S2
uchar num1 = 0, num2 = 0;//数码管显示的值
uchar count = 0;

//共阴数码管段选表0-9
uchar  code tabel[]= { 
   0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};


//毫秒级延时函数定义
void delay(uint z)
{ 
   
	uint x,y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0 ; y--); 		
} 


/*==================================== 描述 :两位共阴数码管动态显示 ====================================*/
void display(uchar num1, uchar num2)
{ 
   
												
	/*第一位显示*/ 		
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFE; //1111 1110
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num1];//
	DU = 0;//锁存段选数据
	delay(1);

	/*第二位显示*/
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFD; //1111 1101
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num2];//
	DU = 0;//锁存段选数据
	delay(1);
	
}

void main()//main函数自身会循环
{ 
   
	display(num1, num2); //数码管显示函数
	
	while(1)
	{ 
   
		if(key_s4 == 0)//判断S2是否被按下
		{ 
   
			delay(20);//按键消抖
			if(key_s4 == 0)
			{ 
   
				if(count == 0){ 
   
					num1 = 1;
					num2 = 0;
					count++;
				} else if(count == 1){ 
   					
					num1 = 0;
					num2 = 9;
					count++;
				} else if(count < 11){ 
   
					num2--;
					count++;
				} else { 
   
					count = 0;
				}

				if(count == 0){ 
   
					num1 = 1;
					num2 = 0;
					count++;
				} 
				while(!key_s4);//松手检测 
			}	
		}
	   display(num1, num2); 
	}	
} 

方法二:

/********************************************************************************* * 【作 者】: vvcat * 【版 本】: V1.0 * 【外部晶振】: 11.0592mhz * 【主控芯片】: STC89C52 * 【编译环境】: Keil μVisio4 * 【程序功能】: 独立按键识别 * 【使用说明】: 每次按动按键 S4,控制数码管显示数字减 1,当数码管数字变为 00 时, 按动按键 S4,会让数码管重新变为 10。 **********************************************************************************/
#include <reg52.h>
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选
sbit key_s4 = P3^2;//独立按键S4
uchar display_num = 0; // 对数码管显示的数值初始化
uchar num1 = 0, num2 = 0;//数码管显示的值

//共阴数码管段选表0-9
uchar  code tabel[]= { 
   0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};


//毫秒级延时函数定义
void delay(uint z)
{ 
   
	uint x,y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0 ; y--); 		
} 


/*==================================== 描述 :两位共阴数码管动态显示 ====================================*/
void display(uchar num1, uchar num2)
{ 
   
												
	/*第一位显示*/ 		
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFE; //1111 1110
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num1];//
	DU = 0;//锁存段选数据
	delay(1);

	/*第二位显示*/
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFD; //1111 1101
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num2];//
	DU = 0;//锁存段选数据
	delay(1);
	
}

void main()//main函数自身会循环
{ 
   
	display(num1, num2); //数码管显示函数
	
	while(1)
	{ 
   
		if(key_s4 == 0)//判断S4是否被按下
		{ 
   
			display_num--; // 每按一次独立按键,数码管显示的值减去1
			delay(20);//按键消抖
			if(key_s4 == 0)
			{ 
   
				switch(display_num){ 
      // 通过 switch case 语句对 数码管的数值进行精准的管理
				    case 0 :
				       num1 = 0;
					   num2 = 0;
				       break; 
				    case 1 :
				       num1 = 0;
					   num2 = 1;
				       break;
					case 2 :
				       num1 = 0;
					   num2 = 2;
				       break;
					case 3 :
				       num1 = 0;
					   num2 = 3;
				       break;
					case 4 :
				       num1 = 0;
					   num2 = 4;
				       break;
					case 5 :
				       num1 = 0;
					   num2 = 5;
				       break;
					case 6 :
				       num1 = 0;
					   num2 = 6;
				       break;   
					case 7 :
				       num1 = 0;
					   num2 = 7;
				       break; 
					case 8 :
				       num1 = 0;
					   num2 = 8;
				       break;
					case 9 :
				       num1 = 0;
					   num2 = 9;
				       break;
					case 10 :
				       num1 = 1;
					   num2 = 0;
				       break;
					default : // 当display_num数值小于0的时候,display_num 重新赋值10,不能使 display_num 变为负数
						display_num = 10;
						num1 = 1;
					   	num2 = 0;      
				}
				while(!key_s4);//松手检测 
			}	
		}

	   display(num1, num2); 
	}	
} 

每次按动按键 S5,可以让数码管复位为 0.0.。
/********************************************************************************* * 【作 者】: vvcat * 【版 本】: V1.0 * 【外部晶振】: 11.0592mhz * 【主控芯片】: STC89C52 * 【编译环境】: Keil μVisio4 * 【程序功能】: 独立按键识别 * 【使用说明】: 按下开发板左下角S3按键数码管值+1,最大到10 按下S4按下,值减一,最小减到0 按下s5复位 **********************************************************************************/
#include <reg52.h>
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char

sbit DU = P2^6;//数码管段选
sbit WE = P2^7;//数码管段选

sbit key_s3 = P3^1;//独立按键S3
sbit key_s4 = P3^2;//独立按键S4
sbit key_s5 = P3^3;//独立按键S5
uchar num1 = 0, num2 = 0;//数码管显示的值
uchar count = 0;
uchar count2 = 0;

//共阴数码管段选表0-9
uchar  code tabel[]= { 
   0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};


//毫秒级延时函数定义
void delay(uint z)
{ 
   
	uint x,y;
	for(x = z; x > 0; x--)
		for(y = 114; y > 0 ; y--); 		
} 


/*==================================== 描述 :两位共阴数码管动态显示 ====================================*/
void display(uchar num1, uchar num2){ 
   
												
	/*第一位显示*/ 		
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFE; //1111 1110
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num1];//
	DU = 0;//锁存段选数据
	delay(2);

	/*第二位显示*/
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFD; //1111 1101
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = tabel[num2];//
	DU = 0;//锁存段选数据
	delay(2);
	
}

/*==================================== 描述 :两位共阴数码管复位函数显示 0.0. ====================================*/
void restoration(){ 
   
	/*第一位显示*/ 		
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFE; //1111 1110
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = 0XBF;// 1011 1111
	DU = 0;//锁存段选数据
	delay(2);

	/*第二位显示*/
	P0 = 0XFF;//清除断码
	WE = 1;//打开位选锁存器
	P0 = 0XFD; //1111 1101
	WE = 0;//锁存位选数据
	
	DU = 1;//打开段选锁存器
	P0 = 0XBF;// 1011 1111
	DU = 0;//锁存段选数据
	delay(2);
		
}


void main()//main函数自身会循环
{ 
   
	
	while(1){ 
   
		if(count2 == 1){ 
   
			restoration();
		}else if(count2 == 0){ 
   
		  display(num1, num2); //数码管显示函数
		}

		if(key_s3 == 0)//判断S2是否被按下
		{ 
   
			count2 = 0; // 目的是为了调用 display(num1, num2); 数码管显示函数
			count++;	 
			delay(20);//按键消抖
			switch(count){ 
   	// 通过 switch case 语句对 数码管的数值进行精准的管理
			    case 0 :
			       num1 = 0;
				   num2 = 0;
			       break; 
			    case 1 :
			       num1 = 0;
				   num2 = 1;
			       break;
				case 2 :
			       num1 = 0;
				   num2 = 2;
			       break;
				case 3 :
			       num1 = 0;
				   num2 = 3;
			       break;
				case 4 :
			       num1 = 0;
				   num2 = 4;
			       break;
				case 5 :
			       num1 = 0;
				   num2 = 5;
			       break;
				case 6 :
			       num1 = 0;
				   num2 = 6;
			       break;   
				case 7 :
			       num1 = 0;
				   num2 = 7;
			       break; 
				case 8 :
			       num1 = 0;
				   num2 = 8;
			       break;
				case 9 :
			       num1 = 0;
				   num2 = 9;
			       break;
				case 10 :
			       num1 = 1;
				   num2 = 0;
			       break;
				default : // 当count数值大于10的时候,count 重新赋值0,不能使count 大于 10
					count = 0;
					num1 = 0;
				   	num2 = 0;      
			}
			while(!key_s3);//松手检测 
			display(num1, num2); // 调用函数显示数值
		 
		  }

		if(key_s4 == 0)//判断S4是否被按下
		{ 
   
			count2 = 0;	   // 目的是为了调用 display(num1, num2); 数码管显示函数
			count--;  // 每次按下 独立按键S4 数码管数值减一 
			delay(20);//按键消抖
			if(key_s4 == 0)
			{ 
   
				switch(count){ 
   
			    case 0 :
			       num1 = 0;
				   num2 = 0;
			       break; 
			    case 1 :
			       num1 = 0;
				   num2 = 1;
			       break;
				case 2 :
			       num1 = 0;
				   num2 = 2;
			       break;
				case 3 :
			       num1 = 0;
				   num2 = 3;
			       break;
				case 4 :
			       num1 = 0;
				   num2 = 4;
			       break;
				case 5 :
			       num1 = 0;
				   num2 = 5;
			       break;
				case 6 :
			       num1 = 0;
				   num2 = 6;
			       break;   
				case 7 :
			       num1 = 0;
				   num2 = 7;
			       break; 
				case 8 :
			       num1 = 0;
				   num2 = 8;
			       break;
				case 9 :
			       num1 = 0;
				   num2 = 9;
			       break;
				case 10 :
			       num1 = 1;
				   num2 = 0;
			       break;
				default : // 当count数值小于0的时候,count 重新赋值10,不能使count 变为负数
					count = 10;
					num1 = 1;
				   	num2 = 0;      
			}

				while(!key_s4);//松手检测
				display(num1, num2); 
			}	
		}

		if(key_s5 == 0)//判断S3是否被按下
		{ 
   
			delay(20);//按键消抖
			if(key_s5 == 0)
			{ 
   
				count = 0;	// 按下后count 初始化为0,数码管的值会从0开始重新计数
				count2 = 1;	 // 目的是为了调用 restoration 数码管显示函数 显示0.0.
				num1 = 0;   // 将数码管第一位的值初始化为0
				num2 = 0;  // 将数码管第二位的值初始化为0
				
				while(!key_s5);  // s5松手检测
				restoration();	// 目的是为了调用 restoration 数码管显示函数 
			}	
		}
	}	
}  

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/38902.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注