51单片机练习:独立键盘篇

题目:

用数码管的前两位显示一个十进制数,变化范围为00~59,开始时显示00,每按下S2键一次,数值加1;每按下S3键一次,数值减1;每按下S4键一次,数值归零;按下S5键一次,利用定时器功能使数值开始自动每秒加1,再次按下S5键,数值停止自动加1,保持显示原数。(来自郭天祥老师的51单片机练习)

代码:

初始化函数:

void Init()
{
	LE = 0;//锁住led灯,防止实验过程中灯亮
	
	WLE = 1;//打开位选
	P0 = 0xfc;
	WLE = 0;//关闭位选
	P0 = 0xff;//消影
	DLE = 1;//打开段选
	P0 = Table[0];
	DLE = 0;//关闭段选
	delay_1ms(10);
	
	TMOD = 0x01;//定时器工作类型
	TH0 = (65536 - 45872) / 256;//50ms
	TL0 = (65536 - 45872) % 256;
	EA = 1;//总中断
	ET0 = 1;//T0中断
	TR0 = 0;//开启T0
	
	num = 0;
	tt = 0;
}

1ms延时函数:

//延时1ms函数
void delay_1ms(uint z)
{
	uint x,y;
	for(x = z;x > 0;x--)
	{
		for(y =110;y > 0;y--){}
	}
}

四个独立按键函数:

//按键2函数
void Switch2()
{
	while(SW2 == 0)
	{
		delay_1ms(10);//消抖
		if(SW2 == 0)
		{
			num++;//加1
		}
		while(SW2 == 0);//等待按键释放
	}
}

//按键3函数
void Switch3()
{
	while(SW3 == 0)
	{
		delay_1ms(10);//消抖
		if(SW3 == 0)
		{
			if(num == 0)
			{
				num = 59;
			}
			else
			{
				num--;//减1
			}
		}
		while(SW3 == 0);//等待按键释放
	}
}

//按键4函数
void Switch4()
{
	while(SW4 == 0)
	{
		delay_1ms(10);//消抖
		if(SW4 == 0)
		{
			num = 0;//归零
		}
		while(SW4 == 0);//等待按键释放
	}
}

//按键5函数
void Switch5()
{
	while(SW5 == 0)
	{
		delay_1ms(10);//消抖
		if(SW5 == 0)
		{
			if(TR0 == 0)
			{
				TR0 = 1;
			}
			else
			{
				TH0 = (65536 - 45872) / 256;//50ms
				TL0 = (65536 - 45872) % 256;
				TR0 = 0;
			}
		}
		while(SW5 == 0);//等待按键释放
	}
}

数码管显示函数:

//数码管显示函数
void display()
{
	uint ge,shi;
	//定时1s
	if(tt == 20)
	{
		tt = 0;
		num++;
	}
	//计算每秒个位与十位的变化
	if(num == 60)
	{
		num = 0;
		
	}
	shi = num / 10;//十位
	ge = num % 10;//个位
	
	//显示十位
	WLE = 1;
	P0 = 0xfe;
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[shi];
	DLE = 0;
	delay_1ms(5);//延时短,达到动态扫描的效果
	
	//显示个位
	WLE = 1;
	P0 = 0xfd;
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[ge];
	DLE = 0;
	delay_1ms(5);//延时短,达到动态扫描的效果
} 

定时器T0中断函数:

void Timer0() interrupt 1
{
	TH0 = (65536 - 45872) / 256;//50ms
	TL0 = (65536 - 45872) % 256;
	tt++;
}

整个项目代码:

#include 

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

#define uint unsigned int
#define uchar unsigned char
sbit SW2 = P3^4;//S2键
sbit SW3 = P3^5;//S3键
sbit SW4 = P3^6;//S4键
sbit SW5 = P3^7;//S5键
sbit WLE = P2^7;//位选
sbit DLE = P2^6;//段选
sbit LE = P2^5;//led灯的锁存器
//数码管的编码表
uchar code Table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uint num,tt;

void Init();
void delay_1ms(uint z);
void Switch2();//也可以将四个按键都写在一个函数里面
void Switch3();
void Switch4();
void Switch5();
void display();

void main()
{
	Init();
	while(1)
	{
		Switch2();
		Switch3();
		Switch4();
		Switch5();
		display();
	}
}

void Init()
{
	LE = 0;//锁住led灯,防止实验过程中灯亮
	
	WLE = 1;//打开位选
	P0 = 0xfc;
	WLE = 0;//关闭位选
	P0 = 0xff;//消影
	DLE = 1;//打开段选
	P0 = Table[0];
	DLE = 0;//关闭段选
	delay_1ms(10);
	
	TMOD = 0x01;//定时器工作类型
	TH0 = (65536 - 45872) / 256;//50ms
	TL0 = (65536 - 45872) % 256;
	EA = 1;//总中断
	ET0 = 1;//T0中断
	TR0 = 0;//开启T0
	
	num = 0;
	tt = 0;
}

//延时1ms函数
void delay_1ms(uint z)
{
	uint x,y;
	for(x = z;x > 0;x--)
	{
		for(y =110;y > 0;y--){}
	}
}

//按键2函数
void Switch2()
{
	while(SW2 == 0)
	{
		delay_1ms(10);//消抖
		if(SW2 == 0)
		{
			num++;//加1
		}
		while(SW2 == 0);//等待按键释放
	}
}

//按键3函数
void Switch3()
{
	while(SW3 == 0)
	{
		delay_1ms(10);//消抖
		if(SW3 == 0)
		{
			if(num == 0)
			{
				num = 59;
			}
			else
			{
				num--;//减1
			}
		}
		while(SW3 == 0);//等待按键释放
	}
}

//按键4函数
void Switch4()
{
	while(SW4 == 0)
	{
		delay_1ms(10);//消抖
		if(SW4 == 0)
		{
			num = 0;//归零
		}
		while(SW4 == 0);//等待按键释放
	}
}

//按键5函数
void Switch5()
{
	while(SW5 == 0)
	{
		delay_1ms(10);//消抖
		if(SW5 == 0)
		{
			if(TR0 == 0)
			{
				TR0 = 1;
			}
			else
			{
				TH0 = (65536 - 45872) / 256;//50ms
				TL0 = (65536 - 45872) % 256;
				TR0 = 0;
			}
		}
		while(SW5 == 0);//等待按键释放
	}
}

//数码管显示函数
void display()
{
	uint ge,shi;
	//定时1s
	if(tt == 20)
	{
		tt = 0;
		num++;
	}
	//计算每秒个位与十位的变化
	if(num == 60)
	{
		num = 0;
		
	}
	shi = num / 10;//十位
	ge = num % 10;//个位
	
	//显示十位
	WLE = 1;
	P0 = 0xfe;
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[shi];
	DLE = 0;
	delay_1ms(5);//延时短,达到动态扫描的效果
	
	//显示个位
	WLE = 1;
	P0 = 0xfd;
	WLE = 0;
	P0 = 0xff;//消影
	DLE = 1;
	P0 = Table[ge];
	DLE = 0;
	delay_1ms(5);//延时短,达到动态扫描的效果
} 

void Timer0() interrupt 1
{
	TH0 = (65536 - 45872) / 256;//50ms
	TL0 = (65536 - 45872) % 256;
	tt++;
}

心得/经验记录:

1.按键的代码编写过程中,要注意“消抖”(消除人在按动按键的过程中的抖动),这个过程大概延时10ms即可;

2.按键在按下去和释放的瞬间都会有抖动,但是实际过程中,只需要在按下去的时候消抖即可,释放时可以不用消抖;

3.在处理按键按下去的那段代码时,要注意加一个“等待释放”的过程,如果一直按着按键,程序就要等待在那,而不是一直加数;

4.数码管在遇到60的时候要显示0,在0与59之间的加减转换要衔接好;

5.定时器T0的TR0开启或关闭,可以将if else语句简化成TR0 = ~TR0代替;

6.因为P1^7口是第8个发光二极管的口,也是时钟SCLK的口,如果不将发光二极管的使能端LE = 0(锁住),那么在按下按键5的时候,会导致发光二极管亮;

7.可将Switch2()、Switch3()、Switch4()、Switch5()这四个按键写在一个函数里简化,依次判断即可。

你可能感兴趣的:(51单片机学习,51单片机,嵌入式硬件,单片机)