标题: 关于51单片机的定时器T0、T1总结 [打印本页]

作者: a1075511750    时间: 2017-12-26 23:13
标题: 关于51单片机的定时器T0、T1总结
这是我总结的51单片机的中断定时器原理,之后会附上附件。第一次发帖,不足之处请多多包含!
我总结的文稿画面很花,所以给上个参考,各位不习惯的话,请酌情选择。


目录

一、原理:
1、对中断和定时器进行初始化:
①定时器/计数器工作方式寄存器
②设定初值
③开启中断和定时器
2、设置中断服务程序:
3、主函数:
二、各个定时器和工作方式:
方式0:
方式2:
方式3:
借鉴:郭天祥《新概念51单片机C语言教程》
一、原理:
51单片机,拥有两个定时器,用来中断计数,分别是T0和T1。而52单片机和51单片机的定时器是一样的,只是52比51多了一个定时器/计数器T2,它们的设置都大同小异,下面我来总结各个定时器的用法。
定时器T0与T1不同之处在于它们的工作方式3不同,方式0、1、2相同。
M1
M0
工作方式
0
0
方式0,13位定时器/计数器
0
1
方式1,16位定时器/计数器
1
0
方式2,8位自动重装的8位定时器/计数器
1
1
方式3,仅适用于T0,分成两个8位计数器,
当设置成T1时停止计数

首先我们看要使用定时器T0应该设置的东西:
1、对中断寄存器和定时器进行初始化:
              
初始化函数里的内容也可以写在头文件里,但是为了美观和好查阅,就把它单独写出来,后面在头文件里直接调用就行。那么应该要进行初始化的设置:
定时器工作方式
单片机内,有其中一个特殊寄存器叫TMOD,这是用来设置定时器工作方式的寄存器,通过软件,将其寄存器内的D0~D7位置0或1,从而达成对定时器的操作。
寄存器TMOD
定时器1
定时器0
位序号
D7
D6
D5
D4
D3
D2
D1
D0
位符号
GATE
C/
M1
M0
GATE
C/
M1
M0
如表格,这是定时器的工作方式寄存器TMOD,要更改定时器的工作方式,我们只用到M1、M2所以其他位一般置0,又因为我们使用的是T0的定时器,所以就有:
0000 0000
使用工作方式0
0000 0001
使用工作方式1
0000 0010
使用工作方式2
0000 0011
使用工作方式3

控制M1、M0将它们置1或0,即可达成操作控制方式的目的,然后转换成16进制即方便查阅。
同理,使用定时器1时也是这么设置。注意,有时候也有使用两个定时器T0、T1的时候,那么就是0001 0001两个都是工作方式1。请大家举一反三。
②设定初值
先说说总值:
以方式1为例(之后会介绍其他方式):
方式1为16位的定时器/计数器,对定时器T0来说是分成两个寄存器(可以形象地比作容器吧,网上有比我更形象的比喻,我就不多写了,请自行查阅):TH0为高八位,TL0为低八位,组成了16位的定时器,当低位TL0计满就向高位TH0移一个数,然后清零。
以12Mhz的晶振来说,机器周期是1us,计满TH0、TL0就需要216-1个数,再来一个数就“溢出”产生中断,一次溢出也就是65536us,约等于65.5ms,如果要定时50ms的话就要给他们装一个预装值(初值),总值-需要值=预装值,
也就是65536-50000=15536,预装后,定时器从预装值开始加值,定时器溢出中断后,会重新从预装值开始加值加到50ms就再产生中断,从而达到了定时的目的。如果要定时1s就可以让定时器中断1000ms/50ms=20次。
另外一点,TH0和TL0中应该装入的总数是15536,然后把15536对256求模:15536/256=60装入TH0中,把15536对256求余:15536%256=176装入TL0中,因为这是两个八位28*28的容器。
所以就有了
TH0=(65535-50000)/256
TL0=(65535-50000)%256
③开启中断和定时器
关于中断,需要用到中断允许寄存器:
IE
位序号
D7
D6
D5
D4
D3
D2
D1
D0
位符号
EA
-
ET2
ES
ET1
EX1
ET0
EX0
位地址
AFH
-
ADH
ACH
ABH
AAH
A9H
A8H

定时器中断需要的是:
总中断EA:用来开启全局中断。
ET0、1、2:各个定时器中断位。
使用中断位只用将其置1就行,例如EA=1;ET0=1;
打开了中断开关只是完成了一半,还需要定时器控制寄存器:
TCON
位序号
D7
D6
D5
D4
D3
D2
D1
D0
位符号
TF1
TR1
TF0
TR0
IE1
IT1
IE0
IT0
位地址
8FH
8EH
8DH
8CH
8BH
8AH
89H
88H

使用方法也是和中断寄存器一样,
定时器0运行控制位TR0:用来开启定时器0.
把TR0置1,TR0=1;就开启了定时器。
2、设置中断服务程序:
中断服务程序:就是当计满TH0、TL0时溢出申请中断,然后单片机允许中断时,所要发生的事情。允许后就自动跳转到中断服务程序,并执行。
在服务程序中,如果不装入初值,那定时器中断服务完成后,就会从0开始重新计时,所以要在中断程序中重新计算并装入初值。
然后给一个变量(变量的意义为中断次数),变量+1,当中断次数达到20次的时候(50ms*20次=1000ms=1s),次数清零,并且让产生指令(例如让二极管亮呀,让I/O口发生什么事呀)。
3、主函数:
由于有了初始化函数,所以直接调用即可(不然主函数很混乱)。
While(1);这段是为了等待函数发生,挺含糊的。
另外:一般中断服务程序中不要写过多的处理语句,否则程序会来不及执行代码,下一次中断又来袭,结果程序久而久之就乱套了。
所以while处可以改成:把if处理语句写到while处。
附上完整程序
二、各个定时器和工作方式:
先来看看工作方式:
工作方式
方式0,13位定时器/计数器
方式1,16位定时器/计数器
方式2,8位自动重装的8位定时器/计数器
方式3,仅适用于T0,分成两个8位计数器,
当设置成T1时停止计数

工作方式有四种:0、1、2、3。我们之前已经学习了方式1的工作方式,那么接下来就先来看看其他的工作方式:
方式0
方式0,的用法和方式1的用法一样,但是值得注意的是:
方式0是13位的定时器,它的低位TL0是五位的,所以它的总值是28*25=8192。它能装的值也不能那么多了,于是就装入5ms:
TH0(8192-5000)/32;
TL0(8192-5000)%32;
32是5位寄存器的容量。
所以要中断200次才能达到1s。
这个方式0可以用来做短时间中断。
方式2
方式0和方式1,当计数溢出后,计数器变为0,所以要反复重新装填初值,这会影响定时精度。但是方式2可以解决这个问题。
如图,其中低位TL0是8位定时器,而TH0是常数缓冲器,当低位TL0溢出时,在溢出标志位TF0置1的同时,自动将高位TH0的常数重新装入TL0中,让TL0从初值开始重新计数,这样就不用人为软件重新装入初值带来的误差,从而提高精度。
由于两个是分开的,所以计算初值可以不用求余取模:
              TL0=总值-要计数的个数;
              TH0=总值-要计数的个数;


以11.0592MHz为晶振,那么机械周期为12x(1/11059200)≈1.085us,以计时1s为例,当要计250个数时耗时1.0851x250=271.275us,再来算计时1s要用多少次,即1000000/271.275≈3686次。
那么就是:

TL0=256-250=6;
TH0=256=250=6;
由于方式2是自动装填,已经不用人为装填了,所以:
中断服务程序中只有一句num++
整个过程就是:

方式3
接下来介绍方式3,方式3不同于其他三个方式,它只能用于T0,也就是定时器0,和方式2差不多,也是把TL0、TH0分成两个独立的寄存器,但是TH0也参与计数,也就是两个独立的8位定时器/计数器。
普通的使用一样,TL0计数溢出后置位TF0,并申请中断,之后重装。但是由于TL0占用了TR0和TF0,所以TH0只能占用定时器              T1的TR1和TF1。所以定时器T1一定不要用在有中断的场合,当然,T1同样可以正常工作在方式0、1、2下。通常这种情况,T1都被用来当做串行口的波特率发生器。
首先把T0、T1的中断位和控制位打开:
然后分别给低位TL0和高位TH0设置中断服务程序:
可以注意到interrupt后面的数值,这个是编译器识别不同中断的唯一符号:
52单片机的中断级别
中断源
默认中断级别
序号(c语言)
入口地址(汇编)
INT0-外部中断0
最高
0
0003H
T0-定时器0中断
第2
1
000BH
INT1-外部中断1
第3
2
0013H
T1-定时器1中断
第4
3
001BH
T1/R1串行口中断
第5
4
0023H
T2-定时器2中断
最低
5
002BH


然后到主函数:
调用init();
可以看到if语句里面的符号是>=,为什么呢?因为当if语句的值到了时,主程序停止下来判断num1==3686是否为真,当它还在判断的时候,num2是还在走的,于是当主程序判断好num1的时候再去判断num2,为时已晚,num2这时可能已经是1844或者1845或者更高的数了,所以要变成>=。

完整的Word格式文档51黑下载地址:
51定时器.docx (148.84 KB, 下载次数: 669)



作者: 天使之泪雨扬    时间: 2017-12-27 11:09
这么好的帖子,都没有人顶?楼主写的非常不错,分享精神值得学习!
作者: ffhhxx    时间: 2018-2-24 11:23
守着这个贴子研究了3个小时,终于搞懂了,看郭天祥视频时要停下来研究一下这里再看视频就顺了,有部分重了,也有个别错字,但绝对是好贴子
作者: endura82    时间: 2018-3-12 19:35
好贴子。我准备将51单片机两个功能合并到一起,正遇到怎么合理用T0和T1。原来两个功能的程序都用到TH0, TL0和TH1,TL1。不知道合并之后怎么实现,看起来T0和T1被重复利用了。

楼主大人能否帮忙解答一下?谢谢啦!
作者: JOESENTION    时间: 2018-3-15 23:53
赞一个,这个很有用,在单片机定时器上的逻辑很清晰,真是我需要的
作者: 564    时间: 2018-5-12 11:55
endura82 发表于 2018-3-12 19:35
好贴子。我准备将51单片机两个功能合并到一起,正遇到怎么合理用T0和T1。原来两个功能的程序都用到TH0, TL0 ...

我也遇到了,你怎么解决的,大佬
作者: 847257243    时间: 2018-5-15 19:13
非常感谢楼主的分享 正在学这方面的知识!
作者: j2510666    时间: 2018-6-27 10:59
这么好的帖子,都没有人顶?楼主写的非常不错,分享精神值得学习!

作者: wdliming    时间: 2018-8-4 17:00
郭天祥的资料上差不多啊~~~
作者: fpy135228    时间: 2018-8-21 08:35
好帖子,真的很不错,值得分享
作者: lumingfei    时间: 2018-9-23 11:37
谢谢,正在努力学习
作者: 飞线    时间: 2018-9-27 09:04
总结的很到位,很有收益
作者: 一片到    时间: 2018-9-28 11:54
这个讲得仔细,值得学习啊。
作者: stkh    时间: 2018-9-28 17:07
很有用,网页保存了
作者: AIYLE520    时间: 2018-10-2 07:18
真是好帖子,新手专用,非常详细!感谢楼主
作者: styleone    时间: 2018-11-28 17:32
实验内容:正常情况下8个小灯按状态点亮,时间间隔为1S。当按下控制按钮后,低四位亮高四位灭,间隔为0.5S后,低四位灭高四位亮。

楼主,想请教你一个问题,对于这个要求,我想用T0定时器给流水灯计时,然后T1定时器用来给外部中断那个0.5秒闪烁计时,我的外部中断服务程序应该怎么写?从流水灯转化到中断服务函数时是不是应该把流水灯初始化一遍?

希望楼主能指点一下

作者: 暗色狸    时间: 2018-12-10 23:02
正准备学习了解定时器相关知识
作者: QAZ1235888    时间: 2019-3-1 14:12
是真的真的很不错,一定得鼓励啊。
作者: qweo23    时间: 2019-3-20 11:46
51单片机定时器最全的资料
作者: sis620    时间: 2019-4-1 10:21
总结很到位的文章,赞
作者: assor    时间: 2019-4-3 15:45
厉害,总结的不错
作者: 快乐眼泪    时间: 2019-4-3 20:19
正在努力学习中!好帖,收藏了
作者: lyw98    时间: 2019-4-18 19:58
帅,详细易懂
作者: qinqin225599    时间: 2019-4-24 11:09
写的是真的真的很不错,值得得鼓励。菜鸟正需要.
作者: huihui9925    时间: 2019-4-24 11:46
看了一会28*28没搞懂,后面终于看懂了是2的8次方.
作者: q1065406715    时间: 2019-4-25 21:14
谢谢,正在努力学习
作者: univers    时间: 2019-4-26 06:26
郭老师的入门宝典
作者: 166864646883    时间: 2019-4-26 09:13
楼主有个小错误,在工作方式1的时候,因为是16位定时器,所以是低八位和高八位组成的,不应该是216-1,而是256-1
作者: uiop5    时间: 2019-4-26 10:50
下学习谢谢谢谢谢谢
作者: keyison    时间: 2019-5-25 21:19
写的很好,收益很多
作者: xiaohaoshifu    时间: 2019-6-4 07:58
写的很详细。我正遇到怎么用T0和T1的使用问题。原来两个功能的程序都用到TH0, TL0和TH1,TL1。不知道合并之后怎么实现,看起来T0和T1被重复利用了。
作者: 江西奉新    时间: 2019-6-7 09:26
现在正在学定时器
作者: hahatomato    时间: 2019-6-26 14:03
守着这个贴子研究了3个小时,终于搞懂了,看郭天祥视频时要停下来研究一下这里再看视频就顺了,有部分重了,也有个别错字,但绝对是好贴子
作者: 321331    时间: 2019-7-3 14:12
写的很好,很详细,赞

作者: 767103079    时间: 2019-7-25 11:29
刚接触单片机3天,学到中断这个知识点,感谢楼主分享的资料,让新手能更懂定时器的各种工作方式
作者: 192141477    时间: 2019-8-17 11:57
之前一直没理解,看了博主的帖子算是懂了定时器和中断的原理。赞
作者: jndy    时间: 2019-10-17 22:48
非常好
作者: zbxiaowu    时间: 2019-10-18 21:50
谢谢,感谢分享
作者: zhangjianhu    时间: 2019-10-19 13:13
非常棒的定时器教程,反复开了好几遍,一定要搞懂。
作者: wdliming    时间: 2019-11-14 12:40
很基础~~
作者: 破音小跳蛙    时间: 2019-11-17 11:35
可以写的简单易懂
作者: hnnnj    时间: 2019-11-17 13:06
谢谢分享
作者: 荔枝陛下    时间: 2019-12-12 13:24
用方式1的时候 为什么TMOD=0x00啊 不应该是TMOD=0x01吗
作者: 2983186218    时间: 2019-12-12 15:47
挺好的  初学很有用
作者: lindeijun1    时间: 2020-1-3 23:46
谢谢楼主分享!!!
作者: jovew    时间: 2020-1-5 09:57
总算是明白计时器 中断的使用了,,
作者: kevintang    时间: 2020-2-2 22:42
不错,是好贴子,谢谢分享。
作者: w1179benp    时间: 2020-3-13 19:09
挺好的  初学很有用
作者: 布吉岛,    时间: 2020-3-14 08:09
谢谢楼主分享
作者: hbcqd    时间: 2020-3-14 16:42
看了这个之后,再看郭天祥的视频就容易理解了,谢谢分享!
作者: ljj3166    时间: 2020-4-4 19:10
总结的很到位,很有收益
作者: Aureliano245    时间: 2020-4-4 20:34
楼主写的不错
作者: laputa1314    时间: 2020-4-14 14:06
哈哈,你以为写的详细我就能看懂了吗?太天真了
作者: Crazy·    时间: 2020-4-14 17:19
看完你的帖子我舒服了兄弟
作者: pxh316    时间: 2020-4-25 16:39
谢谢楼上兄弟分享!
作者: 大华    时间: 2020-5-28 15:37
最近学习中断和定时器,非常有帮助!
作者: xiaobaiyg    时间: 2020-8-4 15:40
该怎么表达我的感谢之情呢?一切尽在不言中!真心感谢!
作者: 大黄狗子246    时间: 2020-8-4 19:46
styleone 发表于 2018-11-28 17:32
实验内容:正常情况下8个小灯按状态点亮,时间间隔为1S。当按下控制按钮后,低四位亮高四位灭,间隔为0.5S ...

我觉得可以用中断来实现时间间隔为一秒,用左移子程序实现流水效果
作者: ddsone    时间: 2020-8-5 18:59
超级详细,赞一个,研究了半天搞好了定时器流水灯才看到这个
作者: 好奇先生1234    时间: 2020-8-6 16:10
温故而知新(^o^)
作者: 肥仔哟    时间: 2020-8-11 01:08
真好,总算知道定时器怎么工作的了,卡这里好多天了
作者: 阡_陌    时间: 2020-8-12 12:03
楼主写的条理清晰,总结的很好,很有用
作者: tangde8    时间: 2020-8-13 22:53
太好了,楼主的教程通俗易懂,看书一直都迷迷糊糊看不懂,不知道说的什么,你这个很详细
作者: mirror.    时间: 2020-8-14 09:51
这么好的帖子,都没有人顶?楼主写的非常不错,分享精神值得学习!
作者: xujuanliang    时间: 2021-3-15 16:23
非常感谢 写的非常好
作者: 星空幻秋    时间: 2021-5-18 12:21
总结的很好
作者: caifei9280    时间: 2021-6-7 22:26
很优质的文章,我研究了2小时,楼主,还有更骄傲的吗
作者: Dekia    时间: 2021-6-22 14:54
这两天设计 正学这单片机 中断 呢 弄了个按键计数 谢谢楼主
作者: blueskynj    时间: 2021-7-7 10:07
28*28建议改成2^8 * 2^8乘方的写法,不然人看了不知道是什么意思,不知道这个28数字从何而来。
作者: lsg0280    时间: 2021-7-7 17:34
这篇文章非常好,让正在学习定时器的我有所体会,谢谢。
作者: gain    时间: 2021-7-7 20:35
564 发表于 2018-5-12 11:55
我也遇到了,你怎么解决的,大佬

合理分配定时器T0和T1的优先级就可以了
作者: gain    时间: 2021-7-7 20:37
styleone 发表于 2018-11-28 17:32
实验内容:正常情况下8个小灯按状态点亮,时间间隔为1S。当按下控制按钮后,低四位亮高四位灭,间隔为0.5S ...

只需要设置T1的中断优先级高于T0即可
作者: 不能再吃了    时间: 2021-9-10 22:09
牛啊,这几天学这个中断程序,都看晕了,感觉很混乱都搞混了,不知道哪个是哪个,看了这篇帖子犹如醍醐灌顶
作者: herui2128    时间: 2021-9-13 17:24
3个定时器用过。但是T1当波特率发生器,T0当定时器就会出现问题,不知道是那个地方没搞起。
作者: pq1972    时间: 2021-9-13 19:00
重点也是难点,谢谢学习
作者: hhwsljb    时间: 2021-10-19 15:27
这篇文字对定时器真是讲得透彻
作者: rp_0825    时间: 2021-10-22 23:46
优秀的发帖者,总结的也很实用,非常感谢
作者: szkalwa    时间: 2021-10-23 16:49
定时中断是难点,好多人卡在这里学不下去,感谢楼主这么详细的解说,谢谢分享!
作者: dyx811    时间: 2021-10-23 22:33
终于搞懂定时器了。谢谢分享!
作者: 朱明辉    时间: 2021-10-24 10:19
51单片机还有个定时器2,再给讲一讲3个定时器同时中断工作就更好了
作者: 猪八戒2179    时间: 2021-12-23 19:04
多谢---------------!
初学者。
作者: lsg0280    时间: 2021-12-24 17:14
仔细看完了,又复习了一次定时器的使用。谢谢。
作者: HAPPY3    时间: 2021-12-29 16:29
看了,有点明白,不明白的多看吧




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1