登录  | 立即注册

游客您好!登录后享受更多精彩

扫一扫,访问微社区

QQ登录

只需一步,快速开始

开启左侧

[寒假笔记] 51单片机之定时器原理详解及配合中断应用

[复制链接]
发表于 2023-1-23 18:40:01 | 显示全部楼层 |阅读模式
学习笔记
学习科目: 51单片机
学习安排: 51单片机定时器
开始时间: 2023-01-04
结束时间: 2023-01-04
本帖最后由 郑中源 于 2023-2-10 17:10 编辑

一、定时器原理的定义
我们如何理解定时器呢?他就像一个闹钟帮助我们去计时,一旦达到了设定的时间,就会提醒我们(在定时器中这个提醒就是“计数的溢出”),而定时器是内置于单片机的。另外,定时器如果不配合“中断”使用,只能达到类似提醒你时间到了的效果,时间到了你总该做点事吧,做事的这个过程就是中断要做的,定时器和中断一般会结合使用,但也不是一定
(图片来源:江科大自化协)
1.png
图中“时钟”相当于秒针,会不断的在钟表上转圈(在单片机中表现为计数值+1),每隔多长时间加1是晶振和定时器模式决定的,计数单元就相当于你设定好的值,达到这个值就会提醒,有了提醒,就会进入中断系统去做临时的事。
2.png
就像图中这样,做完中断系统中的事就继续干主程序的事。




二、定时器详解,如何配置定时器
3.png
首先是这张图,有几种工作模式是看什么型号的单片机,我们一般用模式1,16位定时器,我们以模式1为目标讲解
4.png
1.对TH0,TL0,TF0的配置(字母后边的0都代表这是定时器0的东西,如果是TH1之类的就是定时器1的东西)
首先假设我们已经调好了工作模式(下面会补),TR0这个东西,赋1代表开始自动计数,TH0(高八位)和TL0(低八位)分别是两个八位寄存器(可以不用知道这是什么东西,知道能存的最大数是256就行),TL0中每次计数到256都会溢出,让TH0+1,直到TH0也到256,(此时已经计数256*256=65536个数,很重要,背住!)会产生提醒,这个提醒就是TF0干的事,产生提醒时TF0为1(中断函数执行完毕时会自动变0),TF0为1时此时停止计数。图中C/T是选择定时器还是计数器,这东西既可以定时也可以计数,但此处只讲定时,T是定时器。
附:对于TH0,TL0,TF0的官方解释图:(了解就行)
6.png
2.对定时器模式的配置(下图中不可位寻址的意思是八个值必须同时赋值,不能像点灯那样,可以同时也可以分开)
下面我们来讲如何配置定时器模式(以定时器0举例,一个单片机中一般有多个定时器,视型号而定)
5.png
如图,我们配置TMOD即可配置定时器模式,由于我们不用定时器1,给定时器1的四位全赋0,然后根据图中内容对应,想用16位定时器,我们需要让TMOD=0x01,配置其他模式也可以按图对应(图在手册里有,下面有手册链接)

3.对定时器初始值的配置
配置好定时器模式后,就还差最后一部了,设置TH0和TL0的初始值,为什么要设置初始值呢,上面说过TH0和TL0配合起来能存的最大数是65536,而计数都是从0开始的,如果你不配置初始值,计数的时间是固定的(即从0加到65536这段时间)


那么如何配置初始值呢,这和我们的晶振有关,我们的晶振是32mhz的,定时器默认会先把频率除以12(在你不改变除以几的条件下),即2mhz,这个频率就是一秒钟给你计数2*10^6次,我们取倒数就是周期了,也就是记一次数要花0.5*10^(-6)s,假设你要记x秒的时间,你就要用x/记一次数花的时间,算出要记多少次数,假设为y(如果是其他晶振,也可以这么算)


然后用65536-y,这样计数器就会以65536-y这个数为起点计数,记到65536就停止,根据“TL0中每次计数到256都会溢出,让TH0+1这个原理”此时你要让TH0=(65536-y)/256(即TH0记了多少个256),TL0=(65535-y)%256(即还没记到256的数)。这样就配置好定时器的提醒部分了,代码如下
  1. TMOD=0x01;//0000 0001
  2.           TF0=0;//TF判断是否产生中断 0是没有产生
  3.           TR0=1;//定时器开始工作
  4.           TH0=62770/256;//为了配置1ms的定时器,提前算好预留的数
  5.           TL0=62770%256;//同上
复制代码
其中的62770就是之前提到的65536-y,请根据晶振自行计算(这段代码的晶振是33.几mhz的)



三、定时器配合中断的简单应用
7.png
1.两个开关
当TF0=1时(即计数完毕时),我们可以进入中断系统,图中红线就是代表定时器进入的中断系统,ET0负责定时器对应中断的开关,赋1为闭合,EA为总开关,赋1为闭合,
2.优先级
其中PT0是优先级的设置,如果你用了多个定时器,就需要考虑优先级(即计数完毕后先进入谁的中断),比如你在做作业,同一时间内水烧开了且饭搞糊了,那你就要判断一下这两个哪个先处理,由于我们暂时就只用一个优先级,所以可以不配置,她有自己默认的优先级,要配置时,按照芯片手册配置即可。
以上是要写到定时器的配置里的,这些完成之后我们就可以进行定时器的初始化,代码如下:
  1. <font size="3">void TimerInit()</font>
  2. {         
  3.                 TMOD=0x01;//0000 0001
  4.           TF0=0;//TF判断是否产生中断 0是没有产生
  5.           TR0=1;//定时器开始工作
  6.           TH0=62770/256;//为了配置1ms的定时器,提前算好预留的数
  7.           TL0=62770%256;//同上
  8.           ET0=1;//开关
  9.           EA=1;//开关
  10.           PT0=0;//优先级
  11. }
复制代码


3.中断函数
每个优先级都有自己的查询顺序(如图的官方顺序)
8.png
当你像写中断函数的时候,你就可以按照图中Timer0那个写,名字无所谓,重要的是中断查询顺序(图中的是interrupt1),然后写出中断函数:
9.png
每次进入中断函数后要给TH0和TL0重新赋值,不然就会从0开始计数,然后再在中断函数中加上你要执行的东西,即可。如果你不配置相关代码,出中断函数后,定时器还是在工作的


使用定时器时,要提前在主函数中初始化定时器(在主函数的while之前用一下初始化函数,前面有写)


附:stc12c5a60s2手册: STC-STC12C5A60S2.pdf (2.16 MB, 下载次数: 51)
好懒~~不想说~~~
 楼主| 发表于 2023-1-23 18:48:24 | 显示全部楼层
忘记说了,定时器如果自己配置不好的话,stc的烧录软件有现成的定时器初始化函数,用的时候加上中断部分的开关部分的内容就好。
好懒~~不想说~~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

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