历史上的今天
返回首页

历史上的今天

今天是:2024年10月18日(星期五)

正在发生

2019年10月18日 | 关于51单片机的定时器T0、T1总结

2019-10-18 来源:eefocus

这是我总结的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或者更高的数了,所以要变成>=。


推荐阅读

史海拾趣

Cal Test Electronics公司的发展小趣事

随着客户需求的多样化,Cal Test Electronics开始关注小批量定制型测试电缆组件的市场。公司利用自身的技术优势和生产能力,为客户提供个性化的定制服务。这些定制产品不仅满足了客户的特殊需求,也提高了公司的市场竞争力。通过这一策略,Cal Test Electronics成功打开了一个全新的市场领域,为公司的发展注入了新的动力。

ERNI公司的发展小趣事

1947年,瑞士工程师Ernst Rudolf Erni和他的妻子Elsa在瑞士那提空(Nänikon)共同创立了“ERNI & CO.”公司。他们的首个订单是为苏黎世克洛腾机场开发地雷探测器和机场导航灯。这个起点虽小,但为ERNI日后在电子行业的辉煌奠定了基础。随着订单的增多,公司逐渐扩大了生产规模,并开始涉足继电器、电气设备等领域。

CAMBION公司的发展小趣事

CAMBION公司自成立以来,始终将技术创新作为核心驱动力。在早期,公司研发团队成功开发了一款具有革命性的芯片技术,显著提升了电子设备的处理速度和能效。这一技术迅速在行业内引起关注,为CAMBION赢得了大量订单和合作伙伴。随着技术的不断完善和应用范围的扩大,CAMBION逐渐在电子行业中崭露头角。

CML公司的发展小趣事

随着产品线的不断丰富和市场的扩大,CML逐渐意识到品质管理的重要性。公司开始引入先进的质量管理体系,对产品的研发、生产、销售等各个环节进行严格把控。通过持续改进和优化流程,CML成功提升了产品的品质和可靠性,赢得了客户的广泛认可。同时,公司还建立了完善的售后服务体系,为客户提供及时、专业的技术支持和服务,进一步提升了客户满意度。

Heyco公司的发展小趣事

Heyco公司成立于1906年(部分资料提及为1926年或1937年,这里以多个资料综合为准),最初在德国柏林成立。起初,公司专注于制造手工工具,随着汽车工业的兴起,Heyco迅速转型为汽车装配线所需工具的生产商。在二战后,Heyco抓住了汽车工业快速发展的机遇,进一步扩大了生产规模,不仅为德国本土汽车制造商如宝马、奥迪、大众和梅赛德斯奔驰提供定制工具,还逐渐拓展到国际市场。这一时期,Heyco凭借其高质量的产品和卓越的服务赢得了市场的广泛认可。

Hmc Inc公司的发展小趣事

“Global Memory Tech”公司在HMC技术的研发过程中,深刻认识到国际合作的重要性。该公司积极与全球各地的科研机构、高校和行业标准组织合作,共同推动HMC技术的标准化进程。通过不懈努力,Global Memory Tech成功推动了HMC相关标准的制定,为HMC技术的广泛应用奠定了坚实基础。同时,该公司还通过技术授权和合作生产的方式,与多家国际企业建立了紧密的合作关系。

问答坊 | AI 解惑

带有温度自适应调节的LD阵列驱动电源

        传统驱动电源通常采用电流参数预定输入的工作方式,其只能输出给定脉宽!重复频率及峰值的驱动电流,这种方式注定其不能随工作环境的变化而做相应调节而根据的输出特性,通过检测的工作温度,采用温度补偿的 ...…

查看全部问答>

BU72435热卖

本帖最后由 jameswangsynnex 于 2015-3-3 20:01 编辑 RIHM BU72435 …

查看全部问答>

什么是变频器的四象限运行?

1、四象限,用两个正交的数轴把平面分成四个部分,分别为四象限;2、两个数轴分别赋予不同的意义,或者代表不同意义的参数,这时四象限就分别表示参数变化时物体运动或变化的四个状态;3、凡是运动或变化的状态可以用两个独立的具有相反意义的参数 ...…

查看全部问答>

请教驱动测试问题?

大家好,请问各位当你们的驱动写好后如何测试驱动的可靠性,有没有测试规则之类的东西啊,…

查看全部问答>

数据采集卡应用实例讲解

本人没用接触过数据采集卡,但想买一个玩玩。请问哪里有数据采集卡具体应用实例的讲解啊? 或者有谁知道的,请举个例子来说说数据采集卡结合Vc的使用啊?越详细越好!明白了一定给附加分,谢谢了!…

查看全部问答>

Linux 下 java 串口编程(拜求大家的帮助,请大家发发善心吧)

在linux下配置如下:   安装了jdk.1.6.0_10(linnux版)   安装了eclipse(linux) 然后配置环境:   EXPORT JAVA_HOME=/usr/jdk.1.6.0_10   EXPORT PATH=&JAVA_HOME/bin:&PATH   EXPORT CLASSPATH=.:&JAVA_HOME/lib/rt.jar:&JAVA_HOME ...…

查看全部问答>

wince 系统启动声音

请问wince 系统启动时的声音是从那个函数里发出来的?…

查看全部问答>

ISE+synplify流程中约束问题

用synplify进行综合,然后用ISE进行P&R,但是发现synplify综合后,布局布线提示UCF文件中约束的信号找不到而报错,大概是被synplify改名或是优化掉了,但是这个信号很重要,要添加约束的,这个不知道该怎么处理…

查看全部问答>

基于AD型单片机的数字电源设计

 基于AD型单片机的数字电源设计…

查看全部问答>

贴片90129013封装怎么处理???

各位好!我遇到一个基本的问题, 我原理图用到了9012和9013,都是SOT-23封装, 见下图, 这个是9012的原理图: 9013的原理图: 可见基原理图的管脚排布不一样的。我用的是原理图库里的NPN和PNP 我的问题是PCB管脚还得改么?大家是怎么 ...…

查看全部问答>