找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 917|回复: 7
收起左侧

52单片机定时器定时程序问题

[复制链接]
ID:1002906 发表于 2022-2-17 14:18 | 显示全部楼层 |阅读模式
刚学定时器,想写一个程序,让单片机数码管每秒显示的数字加1,用的定时器定时,但是现在发现这个速度比较慢,我用手机一起计数发现手机每经过10s,单片机就会慢2s,就是手机秒表显示10的时候,单片机数码管显示8,有没有人帮我看一下是哪里的问题?单片机机器周期是1.085us。数码管显示数字全对,感觉只有定时器那里有问题。

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. sbit WE=P2^7;
  6. sbit DU=P2^6;

  7. uchar table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

  8. void delay(uchar x)                //@11.0592MHz
  9. {
  10.         unsigned char i, j;
  11.         while(x>0)
  12.                 {
  13.                 _nop_();
  14.                 i = 2;
  15.                 j = 199;
  16.                 do
  17.                 {
  18.                         while (--j);
  19.                 } while (--i);
  20.                 x--;
  21.         }
  22. }

  23. void display(uchar z)
  24. {
  25.         uchar ge,shi,bai;
  26.         ge=z%10;
  27.         shi=z%100/10;
  28.         bai=z/100;

  29.         P0=0XFF;
  30.         WE=1;
  31.         P0=0XFB;
  32.         WE=0;

  33.         DU=1;
  34.         P0=table[ge];
  35.         DU=0;
  36.         delay(5);        

  37.         P0=0XFF;
  38.         WE=1;
  39.         P0=0XFD;
  40.         WE=0;

  41.         DU=1;
  42.         P0=table[shi];
  43.         DU=0;
  44.         delay(5);

  45.         P0=0XFF;
  46.         WE=1;
  47.         P0=0XFE;
  48.         WE=0;

  49.         DU=1;
  50.         P0=table[bai];
  51.         DU=0;
  52.         delay(5);
  53. }

  54. void timer0Init()//50ms
  55. {
  56.         TR0=1;
  57.         TMOD=0x01;
  58.         TH0=(65535-46082)/256;
  59.         TL0=(65535-46082)%256;        
  60. }

  61. void main()
  62. {
  63.         uchar msec,sec;
  64.         timer0Init();
  65.         while(1)
  66.     {
  67.                 if(TF0==1)
  68.                 {
  69.                         msec++;
  70.                         TF0=0;
  71.                         TH0=(65536-46080)/256;
  72.                         TL0=(65536-46080)%256;
  73.                         
  74.                 }
  75.                 if(msec==20)
  76.                 {
  77.                         sec++;
  78.                         msec=0;
  79.                 }        
  80.                 display(sec);
  81.         }
  82. }
复制代码


回复

使用道具 举报

ID:625730 发表于 2022-2-17 16:49 | 显示全部楼层
你这个放在主函数里面,顺序执行,定时器起不到想要的效果。比如刚开始执行display函数的时候,计数器记满,TF0=1,那么要等display执行结束,回到while(1)的开头,去判断TF0的值,才会进入if语句里执行指令,如果TF0是0,那就不会进入if条件语句中执行指令,这样又得等执行完display,再回来判断TF0,
一般用定时器中断操作,打开ET0,EA,然后写一个定时器0的中断函数。
回复

使用道具 举报

ID:313048 发表于 2022-2-17 18:26 | 显示全部楼层
在中断里做计数值的累加,不要在while中做累加,while只做显示就好了,定时器中断产生后,里马重新写计数值,然后做计数就可以了。前提是定时器预装值计算正确。
回复

使用道具 举报

ID:213173 发表于 2022-2-17 20:00 | 显示全部楼层
如果用定时器查询方式一定要保证主循环周期明显小于定时周期,否则会发生计时信号丢失而走时变慢。修改如下:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #define uchar unsigned char
  4. #define uint unsigned int
  5. sbit WE=P2^7;
  6. sbit DU=P2^6;

  7. uchar table[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
  8. uchar i;

  9. void display(uchar z)
  10. {
  11.         uchar a[3];
  12.         a[0]=table[z/100%10];
  13.         a[1]=table[z/10%10];
  14.         a[2]=table[z%10];
  15.        
  16.         P0=0x00;
  17.         DU=1;
  18.         DU=0;
  19.        
  20.         P0=~(0x01<<i);
  21.         WE=1;
  22.         WE=0;
  23.        
  24.         P0=a[i];
  25.         DU=1;
  26.         DU=0;
  27.        
  28.         i=++i%3;
  29. }

  30. void timer0Init()        //5ms
  31. {
  32.         TMOD|= 0x01;        //设置定时器模式
  33.         TL0 = 0x00;                //设置定时初始值
  34.         TH0 = 0xEE;                //设置定时初始值
  35.         TF0 = 0;                //清除TF0标志
  36.         TR0 = 1;                //定时器0开始计时
  37. }

  38. void main()
  39. {
  40.         uchar msec,sec;
  41.         timer0Init();
  42.         while(1)
  43.         {
  44.                 if(TF0==1)
  45.                 {
  46.                         TF0=0;
  47.                         TL0 = 0x00;                //设置定时初始值
  48.                         TH0 = 0xEE;                //设置定时初始值
  49.                         msec++;
  50.                         if(msec==200)
  51.                         {
  52.                                 sec++;
  53.                                 msec=0;
  54.                         }        
  55.                         display(sec);
  56.                 }
  57.         }
  58. }
复制代码
回复

使用道具 举报

ID:1002906 发表于 2022-2-18 08:27 | 显示全部楼层
TEC 发表于 2022-2-17 16:49
你这个放在主函数里面,顺序执行,定时器起不到想要的效果。比如刚开始执行display函数的时候,计数器记满 ...

谢谢,我再去看看
回复

使用道具 举报

ID:1002906 发表于 2022-2-18 08:28 | 显示全部楼层
wulin 发表于 2022-2-17 20:00
如果用定时器查询方式一定要保证主循环周期明显小于定时周期,否则会发生计时信号丢失而走时变慢。修改如下 ...

谢谢,我再去看看
回复

使用道具 举报

ID:1002906 发表于 2022-2-18 08:28 | 显示全部楼层
AUG 发表于 2022-2-17 18:26
在中断里做计数值的累加,不要在while中做累加,while只做显示就好了,定时器中断产生后,里马重新写计数值 ...

谢谢,我再去看看
回复

使用道具 举报

ID:1005963 发表于 2022-2-21 12:11 | 显示全部楼层
wulin 发表于 2022-2-17 20:00
如果用定时器查询方式一定要保证主循环周期明显小于定时周期,否则会发生计时信号丢失而走时变慢。修改如下 ...

既然用了定时器,为什么不在中断函数里,要在main函数里面
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表