打印
[51单片机]

使用定时器和数码管实现秒表倒计时的疑问

[复制链接]
2393|20
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
快鲨1|  楼主 | 2019-1-14 07:27 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
#include<reg52.h>
void InitTimer0(void);

unsigned int code LedChar[]={
    0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
    0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
};


void main()
{
    unsigned int sec = 0;
    while(1)
    {
        if(sec<=16)
        {
        P0=LedChar[sec];
        InitTimer0();
        sec++;
        }
        else
        {
        sec=0;
        }
    }
}


void InitTimer0(void)
{
    TMOD = 0x01;
    TH0 = 0x0FC;
    TL0 = 0x18;
    TR0 = 1;
}

为什么我的数码管一直都是停在8这个数字上没有变动?


相关帖子

沙发
xuyaqi| | 2019-1-14 08:31 | 只看该作者
延时有问题,把void InitTimer0(void)改成:
void delay(uint16 x)
{
        uint16 i,j;
        for(i = x; i > 0; i --)
                for(j = 114; j > 0; j --);               
}
调用这个延时就可以啦。

使用特权

评论回复
板凳
ningling_21| | 2019-1-14 13:12 | 只看该作者
程序逻辑不对

使用特权

评论回复
地板
快鲨1|  楼主 | 2019-1-15 07:03 | 只看该作者

可以说的具体点吗,我个人认为应该是void InitTimer0(void)函数定义的时候漏了什么,但是就是不知道漏了什么东西,这个函数我是用单片机小精灵弄出来的。

使用特权

评论回复
评论
ningling_21 2019-1-15 08:38 回复TA
没有开定时器中断和总中断 
5
ningling_21| | 2019-1-15 08:37 | 只看该作者
快鲨1 发表于 2019-1-15 07:03
可以说的具体点吗,我个人认为应该是void InitTimer0(void)函数定义的时候漏了什么,但是就是不知道漏了 ...

没有中断服务函数,初始化函数不用调用多次,
sec  在哪加1?

使用特权

评论回复
6
快鲨1|  楼主 | 2019-1-16 07:13 | 只看该作者
本帖最后由 快鲨1 于 2019-1-16 07:23 编辑
ningling_21 发表于 2019-1-15 08:37
没有中断服务函数,初始化函数不用调用多次,
sec  在哪加1?

如果您是问SEC在哪加一的话,SEC不是已经在一开始就初始化为0了吗,那肯定是从0开始加1。
unsigned int sec = 0
;如果您是问TH0在哪加一的话,TH0在0X0FC加一
TH0 = 0x0FC;
TL0 = 0x18;
;这样子有什么问题吗?至于为什么没有中断那是因为我还没学到中断,现在只学到如何使用定时器而已;另外你说的"初始化函数不用调用多次",我不是很懂,能说具体的吗?拜托了!
注:我这个是单个数码管静态显示,要求使用定时器每个数延时一秒显示。

使用特权

评论回复
7
ningling_21| | 2019-1-16 08:43 | 只看该作者
快鲨1 发表于 2019-1-16 07:13
如果您是问SEC在哪加一的话,SEC不是已经在一开始就初始化为0了吗,那肯定是从0开始加1。;如果您是问TH0 ...

主程序改一下
void main()
{
    unsigned int sec = 0;
InitTimer0();
    while(1)
    {
        if(sec<=16)
        {
        P0=LedChar[sec];
        
        sec++;
        }
        else
        {
        sec=0;
        }
    }
}

使用特权

评论回复
8
快鲨1|  楼主 | 2019-1-17 07:18 | 只看该作者
ningling_21 发表于 2019-1-16 08:43
主程序改一下
void main()
{

我不是很懂为什么 InitTimer0();放在unsigned int sec = 0;下面,按道理来讲函数不应该是执行到哪一步了,需要在那一步使用的时候才进行调用的吗?

使用特权

评论回复
9
快鲨1|  楼主 | 2019-1-19 23:15 | 只看该作者

ningling_21 发表于 2019-1-16 08:43 主程序改一下 void main() {

本帖最后由 快鲨1 于 2019-1-19 23:23 编辑
#include<reg52.h>
void InitTimer0(void);

unsigned int code LedChar[]={
        0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
        0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
};


void main()
{
    unsigned int sec = 0;
InitTimer0();
    while(1)
    {
        if(sec<=16)
        {
        P0=LedChar[sec];
        
        sec++;
        }
        else
        {
        sec=0;
        }
    }
}


void InitTimer0(void)
{
    TMOD = 0x01;
    TH0 = 0xb8;
    TL0 = 0x00;
TR0 = 1;


还是不行啊,一点变化都没有,还是一直停留在8这个数字上,就像图片上的一样。怎么办,还是说还是按参考答案的套路写算了?但是我不甘心啊,我想自己写一个出来。
//编程实现数码管静态显示秒表的倒计时参考答案!

#include <reg52.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

//ÓÃÊý×éÀ´´æ´¢ÊýÂë¹ÜµÄÕæÖµ±í£¬Êý×齫ÔÚÏÂÒ»ÕÂÏêϸ½éÉÜ
unsigned char code LedChar[] = {
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};

void main()
{
    unsigned char cnt = 0;  //¼Ç¼T0ÖжϴÎÊý
    unsigned char sec = 0x0F;  //¼Ç¼¾­¹ýµÄÃëÊý£¬µ¹¼Æʱ³õÖµ0x0F(15)

    ENLED = 0;    //ʹÄÜU3£¬Ñ¡ÔñÊýÂë¹ÜDS1
    ADDR3 = 1;
    ADDR2 = 0;
    ADDR1 = 0;
    ADDR0 = 0;
    TMOD = 0x01;  //ÉèÖÃT0Ϊģʽ1
    TH0  = 0xB8;  //ΪT0¸³³õÖµ0xB800
    TL0  = 0x00;
    TR0  = 1;     //Æô¶¯T0
   
    while (1)
    {
        if (TF0 == 1)        //ÅжÏT0ÊÇ·ñÒç³ö
        {
            TF0 = 0;         //T0Òç³öºó£¬ÇåÁãÖжϱêÖ¾
            TH0 = 0xB8;      //²¢ÖØи³³õÖµ
            TL0 = 0x00;
            cnt++;           //¼ÆÊýÖµ×Ô¼Ó1
            if (cnt >= 50)   //ÅжÏT0Òç³öÊÇ·ñ´ïµ½50´Î
            {
                cnt = 0;            //´ïµ½50´Îºó¼ÆÊýÖµÇåÁã
                P0 = LedChar[sec];  //µ±Ç°ÃëÊý¶ÔÓ¦µÄÕæÖµ±íÖеÄÖµË͵½P0¿Ú
                if (sec > 0)        //µ±ÃëÊý´óÓÚ0ʱ£¬¼õ1
                {
                    sec--;
                }
                else                //µ±ÃëÊýµÈÓÚ0ʱ£¬ÖØи³³õÖµ0x0F
                {
                    sec = 0x0F;
                }
            }
        }
    }
}

QQ图片20190119230915.png (271.24 KB )

QQ图片20190119230915.png

使用特权

评论回复
10
快鲨1|  楼主 | 2019-1-19 23:24 | 只看该作者
本帖最后由 快鲨1 于 2019-1-19 23:25 编辑
ningling_21 发表于 2019-1-16 08:43
主程序改一下
void main()
{
#include<reg52.h>
void InitTimer0(void);

unsigned int code LedChar[]={
        0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
        0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
};


void main()
{
    unsigned int sec = 0;
InitTimer0();
    while(1)
    {
        if(sec<=16)
        {
        P0=LedChar[sec];
        
        sec++;
        }
        else
        {
        sec=0;
        }
    }
}


void InitTimer0(void)
{
    TMOD = 0x01;
    TH0 = 0xb8;
    TL0 = 0x00;
TR0 = 1;
还是不行啊,一点变化都没有,还是一直停留在8这个数字上,就像图片上的一样。怎么办,还是说还是按参考答案的套路写算了?但是我不甘心啊,我想自己写一个出来。
//编程实现数码管静态显示秒表的倒计时参考答案!

#include <reg52.h>

sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;

//ÓÃÊý×éÀ´´æ´¢ÊýÂë¹ÜµÄÕæÖµ±í£¬Êý×齫ÔÚÏÂÒ»ÕÂÏêϸ½éÉÜ
unsigned char code LedChar[] = {
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};

void main()
{
    unsigned char cnt = 0;  //¼Ç¼T0ÖжϴÎÊý
    unsigned char sec = 0x0F;  //¼Ç¼¾­¹ýµÄÃëÊý£¬µ¹¼Æʱ³õÖµ0x0F(15)

    ENLED = 0;    //ʹÄÜU3£¬Ñ¡ÔñÊýÂë¹ÜDS1
    ADDR3 = 1;
    ADDR2 = 0;
    ADDR1 = 0;
    ADDR0 = 0;
    TMOD = 0x01;  //ÉèÖÃT0Ϊģʽ1
    TH0  = 0xB8;  //ΪT0¸³³õÖµ0xB800
    TL0  = 0x00;
    TR0  = 1;     //Æô¶¯T0
   
    while (1)
    {
        if (TF0 == 1)        //ÅжÏT0ÊÇ·ñÒç³ö
        {
            TF0 = 0;         //T0Òç³öºó£¬ÇåÁãÖжϱêÖ¾
            TH0 = 0xB8;      //²¢ÖØи³³õÖµ
            TL0 = 0x00;
            cnt++;           //¼ÆÊýÖµ×Ô¼Ó1
            if (cnt >= 50)   //ÅжÏT0Òç³öÊÇ·ñ´ïµ½50´Î
            {
                cnt = 0;            //´ïµ½50´Îºó¼ÆÊýÖµÇåÁã
                P0 = LedChar[sec];  //µ±Ç°ÃëÊý¶ÔÓ¦µÄÕæÖµ±íÖеÄÖµË͵½P0¿Ú
                if (sec > 0)        //µ±ÃëÊý´óÓÚ0ʱ£¬¼õ1
                {
                    sec--;
                }
                else                //µ±ÃëÊýµÈÓÚ0ʱ£¬ÖØи³³õÖµ0x0F
                {
                    sec = 0x0F;
                }
            }
        }
    }
}


QQ图片20190119230915.png (271.24 KB )

一直停留在原处不动

一直停留在原处不动

使用特权

评论回复
评论
ningling_21 2019-1-20 08:09 回复TA
上面那样定时器没起作用 
11
ningling_21| | 2019-1-20 08:12 | 只看该作者
快鲨1 发表于 2019-1-19 23:24
还是不行啊,一点变化都没有,还是一直停留在8这个数字上,就像图片上的一样。怎么办,还是说还是按参考答 ...
void main()
{
    unsigned int sec = 0;
        InitTimer0();
    while(1)
    {
                if(TF0==1)          
                {
                        TF0=0;
                        TH0 = 0xB8;     
            TL0 = 0x00;
                if(sec<=49)
                {
                                sec++;
                        P0=LedChar[sec];
                
                }
                else
                {
                        sec=0;
                }
                }
    }
}

使用特权

评论回复
12
快鲨1|  楼主 | 2019-1-22 07:19 | 只看该作者
if(TF0==1) 

为什么需要TF0==1,知道定时器溢出来有什么用?

使用特权

评论回复
13
ningling_21| | 2019-1-22 07:39 | 只看该作者
快鲨1 发表于 2019-1-22 07:19
为什么需要TF0==1,知道定时器溢出来有什么用?

不判断溢出怎么实现定时?

使用特权

评论回复
14
快鲨1|  楼主 | 2019-1-23 07:28 | 只看该作者
本帖最后由 快鲨1 于 2019-1-23 07:30 编辑
ningling_21 发表于 2019-1-22 07:39
不判断溢出怎么实现定时?
#include<reg52.h>
void InitTimer0(void);

unsigned int code LedChar[]={
        0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
        0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
};


void main()
{
                unsigned int sec = 0;
                unsigned int cnt = 0;//在定时器的基础上乘于X,可成倍数关系,可大于73MS。
    InitTimer0();
    while(1)
{
    if(TF0==1)         
                {
     TF0=0;
    TH0 = 0xB8;
    TL0 = 0x00;
                cnt++;
    if(cnt>=50)
    {
                P0=LedChar[sec];
    cnt=0;         
                        if(sec<16)
                        {
                                sec++;
                        }
                        else
                        {
                                sec=0x8e;
                        }
    }
    }
}
}


void InitTimer0(void)
{
    TMOD = 0x00;
    TH0 = 0xB8;
    TL0 = 0x00;
    TR0 = 1;
}

我这个程序只执行一次,为什么会这样子?还有我想知道cnt++=50时花了多少秒,我该怎么标记,是应该在TF0=0;时标记第一个,在if(cnt >=50)时标记第二个?还说是在cnt++;标记第二个?

捕获.PNG (13.64 KB )

捕获.PNG

使用特权

评论回复
15
快鲨1|  楼主 | 2019-1-24 07:15 | 只看该作者
ningling_21 发表于 2019-1-22 07:39
不判断溢出怎么实现定时?

我实在不明白为什么两个程序差不多的,一个不行一个可以,左边的那个我又没有重新赋值给T0,按道理说不应该是定时器T0一直自加1,然后一直溢出一直循环的吗,怎么现在好像TF0不等于1所以执行不了下一步似的?

捕获.PNG (260.35 KB )

捕获.PNG

使用特权

评论回复
16
linqing171| | 2019-1-24 22:57 | 只看该作者
先做个程序,里面写上 while(1)P0=0x55;
看看灯是不是接P0上的。

使用特权

评论回复
17
快鲨1|  楼主 | 2019-1-25 07:08 | 只看该作者
linqing171 发表于 2019-1-24 22:57
先做个程序,里面写上 while(1)P0=0x55;
看看灯是不是接P0上的。

灯是接P0上了,现在出问题的是这个程序没有按顺序重复点亮真值表上的数字,只点亮一次就停下了,还没都没有循环了。

使用特权

评论回复
18
快鲨1|  楼主 | 2019-1-25 07:46 | 只看该作者
我找到问题所在了,第一个问题是因为我用错了TMOD模式,想用工作模式1的结果用成了0,第二个问题就是最后else{sec=0x8e}应该为sec=0才对的,毕竟我是使用数组里的真值表,不是在用某个具体的真值表数值。不过现在又有一个问题出现了,就是在循环完成后会多出一个数,本来是数码管小数点过后就到零的了,结果多了一个不知道什么的出现如图,怎么去掉它?

捕获.PNG (241.61 KB )

捕获.PNG

使用特权

评论回复
19
快鲨1|  楼主 | 2019-1-26 15:42 | 只看该作者
十分感谢前面各位的耐心回答,谢谢!本帖子的问题已经全部解决了。至于十八楼的问题是我忘记数组是从零开始的,应该if(sec<14)才对的,这样子就不会多出两个了。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

13

主题

45

帖子

0

粉丝