1、定时器中断原理#define _1231_C_#include “reg51.h“/sbit OE=P23;unsigned int SystemTime;void timer0(void) interrupt 1 using 3 /中断部分代码,见下文的释疑TH0 = 0xdb;TL0 = 0xff;/ TF0 = 0;SystemTime+;void main()TMOD TMOD |= 0x01; /TMOD的值表示定时器工作方式选择TH0 = 0xdb; /写入初始值,初始值可以决定定时多久TL0 = 0xff;/根据下文的木桶比喻的话,如果 TH0 = 0x00;TL0 = 0x00
2、;则表示从桶底开始装水。/TH0 = 0xdb;TL0 = 0xff;可以这样子理解相当于木桶里已经有部分液铅在里面,/TH0和 TL0这个两个值表示木桶里液铅的高度,即此时桶里只能从液铅的高度以上开始装水,/TH0 = 0xff;TL0 = 0xff;即表示桶的最高位置.TF0 = 0; /计数到时 TF0为 1,即当 TH0 = 0xff;TL0 = 0xff;再运行一步 TF0 = 1;TR0 = 1; /开始计数,从这时起,每运行一步 TH0和 TL0都会增加,直到 TH0 = 0xff;TL0 = 0xff;/相当于开水龙头,如 TR0=0则 TH0和 TL0不变ET0 = 1; /
3、允许定时器 0中断EA=1; /开总中断/下面是个死循环,程序里每运行一步 TH0和 TL0都会增加,当增加到TH0 = 0xff;TL0 = 0xff;/单片机会从死循环里退出,去执行中断部分的代码,即开始运行 void timer0(void) interrupt 1 using 3/运行完中断部分的代码后,接着继续执行死循环里的代码。/注意:当 TH0 = 0xff;TL0 = 0xff;再运行,TF0 并没有从 0变为 1,个人猜测 TF0=1;时触发了中断,并重新被置零。/如把 ET0 = 1;和 EA=1;注释掉,当 TH0 = 0xff;TL0 = 0xff;再运行,TF0会变为
4、 1,此时不会再执行中断部分代码。while(1)if (SystemTime%100)50) /SystemTime除以 100,余数小于 50为真;else;;释疑:void Timer0() interrupt 1 using 1Timer0 是函数名,随便取的interrupt xx using y跟在 interrupt 后面的 xx 值得是中断号,就是说这个函数对应第几个中断端口,一般在 51中0 外部中断 0 1 定时器 02 外部中断 13 定时器 14 串行中断实际上编译的时候就是把你这个函数的入口地址方到这个对应中断的跳转地址using y 这个 y是说这个中断函数使用的那
5、个寄存器组,51 里面一般有 4组 r0 - r7 寄存器,一共有 32个,如果你的终端函数和别的程序用的不是同一个寄存器组则进入中断的时候就不会将寄存器组压入堆栈返回时也不会弹出来节省代码和时间初始值算法:定时器是当总数达到 FFFFH后产生中断吧!那你要让它计数10000,是不是用 FFFF(16 进制)减去 10000(十进制)的数当计数初值 啊?TH0=-(10000/256); TL0=-(10000%256)跟 FFFF(16 进制)减去 10000(十进制)的数是一样的。从 TH0=-(10000/256); TL0=-(10000%256)开始计数,计数到10000刚好满。跟用
6、 FFFF(16 进制)减去 10000(十进制)的数一样!写起来更简单,不 用算!看看原码、补码就知道。正数的补码是对应的二进制数,符号位为零,负数的补码是它的绝对值对应的二进制数按位取反再加一,符号位为一。无符号数不考虑符号,那么这个结果就跟用 FFFF减去它的绝对值一样我们学习了用指令延时闪灯,但是用指令方式闪灯有 cpu不能做其他工作的缺点。这一课,我们将学习如何使用定时器方式使灯闪烁。中断的理解。这里将涉及到单片机中断的应用,在 cpu的一步步按照指令运行的过程中(主程序),可能会有其它的更紧急的需要做的事情(中断服务程序),需要cpu暂时停止当前的程序(主程序),做完了(中断服务程
7、序)之后,又可以继续去运行先前的程序(主程序)。就像你正在吃饭,一边又在给水桶里放水,吃着吃着,水满了,你就得赶快去把水龙头关掉或者换一个空的水桶,再回来吃饭。单片机的定时器就像是一个水桶,你让它启动了,也就是水龙头打开了;开始装水了;定时在每个机器周期不断自动加 1,最后溢出了;水桶的水不断增加,最也就满出来了;定时器溢出时,你就要去做处理了;水桶的水满了,你也应该处理一下了;处理完后,单片机又可以回到刚刚开停止的地方继续运行;水桶处理了,先前你在做什么也可以继续去做什么了。单片机的主程序是从 0x0000开始运行的,单片机服务程序从哪里开始运行呢?在 51里,有多个中断服务程序入口,0 号
8、入口是外中断 0,地址在0x0003;1 号入口是定时器 0,在 0x000B;2 号入口是外中断 1;地址在0x0013,3 号入口是定时器 2;地址在 0x001B,等等。当中断发生时,程序就记下当前运行的位置,跳到对应的中断入口去运行中断服务程序,运行完之后,又跳回到原来的位置继续运行。在 C51中,你不用理会中断服务程序放在哪里,会怎么跳转。你只要把某个函数标识为几号中断服务函数就可以了。在发生了对应的中断时,就会自动的运行这个函数。请看一下相关的 51的硬件的书,对定时器工作的寄存器设置做进一步的了解。也可以做完试验再了解,因为例程中都已经为您设置好了。请看程序,主程序里的循环里是个
9、死循环,什么也没有做,在实际应用中这里是放的主程序。在定时器服务函数里,需要重新置入定时器的值,这样才能保证每次溢出时,都是你指定的时间。这里置入的是 0x0006,还需要走 0x10000-0x0006 个机器周期才溢出。换成 10进制也就是每 65530个机器周期中断一次。我们仿真的晶振是 22118400HZ,每 12个时钟一个机器周期。6553012/221184000.036 秒。也就是差不多 28HZ的闪烁频率。因为 51的定时器最大只有 0xffff,溢出的速度很快,无法做出更久的闪烁频率来,这一课就先观察一下这个 28HZ左右频率。在下一课我们会用静态变量的办法,做一个长达 1
10、秒钟的 LED闪烁频率。另外,由于 51从中断发生到进入中断的时间不定,是 3至 8个机器周期,我们在进入了中断后才重新置新的定时器初始值,这样就会存在定时误差。也就是不是精确定时,如果要精确定时,需要使用定时器自动装载方式,也就是在定时器溢出的同时,硬件逻辑就自动把定时器初始值装载进去了,而不是在中断服务程序里赋初始值,这样就可以实现精确定时,误差只出现晶振的频率上。这是下一颗的内容。现在请仔细研究一下程序,并编译,进入仿真,全速运行,观察运行结果。我们可以看到 P10上的 LED在快速闪烁。顺便,也请再练习一下停止,单步,断点等等的调试方法。一个特殊的地方,使用 DX516在单步时运行时,可能无法进入到中断服务函数中。这是因为中断函数可能在单步处理的瞬间已经运行过去了。如果要单步调试中断服务函数,请在中断服务函数内设置断点,再点全速。稍后就会停止在断点上,就可以继续单步运行了。
Copyright © 2018-2021 Wenke99.com All rights reserved
工信部备案号:浙ICP备20026746号-2
公安局备案号:浙公网安备33038302330469号
本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。