单片机计时器(数码管显示)
单片机计时器(数码管显示)
一、开发板简介
1、数码管为阴极,位控码对应P2.4~P2.7端口,段码对应P0口,高电平有效

2、LED灯对应P1口,低电平有效

3、独立按键对应P3.4~P3.7端口,低电平有效

4、计算




转化为16进制,高位=x/256
低位=x%256

二、Keil程序
#include <reg51.h>
#define uchar unsigned char
unsigned char j,k,num0,num1,num2,num3,sec,min,count=0;
unsigned char time_count;
//数码管位控码
unsigned char code weitable[]={0x8f,0x4f,0x2f,0x1f};
//数码管段码(不带小数点)
unsigned char code dis_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d, 0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//数码管段码(带小数点)
unsigned char code dis_code1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd, 0x87,0xff,0xef};
sbit k4 = P3^6; //按键K4
sbit k5 = P3^7; //按键K5
sbit beep = P2^3; //蜂鸣器
bit stop = 1; //停止工作标记位
//延时函数
void delay(unsigned char i)
{
for(j=i;j>0;j--)
for(k=85;k>0;k--);
}
//在某一位数码管上显示的数字
void display1(uchar wei,uchar shu)
{
//数码管位控码全置1,即全部选中
P2=P2|0xf0;
//如果是第二位,就用带小数点的段码,即3 2 . 1 0
if(wei == 2)
P0=dis_code1[shu];
//否则用不带小数点的段码
else
P0=dis_code[shu];
//给P2需要显示的那一位置1,其他置0,即单独设置位控码,选择某位
P2=P2&weitable[wei];
delay(5);
}
//一次显示4个数字,且每位显示数字可自定
void display(unsigned char a,unsigned char b,unsigned char c,unsigned char d)
{
display1(3,a);
display1(2,b);
display1(1,c);
display1(0,d);
}
void start_timer()
{
ET0=1; //开定时器0中断
EA=1; //开总中断,中断允许总开关控制位,1表示允许
TR0=1; //打开定时器
}
void stop_timer()
{
ET0=0; //关闭定时器0中断
EA=0; //关总中断,中断允许总开关控制位,0表示不允许
TR0=0; //关闭定时器
}
void main()
{
//模式设置,00000001,采用的是定时器0,工作模式1
TMOD=0x01;
//晶振为11.0592,所以50000*11.0592/12=46080
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
while(1)
{
if(k4 == 0) //按下键
{
delay(10); //去抖动
if(k4 == 0)
{
while(k4 == 0); //直到按键判断松开
{
if(stop) //标记位初值为1
//因为按下了键,所以如果停止工作标记位为1,表示没工作,那么要打开定时器
start_timer();
else
/*如果本来就是0,即本来就打开,那正在工作的时候按下键,说明是暂停,就关闭定时器 */
stop_timer();
//状态取反、关闭蜂鸣器、流水灯全灭
stop = ~stop;
beep = 1;
P1 = 0xff;
}
}
}
else if(k5 == 0) //按下K5键,则清零
{
delay(10); //去抖动
if(k5 == 0) //再次判断按键是否被按下
{
while(k5 == 0); //直到按键判断松开
{
stop_timer(); //关闭定时器
stop = 1;
beep = 1;
P1 = 0xff;
count = 0;
time_count = 0;
sec = 0; //记时清零
min = 0;
}
}
}
//当暂停或停止时,led灯闪亮表明在等待
if(stop)
{
/*每当count加一执行完,P1口对应的led灯状态就取反,即一亮一灭的闪亮效果,count终值越小,闪亮的越快。这里用count实现闪亮,不需要准确时间,不会影响数码管的刷屏,也不会造成延时而影响数码管。*/
count++;
if(count == 60)
{
P1 = ~P1;
count = 0;
}
}
//没停止,即在计时,在工作
else if(time_count==20) //计数20次,20*0.05秒=1秒
{
count = 0;
time_count=0;
sec++;
if(sec==60)
{
sec=0; //如果到了60s,则归零
min++;
}
if(min==60)
{
min=0; //如果到了60min,则归零
}
//计时达最大值,蜂鸣器响,提示
beep = 0;
delay(10);
beep = 1;
}
num0=sec%10; //取出秒数的个位
num1=sec/10; //取出秒数的十位
num2=min%10; //取出分数的个位
num3=min/10; //取出分数的十位
display(num3,num2,num1,num0);
}
}
void timer0() interrupt 1
{
TH0=(65536-46080)/256;
TL0=(65536-46080)%256;
time_count++;//每隔0.05s加一次
}
三、效果展示

浙公网安备 33010602011771号