#include "reg52.h"
typedef unsigned int uint;
typedef unsigned char uchar;
#define dynamic_digital P0 //定义段选IO
sbit SRA = P2^2;
sbit SRB = P2^3;
sbit SRC = P2^4;
sbit k1 = P1^0; //set 设置
sbit k2 = P1^1; //puls +
sbit k3 = P1^2; //minus -
sbit k4 = P1^3; //finish 退出
sbit k5 = P1^4; //switch 切换
sbit k6 = P1^5; //start 计时
sbit k7 = P1^6; //stop 暂停
sbit k8 = P1^7; //reset 重置
uint time = 0; //定时器0的计数值(单位:50ms)
//-------------------------------23:59:50
char hour = 23; //时钟单位
char minute = 59; //时钟单位
char second = 50; //时钟单位
uint time_stopwatch = 0; //定时器1的计数值(单位:2ms)
uchar minute_stopwatch = 0; //秒表的分钟单位(min)
uchar second_stopwatch = 0; //秒表的秒钟单位(s)
uchar microsecond_stopwatch = 0; //秒表的毫秒单位(最小10ms)
uchar mode = 0; //时钟设置标志位:set hour/minute
uchar function = 0; //功能选择: 时钟/秒表
uchar flag = 0; //秒表设置标志位:start/stop/reset
uchar DisplayData[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x40};//共阴:0~9 -
// 延时
void delay(uint i)
{
while(i--);
}
/************************************************************
数码管显示:位选 + 段选
同时附带时钟设置时需要闪烁的效果
************************************************************/
void display_select(uchar pos,uchar dat) // 数码管位选
{
switch (pos)
{
case 0:
SRA=0;SRB=0;SRC=0; //000 第0号管
break;
case 1:
SRA=1;SRB=0;SRC=0; //001 第1号管
break;
case 2:
SRA=0;SRB=1;SRC=0; //010 第2号管
break;
case 3:
SRA=1;SRB=1;SRC=0; //011 第3号管
break;
case 4:
SRA=0;SRB=0;SRC=1; //100 第4号管
break;
case 5:
SRA=1;SRB=0;SRC=1; //101 第5号管
break;
case 6:
SRA=0;SRB=1;SRC=1; //110 第6号管
break;
case 7:
SRA=1;SRB=1;SRC=1; //111 第7号管
break;
}
if(mode==0) //正常亮
{
dynamic_digital = dat;
delay(8);
dynamic_digital = 0x00;
}
if(mode==1) // 设置hour时,闪烁
if(pos==0 || pos==1)
{
if(time<10)
{
dynamic_digital = dat;
delay(8);
dynamic_digital = 0x00;
}
}
else //正常亮
{
dynamic_digital = dat;
delay(8);
dynamic_digital = 0x00;
}
else if(mode==2) // 设置minute时,闪烁
if(pos==3 || pos==4)
{
if(time<10)
{
dynamic_digital = dat;
delay(8);
dynamic_digital = 0x00;
}
}
else //正常亮
{
dynamic_digital = dat;
delay(8);
dynamic_digital = 0x00;
}
//delay(8);
//dynamic_digital = 0x00;
//delay(91);
}
// 显示时钟内容
void display()
{
display_select(0,DisplayData[hour/10]); //显示hour---------------------
display_select(1,DisplayData[hour%10]);
display_select(2,DisplayData[10]); //显示分隔符'-'----------------
display_select(3,DisplayData[minute/10]); //显示minute-------------------
display_select(4,DisplayData[minute%10]);
display_select(5,DisplayData[10]); //显示分隔符'-'----------------
display_select(6,DisplayData[second/10]); //显示second-------------------
display_select(7,DisplayData[second%10]);
}
// 显示秒表内容
void display_stopwatch()
{
display_select(0,DisplayData[minute_stopwatch/10]); //显示minute---------------------
display_select(1,DisplayData[minute_stopwatch%10]);
display_select(2,DisplayData[10]); //显示分隔符'-'----------------
display_select(3,DisplayData[second_stopwatch/10]); //显示second-------------------
display_select(4,DisplayData[second_stopwatch%10]);
display_select(5,DisplayData[10]); //显示分隔符'-'----------------
display_select(6,DisplayData[microsecond_stopwatch/10]); //显示microsecond-------------------
display_select(7,DisplayData[microsecond_stopwatch%10]);
}
// 秒表功能
void stopwatch()
{
// reset
if(flag==0)
{
minute_stopwatch = 0;
second_stopwatch = 0;
microsecond_stopwatch = 0; //单位是10ms
}
// start
else if(flag==1)
{
microsecond_stopwatch = time_stopwatch/5;
if(microsecond_stopwatch>=100)
{
time_stopwatch = 0;
microsecond_stopwatch = 0;
second_stopwatch++;
if(second_stopwatch>=60)
{
second_stopwatch = 0;
minute_stopwatch++;
if(minute_stopwatch>=100)
minute_stopwatch = 0;
}
}
}
}
/**************************************************************
S1:时钟设置 S2:hour++ S3;minute++ S4:finish
S5:时钟/秒表 S6:秒表计时 S7:秒表暂停 S8:秒表复位
***************************************************************/
void key_scan()
{
if(k5==0)
{
delay(1000);
if(k5==0)
function = ~function;
while(!k5);
}
if(function==0) //function=0 时钟模式
{
flag = 0; // 重置秒表设置标志位,方便下次使用
if(k1==0) // set 设置调节模式
{
delay(1000);
if(k1==0)
mode++;
if(mode>2)
mode = 1;
//led=~led;
while(!k1);
}
if(mode!=0)
{
if(k2==0) // puls +1
{
delay(1000);
if(k2==0)
if(mode==1) // 设置hour
hour++;
else if(mode==2) //设置minute
minute++;
while(!k2);
}
if(k3==0) // minus -1
{
delay(1000);
if(k3==0)
if(mode==1) //设置hour
hour--;
else if(mode==2) //设置minute
minute--;
while(!k3);
}
if(k4==0) // back 退出设置模式
{
delay(1000);
if(k4==0)
mode = 0;
while(!k4);
}
}
}
else //function=1 秒表模式
{
mode = 0; // 重置时钟模式,方便下次使用
if(k6==0) // start
{
delay(1000);
if(k6==0)
flag = 1;
//led=~led;
while(!k6);
}
if(k7==0) // stop
{
delay(1000);
if(k7==0)
flag = 2;
while(!k7);
}
if(k8==0) // reset
{
delay(1000);
if(k8==0)
flag = 0;
while(!k8);
}
}
}
// 定时器0初始化
void Timer0Init()
{
TMOD|=0x01; //选择定时器0模式,工作方式:仅用TR0打开启动
TH0=0x3C; //给定时器0赋初值,定时50ms
TL0=0xB0;
ET0=1; //打开定时器0中断允许
EA=1; //打开总允许
TR0=1; //打开定时器0
}
// 定时器1初始化
void Timer1Init()
{
TMOD|=0x10; //选择定时器1模式,8位自动重装载,仅用TR1打开启动
TH1=0xF8; //给定时器1赋初值,定时2ms
TL1=0x30;
ET1=1; //打开定时器0中断允许
EA=1; //打开总允许
TR1=1; //打开定时器0
}
/********************************************************************
完整实现试题所有功能
两个定时器的使用仍然有一点瑕疵,如果使用定时器+DS1302可能会更好
********************************************************************/
void main()
{
Timer0Init(); //定时器0初始化
Timer1Init(); //定时器1初始化
while(1)
{
key_scan(); //扫描按键变化
if(function!=0)
{
mode = 0; //重置时钟模式
stopwatch(); //秒表
}
}
}
/****************************************************************
定时器0中断
功能:累计时钟数值,即使在秒表功能下,时钟仍然累计
****************************************************************/
void Time0() interrupt 1
{
TH0=0x3C; // 定时50ms
TL0=0xB0;
time++;
//display(); //0.5ms
if(time==20) //定时1s
{
second++;
time = 0;
if(second>=60)
{
minute++;
second = 0;
}
if(minute>=60) // 60分钟进1位
{
hour++;
minute = 0;
}
else if(minute<0)
{
hour--;
minute = 59;
}
if(hour>=24) // 24小时进1位
hour = 0;
else if(hour <0)
hour = 23;
}
}
/****************************************************
定时器1中断:数码管的定时显示
功能:可防止数码管因长时间按住按键导致主线程
卡在检测按键的while循环而熄灭
****************************************************/
void Time1() interrupt 3
{
TH1=0xF8; //给定时器1赋初值,定时2ms
TL1=0x30;
if(flag==0)
time_stopwatch = 0;
if(function==0)
display();
else
{
if(flag==1)
time_stopwatch++;
display_stopwatch();
}
}
文末链接为本题的分文件写法,更推荐使用分文件写法!
暂无评论
要发表评论,您必须先 登录