[51单片机] 使用定时器和数码管实现秒表倒计时的疑问

[复制链接]
1051|20
 楼主 | 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这个数字上没有变动?


| 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 --);               
}
调用这个延时就可以啦。

使用特权

评论回复
| 2019-1-14 13:12 | 显示全部楼层
程序逻辑不对

使用特权

评论回复
 楼主 | 2019-1-15 07:03 | 显示全部楼层

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

使用特权

评论回复

评论

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

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

使用特权

评论回复
| 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;
        }
    }
}

使用特权

评论回复
 楼主 | 2019-1-17 07:18 | 显示全部楼层
ningling_21 发表于 2019-1-16 08:43
主程序改一下
void main()
{

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

使用特权

评论回复
 楼主 | 2019-1-19 23:15 | 显示全部楼层

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

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

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


  7. void main()
  8. {
  9.     unsigned int sec = 0;
  10. InitTimer0();
  11.     while(1)
  12.     {
  13.         if(sec<=16)
  14.         {
  15.         P0=LedChar[sec];
  16.         
  17.         sec++;
  18.         }
  19.         else
  20.         {
  21.         sec=0;
  22.         }
  23.     }
  24. }


  25. void InitTimer0(void)
  26. {
  27.     TMOD = 0x01;
  28.     TH0 = 0xb8;
  29.     TL0 = 0x00;
  30. TR0 = 1;


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

  2. #include <reg52.h>

  3. sbit ADDR0 = P1^0;
  4. sbit ADDR1 = P1^1;
  5. sbit ADDR2 = P1^2;
  6. sbit ADDR3 = P1^3;
  7. sbit ENLED = P1^4;

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

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

  17.     ENLED = 0;    //ʹÄÜU3£¬Ñ¡ÔñÊýÂë¹ÜDS1
  18.     ADDR3 = 1;
  19.     ADDR2 = 0;
  20.     ADDR1 = 0;
  21.     ADDR0 = 0;
  22.     TMOD = 0x01;  //ÉèÖÃT0Ϊģʽ1
  23.     TH0  = 0xB8;  //ΪT0¸³³õÖµ0xB800
  24.     TL0  = 0x00;
  25.     TR0  = 1;     //Æô¶¯T0
  26.    
  27.     while (1)
  28.     {
  29.         if (TF0 == 1)        //ÅжÏT0ÊÇ·ñÒç³ö
  30.         {
  31.             TF0 = 0;         //T0Òç³öºó£¬ÇåÁãÖжϱêÖ¾
  32.             TH0 = 0xB8;      //²¢ÖØи³³õÖµ
  33.             TL0 = 0x00;
  34.             cnt++;           //¼ÆÊýÖµ×Ô¼Ó1
  35.             if (cnt >= 50)   //ÅжÏT0Òç³öÊÇ·ñ´ïµ½50´Î
  36.             {
  37.                 cnt = 0;            //´ïµ½50´Îºó¼ÆÊýÖµÇåÁã
  38.                 P0 = LedChar[sec];  //µ±Ç°ÃëÊý¶ÔÓ¦µÄÕæÖµ±íÖеÄÖµË͵½P0¿Ú
  39.                 if (sec > 0)        //µ±ÃëÊý´óÓÚ0ʱ£¬¼õ1
  40.                 {
  41.                     sec--;
  42.                 }
  43.                 else                //µ±ÃëÊýµÈÓÚ0ʱ£¬ÖØи³³õÖµ0x0F
  44.                 {
  45.                     sec = 0x0F;
  46.                 }
  47.             }
  48.         }
  49.     }
  50. }
复制代码

QQ图片20190119230915.png

使用特权

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

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


  7. void main()
  8. {
  9.     unsigned int sec = 0;
  10. InitTimer0();
  11.     while(1)
  12.     {
  13.         if(sec<=16)
  14.         {
  15.         P0=LedChar[sec];
  16.         
  17.         sec++;
  18.         }
  19.         else
  20.         {
  21.         sec=0;
  22.         }
  23.     }
  24. }


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

  2. #include <reg52.h>

  3. sbit ADDR0 = P1^0;
  4. sbit ADDR1 = P1^1;
  5. sbit ADDR2 = P1^2;
  6. sbit ADDR3 = P1^3;
  7. sbit ENLED = P1^4;

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

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

  17.     ENLED = 0;    //ʹÄÜU3£¬Ñ¡ÔñÊýÂë¹ÜDS1
  18.     ADDR3 = 1;
  19.     ADDR2 = 0;
  20.     ADDR1 = 0;
  21.     ADDR0 = 0;
  22.     TMOD = 0x01;  //ÉèÖÃT0Ϊģʽ1
  23.     TH0  = 0xB8;  //ΪT0¸³³õÖµ0xB800
  24.     TL0  = 0x00;
  25.     TR0  = 1;     //Æô¶¯T0
  26.    
  27.     while (1)
  28.     {
  29.         if (TF0 == 1)        //ÅжÏT0ÊÇ·ñÒç³ö
  30.         {
  31.             TF0 = 0;         //T0Òç³öºó£¬ÇåÁãÖжϱêÖ¾
  32.             TH0 = 0xB8;      //²¢ÖØи³³õÖµ
  33.             TL0 = 0x00;
  34.             cnt++;           //¼ÆÊýÖµ×Ô¼Ó1
  35.             if (cnt >= 50)   //ÅжÏT0Òç³öÊÇ·ñ´ïµ½50´Î
  36.             {
  37.                 cnt = 0;            //´ïµ½50´Îºó¼ÆÊýÖµÇåÁã
  38.                 P0 = LedChar[sec];  //µ±Ç°ÃëÊý¶ÔÓ¦µÄÕæÖµ±íÖеÄÖµË͵½P0¿Ú
  39.                 if (sec > 0)        //µ±ÃëÊý´óÓÚ0ʱ£¬¼õ1
  40.                 {
  41.                     sec--;
  42.                 }
  43.                 else                //µ±ÃëÊýµÈÓÚ0ʱ£¬ÖØи³³õÖµ0x0F
  44.                 {
  45.                     sec = 0x0F;
  46.                 }
  47.             }
  48.         }
  49.     }
  50. }
复制代码


一直停留在原处不动

一直停留在原处不动

使用特权

评论回复

评论

ningling_21 2019-1-20 08:09 回复TA
上面那样定时器没起作用 
| 2019-1-20 08:12 | 显示全部楼层
快鲨1 发表于 2019-1-19 23:24
还是不行啊,一点变化都没有,还是一直停留在8这个数字上,就像图片上的一样。怎么办,还是说还是按参考答 ...
  1. void main()
  2. {
  3.     unsigned int sec = 0;
  4.         InitTimer0();
  5.     while(1)
  6.     {
  7.                 if(TF0==1)          
  8.                 {
  9.                         TF0=0;
  10.                         TH0 = 0xB8;     
  11.             TL0 = 0x00;
  12.                 if(sec<=49)
  13.                 {
  14.                                 sec++;
  15.                         P0=LedChar[sec];
  16.                 
  17.                 }
  18.                 else
  19.                 {
  20.                         sec=0;
  21.                 }
  22.                 }
  23.     }
  24. }
复制代码

使用特权

评论回复
 楼主 | 2019-1-22 07:19 | 显示全部楼层
  1. if(TF0==1)
复制代码

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

使用特权

评论回复
| 2019-1-22 07:39 | 显示全部楼层
快鲨1 发表于 2019-1-22 07:19
为什么需要TF0==1,知道定时器溢出来有什么用?

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

使用特权

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

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


  7. void main()
  8. {
  9.                 unsigned int sec = 0;
  10.                 unsigned int cnt = 0;//在定时器的基础上乘于X,可成倍数关系,可大于73MS。
  11.     InitTimer0();
  12.     while(1)
  13. {
  14.     if(TF0==1)         
  15.                 {
  16.      TF0=0;
  17.     TH0 = 0xB8;
  18.     TL0 = 0x00;
  19.                 cnt++;
  20.     if(cnt>=50)
  21.     {
  22.                 P0=LedChar[sec];
  23.     cnt=0;         
  24.                         if(sec<16)
  25.                         {
  26.                                 sec++;
  27.                         }
  28.                         else
  29.                         {
  30.                                 sec=0x8e;
  31.                         }
  32.     }
  33.     }
  34. }
  35. }


  36. void InitTimer0(void)
  37. {
  38.     TMOD = 0x00;
  39.     TH0 = 0xB8;
  40.     TL0 = 0x00;
  41.     TR0 = 1;
  42. }
复制代码

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

使用特权

评论回复
 楼主 | 2019-1-24 07:15 | 显示全部楼层
ningling_21 发表于 2019-1-22 07:39
不判断溢出怎么实现定时?

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

捕获.PNG

使用特权

评论回复
| 2019-1-24 22:57 | 显示全部楼层
先做个程序,里面写上 while(1)P0=0x55;
看看灯是不是接P0上的。

使用特权

评论回复
 楼主 | 2019-1-25 07:08 | 显示全部楼层
linqing171 发表于 2019-1-24 22:57
先做个程序,里面写上 while(1)P0=0x55;
看看灯是不是接P0上的。

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

使用特权

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

使用特权

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

使用特权

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /5 下一条

在线客服 快速回复 返回顶部 返回列表