用数码管的前两位显示一个十进制数,变化范围为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()这四个按键写在一个函数里简化,依次判断即可。