这里说一说定时器的理解学习思路。 定时器其实就是个计数器,我们用得最多的是用于计时,计时这个东西我们应该都明白是个什么东西,手机里的秒表就属于这个东西。手机上是怎么用的?一,调出手机的秒表功能,二归零,三按下开始,四盯着看看到没到我们预定的时间值。 单片机里是一样的流程,先将其设置成计时功能,然后呃不是归零而是设置起始值(初始值),三给个信号让其开始,四不停地查询看其是否计数满值了。这样一说,计时器是不是在你眼中变得很低级? 知道了计时器的工作原理,编程时具体怎么做?查芯片说明书啊,管它什么芯片,都一个查字:计时器功能设置在哪个单元,找地址嘛;初始值要放在哪个单元,启动信号在哪个单元,计满信号(溢出信号)在哪个单元,还是个查字。查到之后,就是修改,怎么修改,还是查说明书啊。 说说为什么要弄个初始值,对于十六位的计时器来说,计时最大值就是65535,再加1就漫出了(溢出)。51单片机的设计上,计数方式是加加加,也就是计数单元中的值是增加方式,如果我们想计数100,从0开始也不是不行,但你要去不断地判断其值是否到了99,这个也不是不行,但有更好的方法,那就是从65436开始,计到溢出,而计数器本身设计了一个功能,就是溢出后就给出一个溢出信号,这个信号存在某一个单元之中(称之为溢出标志,51单片机存在某个单元的某一位上,称之为溢出标志位),程序运行中只需要盯着这个标志位的值就行了,用不着盯计数值。 谈点芯片设计人员的思路,上面说的是计数值加加加,那采用计数值减减减的方式可以不可以实现呢?这个问题并不复杂,我在这里就不罗嗦了。 可以说,这个溢出标志的设计,是很好的设计,定时器的中断功能,也是在这个基础上弄出来的。 有了以上的知识,那我们在应用定时器进行编程时,思路也就很清楚了,首先使用前别忘了标志位应该是零啊,启动位当然也要是零,然后把初始值送进去,然后设置(也可以说是调出)其计时功能(十六位的或八位的,按你的需要),然后把启动位设置成开始(启动),然后不停查询标志位的值。哦还有一点,单片机的定时器不止一个,以上这些动作,只对你所选择的那个定时器进行编程。再有一点,计时完成之后,启动位、溢出标志位等是否需要人工处理,这个要看说明书。 吐槽一下:现有的教材都是告诉你有这些特殊功能寄存器、如何设置这些寄存器,却没怎么讲解为什么机器中存在这些寄存器、为什么需要设置这些项目,这样的结果,自然是让人不容易理解掌握,不能理解的结果,就只能是死记硬背,反正本人特烦死记硬背,没法,记性比别人差,于是只能逼着自己去理解原理,理解了原理,编程就是心中长了竹子。 好了,下面我们就查表,首先是计时功能设置的单元,教材中称之为定时器工作方式寄存器,俗名TMOD,设计在片内数据存储单元中,归于特殊功能寄存器,对这类单元只能直接寻址,不能间接寻址,该单元没有设计位寻址功能,其地址编号为89H,这个单元控制两个定时器的工作模式(标准的51机有两个定时器),高四位控制定时器1,低四位控制定时器0。这四个位的功能在一般的教材上都有讲解,反正如果你想使用十六位计时功能时,将四位设成0001就行了。因为不能位寻址,那一次就得送入一整个字节,所以如果你若让定时器1闲着而用定时器0,那就得把00000001B送入89H单元中,可以用MOV命令将00000001B作为立即数送入89H中(当然你也可以将其先存于某个单元之中再送入),前面说了对于特殊功能寄存器89H这个单元只能直接寻址,那么这个单元的地址就必须直接写在这条语句中,所以这条命令是这样写的:MOV 89H,#00000001B,当然,89H这个单元你可以不用数据地址,而是用其俗名来代替,这个俗名,程序编辑器中已经有了一个,就是“TMOD”,于是,这条命令就可以这样写:MOV TMOD,#00000001B。也当然,如果你不喜欢TMOD这个俗名,你自己取一个自己喜欢自己好记的名字也行。 再就是计数数据单元了,它是十六位,就是两个字节,51机是每个单元里面存的是一个字节的数据,那十六位就得两个字节,就得占用两个单元;51机每个单元都有一个地址编号,那两个单元就得两个地址编号。查说明书,这两个计数单元也属于“特殊功能寄存器”的范畴,不可位寻址,只能直接寻址,所以可以同上面一样的格式编写语句将初始值送入。定时器0的高字节地址编号为8CH,俗名TH0;低字节为8AH,俗名TL0。 再接下来就是启动设置,还有溢出标志,这两个放在一起讲,是因为51机芯片设计中将这两个放在了同一个单元中,只是在不同的位。查说明书,仍属于“特殊功能寄存器”,只能直接寻址,可位寻址,单元地址编号88H,俗名TCON,这一个单元控制两个定时器,其中的第5位(注意,现有教材中的规定是最低位编号为第0位,最高位编号为第7位)是定时器0的启动设置位,这一位的地址编号为8CH,俗名TR0;第6位是定时器0的溢出标志位,这一位的地址编号为8DH,俗名TF0。所以,对这两个位的操作,我们既可以一次送入一个字节到TCON中去,也可以直接操作位。位的操作蛮简单,在51机中,所有的位寻址是只能直接寻址(即在任何时候编写程序时,都只能将其地址直接写在语句中),不具有任何其它的寻址方式。对位的操作51机设计的动作比较少,常用的有两种动作:清零和置位(置位就是置1),51机对位的清零操作码是C2H,汇编助记符CLR;置位的操作码是D3H,汇编助记符为SETB。前面说了,写程序时,只能直接在语句中写它的位地址,所以,编写时,在操作码后面直接写上其位地址就行了,即SETB 8CH(SETB TR0)启动定时器0,CLR 8DH(SETB TF0)清零定时器0的溢出标志。 解释一下51机芯片的位寻址设计。51机的片内数据存储单元中,有一部分单元的位,是统一编有地址的,这个地址是8位地址,编号从0开始,最大255,所以其最多只能对256个位给予地址编号(即最多只有32个单元能有位寻址功能),有了这个地址编号,我们就可以依据这个地址编号,直接找到这个位并进行操作。接下来我们就有了一个疑惑,片内数据存储单元的编号也是从0到255,那么机器是怎么区分这两者而不会弄混的?答案就在操作码上,51机的操作码本身就暗含了接下来的操作的对象是单元还是位,可以这样理解:对单元进行操作的操作码打开的是一道门,门后通向单元;对位进行操作的操作码打开的是另一道门,门后通向位。另外说一句,其它种类的单片机不一定是这样设计的,如stm32的设计,它是统一编号,不管是单元还是位,它们的地址全在0到4G的编号之内。 写得好辛苦啊,没想到会写出这么多。定时器的自动重载和中断,就不写了,有了以上的知识,自己应该可以推理出来吧?
|