菜鸟必看之16位定时器的正确填充方法

2020-01-27 11:28发布

特别注意事项:
1,在进行写定时器时会停止计数,填充的时候需要补偿1。
2,进入定时器中断时需要时间,填充前必须读出再减去进入中断需要的时间。
3,计算填充值时需要时间,填充计算过程中需要考虑。

例子:

活动填充值:
  1. #include<at89x51.h>

  2. #define uint8_t unsigned char
  3. #define uint16_t unsigned int

  4. #define K1 P1_0
  5. #define K2 P1_1
  6. #define L0 P2_0

  7. uint16_t T_D,T_X;

  8. void delay_ms(uint8_t xms)                // 晶体为12M时循环一次为1mS
  9. {
  10.         uint16_t xus;
  11.         for(;xms;--xms)
  12.         {       
  13.                 for(xus=124;xus;--xus);
  14.         }
  15. }

  16. void int_t0(void) interrupt 1
  17. {
  18.         T_X = T_D+TL0+14;        // T_X为临时变量,T_D为定时器填充值,14为补偿值,TL0当前值为进入中断所需时间
  19.         TH0 = T_X>>8;
  20.         TL0 = T_X;
  21.         P2_0 = !P2_0;                       
  22. }

  23. void main(void)
  24. {
  25.         TMOD = 0x01;        // T0设置为16位定时器
  26.         TH0 = 0xFC;
  27.         TL0 = 0x22;
  28.         ET0 = 1;                 // 开T0中断
  29.         EA = 1;                        // 开总中断
  30.         TR0 = 1;                // 打开T0定时器
  31.         T_D = 65536-1000;
  32.         T_X = 0;
  33.         while(1)
  34.         {
  35.                 if(!(K1&&K2))
  36.                 {
  37.                         delay_ms(100);
  38.                         if((!K1)&&(T_D<5000))
  39.                         {
  40.                                 T_D = T_D+100;       
  41.                         }
  42.                         else if((!K2)&&(T_D>100))
  43.                         {
  44.                                 T_D = T_D-100;                                       
  45.                         }
  46.                         while(!(K1&&K2));                               
  47.                 }
  48.         }
  49. }
复制代码固定填充值50mS(12M):
  1. #include<at89x51.h>

  2. #define uint8_t unsigned char
  3. #define uint16_t unsigned int

  4. #define K1 P1_0
  5. #define K2 P1_1
  6. #define L0 P2_0

  7. void int_t0(void) interrupt 1
  8. {
  9.         TH0 = (65536-50000)/256;                // 定时50mS进入中断
  10.         TL0 = (65536-50000)%256+2+TL0;  // 加上补偿时间
  11.         P2_0 = !P2_0;                       
  12. }

  13. void main(void)
  14. {
  15.         TMOD = 0x01;        // T0设置为16位定时器
  16.         TH0 = (65536-50000)/256;        // 定时50mS进入中断
  17.         TL0 = (65536-50000)&256;
  18.         ET0 = 1;                 // 开T0中断
  19.         EA = 1;                        // 开总中断
  20.         TR0 = 1;                // 打开T0定时器
  21.         while(1);
  22. }
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
19条回答
Lu.Shi
1楼-- · 2020-01-28 10:06
chengzepeng 发表于 2012-9-12 16:42
建议你用个仿真器测试下,在中断后的第一句做断点!
主函数就用死循环什么也不干,
中断后看到TL0就是4或 ...

明白了,谢谢指点。。
568581185
2楼-- · 2020-01-28 14:56
 精彩回答 2  元偷偷看……
zhdo1983
3楼-- · 2020-01-28 16:08
mark                             
a794001114
4楼-- · 2020-01-28 16:33
mark,51定时器
chengzepeng
5楼-- · 2020-01-28 22:14
a794001114 发表于 2012-9-13 01:11
mark,51定时器

这个可不单单是51定时器,
PIC或者AVR以及STM都通用,
只要是需要填充的定时器都要进行计数补偿!
Sullivan
6楼-- · 2020-01-29 02:51
chengzepeng 发表于 2012-9-13 12:31  这个可不单单是51定时器,  PIC或者AVR以及STM都通用,  只要是需要填充的定时器都要进行计数补偿! ...

如果TL0恰好是255你岂不悲剧了?如果再加上溢出判断你岂不更悲剧了?

一周热门 更多>