利用51单片机和3位数码管实现10分钟内的简易计时器

利用单片机和3位数码管实现从0到9分59秒的计时,计时的秒通过空操作延时实现,具体代码如下:
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
sbit key1=P2^7;
sbit key2=P2^6;
sbit weiH=P3^0;
sbit weiM=P3^1;
sbit weiL=P3^2;
uint num=0,ge=0,shi=0,fen=0,k; //num用来计数,ge为各位显示,shi为十位显示,fen为分钟显示

void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}

key1scan()
{if(key1==0)
{delayms(10);
if(key1==0)
{while(!key1);
return 1;
}
}
}

key2scan()
{if(key2==0)
{delayms(10);
if(key2==0)
{while(!key2);
return 1;
}
}
}

void showtime() //时间显示
{while(1)
{weiL=1; //显示秒的个位
P1=0xff;
P1=table[ge];
delayms(5);
weiL=0;

weiM=1; //显示秒的十位
P1=0xff;
P1=table[shi];
delayms(5);
weiM=0;

weiH=1; //显示分钟,只显示0-9
P1=0xff;
P1=table[fen];
delayms(5);
weiH=0;
}
}

void main()
{num=0;
if((key1scan()==1)&&(key2scan()!=1)) //按键1按下,按键2未按下开始计时
{
++num;
if(num<10)
{ge=num;}
if(num=10)
{num=num-10; //个位到10清零
if(shi==6) //十位到6清零
{shi=0;
++fen;
}
++shi;
ge=num;
}
showtime();
}
}
请问为什么数码管时钟显示000,而不是计时状态?如何修改(不要太大面积修改)?

修改如下:
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char 
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
sbit key1=P2^7;
sbit key2=P2^6;
sbit weiH=P3^0;
sbit weiM=P3^1;
sbit weiL=P3^2;
uint num=0,ge=0,shi=0,fen=0,k; //num用来计数,ge为各位显示,shi为十位显示,fen为分钟显示

void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}

uchar key1scan(void)
{if(key1==0)
{delayms(10);
if(key1==0)
{while(!key1);
return 1;
}
return 0;
}

uchar key2scan(void)
{if(key2==0)
{delayms(10);
if(key2==0)
{while(!key2);
return 1;
}
}
return 0;
}

void showtime() interrupt 1//时间显示
{
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
num++;
num%=3;
switch(num)
{
case 0:
weiL=1; //显示秒的个位
P1=0xff;
P1=table[ge];
delayms(5);
weiL=0;
break;
case 1:
weiM=1; //显示秒的十位
P1=0xff;
P1=table[shi];
delayms(5);
weiM=0;
break;
case 2:
weiH=1; //显示分钟,只显示0-9
P1=0xff;
P1=table[fen];
delayms(5);
weiH=0;
break;
}

void main()
{
TMOD=0x01;
TH0=(65536-5000)/256;
TL0=(65536-5000)%256;
TR0=1;
ET0=1;
EA=1;
num=0;
while(1)
    {
if((key1scan()==1)&&(key2scan()!=1))break; //按键1按下,按键2未按下开始计时
    }
while(1)
    {
    delay(1000);
    ge++;
    if(ge>9)
        {
        ge=0;
        shi++
        if(shi>5)
            {
            fen++;
            if(fen>9)fen=0;
            }
         }
    showtime();
    }
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-12-22
因为楼主说,(不要太大面积修改)。
所以,就没有敢进行大面积的修改。

只简单的改改,未必能好用,仅供参考:

#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[] = {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

sbit key1=P2^7;
sbit key2=P2^6;
sbit weiH=P3^0;
sbit weiM=P3^1;
sbit weiL=P3^2;

uint num=0,ge=0,shi=0,fen=0,k;
//num用来计数,ge为各位显示,shi为十位显示,fen为分钟显示

void delayms(uint xms) //i=xms即延时约xms毫秒
{
uint i,j;
for(i=xms;i>0;i--) for(j=110;j>0;j--);
}

uchar key1scan()
{
if(key1==0) {
delayms(10);
if(key1==0) {
while(!key1) showtime();//等待释放期间,也进行显示
return 1;
}
}
return 0;//添上了返回值
}

uchar key2scan()
{
if(key2==0) {
delayms(10);
if(key2==0) {
while(!key2) showtime();
return 1;
}
}
return 0;//添上了返回值
}

void showtime() //时间显示
{

//这里去掉了while(1) ,避免了死循环

P1=0xff; weiL=1; P1=table[ge]; delayms(5); weiL=0;//显示秒的个位
P1=0xff; weiM=1; P1=table[shi]; delayms(5); weiM=0;//显示秒的十位
P1=0xff; weiH=1; P1=table[fen]; delayms(5); weiH=0;//显示分钟,只显示0-9
}

void main()
{
num=0;
while(1) {
if(key1scan() && !key2scan()) { //按键1按下,按键2未按下开始计时
++num;
if(num<10) {ge=num;}
if(num=10) {
num = num - 10; //个位到10清零
if(shi == 6) { //十位到6清零
shi=0;
++fen;
}
++shi;
ge=num;
}
showtime();
}
}
}本回答被网友采纳
第2个回答  2013-12-21
你的循环函数用错地方了,应该用在main函数里,而不是子函数里,现在的情况是一直在显示showtime函数里循环不能跳出来,而你的即使部分呢又不是定时中断,这样就导致数码管不会变了。
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
sbit key1=P2^7;
sbit key2=P2^6;
sbit weiH=P3^0;
sbit weiM=P3^1;
sbit weiL=P3^2;
uint num=0,ge=0,shi=0,fen=0,k; //num用来计数,ge为各位显示,shi为十位显示,fen为分钟显示

void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}

key1scan()
{if(key1==0)
{delayms(10);
if(key1==0)
{while(!key1);
TR0 = 1;
}
}
}

key2scan()
{if(key2==0)
{delayms(10);
if(key2==0)
{while(!key2);
TR0 =0;
}
}
}

void showtime() //时间显示
{
//weiL=1; //显示秒的个位
P1=0xff;
weiL=0;
P1=table[ge];
delayms(10);
weiL=1;

//weiM=1; //显示秒的十位
P1=0xff;
P1=table[shi];
weiM=0;
delayms(10);
weiM=1;

//weiH=1; //显示分钟,只显示0-9
P1=0xff;
P1=table[fen];
weiH=0;
delayms(10);
weiH=1;
}

void time_0() interrupt 1
{
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
num++;
if(num ==20) //1秒则个位+1;
{
num = 0;
ge++;
if(ge == 10)
{
ge = 0; //个位到10清零
shi++;
if(shi==6) //十位到6清零
{shi=0;
fen++;
}
}
}
}

void main()
{
TMOD = 0X01; //觉得不用定时器中断简直就是浪费时间。
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256; //50ms*20=1s
ET0 = 1; // 打开定时中断
EA = 1; //打开总中断。
while(1)
{
key1scan(); //扫描按键1,如果按下,则打开定时中断TR0开始计时
key2scan(); //扫描按键2,如果按下,则关闭定时中断TR0停止计时。
showtime();
}
}追问

这个是利用·中断的,数码管跳变,但是显示都一样,而且到后面不清晰

追答

唉,没办法了,这是根据你提供的资料画的proteus的原理图,可以自己试一下。

第3个回答  2013-12-21
主函数里面要加while(1)