单片机交流
直播中

乐骞添

7年用户 975经验值
私信 关注
[问答]

关于51单片机中断与定时器的知识点总结的太棒了

关于51单片机中断与定时器的知识点总结的太棒了

回帖(1)

贾埃罗

2021-10-8 15:22:47
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时停止计数      
      

单片机内,有其中一个特殊寄存器叫TMOD(1个字节),这是用来设置定时器工作方式的寄存器,通过软件,将其寄存器内的D0~D7位置0或1,从而达成对定时器的操作。
  寄存器TMOD


                 定时器1     
     
                 定时器0     
     






                 位序号     
     
                 D7     
     
                 D6     
     
                 D5     
     
                 D4     
     
                 D3     
     
                 D2     
     
                 D1     
     
                 D0     
     
                 位符号(是什么)     
     
                 GATE     
     
                 C/      







     
     
                 M1     
     
                 M0     
     
                 GATE     
     
                 C/      







     
     
                 M1     
     
                 M0     
     
要更改定时器的工作方式,我们只用到M1、M2所以其他位一般置0,又因为我们使用的是T0的定时器,所以就有:
   
                    0000 0000      
      
                    使用工作方式0      
      
                    0000 0001      
      
                    使用工作方式1      
      
                    0000 0010      
      
                    使用工作方式2      
      
                    0000 0011      
      
                    使用工作方式3      
      

同理,使用定时器1时也是这么设置。注意,有时候也有使用两个定时器T0、T1的时候,那么就是0001 0001两个都是工作方式1。





可能一般就是往这里面一直计数,方式1为16位的定时器/计数器,对定时器T0(TH0和TL0)来说是分成两个寄存器,TH0为高八位,TL0为低八位,组成了16位的定时器,当低位TL0计满就向高位TH0移一个数,然后清零。
12M的晶振,它的时间周期就是1/12 us。反正机器周期是1us(应该是加1的机器周期)。51单片机是12分频的,如果选用12M晶振,如果是单指令周期的语句(例如i++),刚好是1us,其他语句好似1us的整数倍。这样计算指令时间很方便。
对于利用51单片机进行串口通讯的,一般会就会选用11.0592M晶振了,因为对于9600,4800的波特率,11.0592M晶振计算时正好可以得到整数。而且一条单指令语句也大约是1us。
计满TH0、TL0是65536us(2^16=65536),约等于65.5ms,如果要定时50ms的话,也就是50ms触发一次,可以预装65536-50000=15536us,这样就自动触发了。定时器溢出中断后,会重新从预装值开始加值加到50ms就再产生中断,从而达到了定时的目的。如果要定时1s就可以让定时器中断1000ms/50ms=20次。用软件实现就好了。
另外实际操作时,把15536对256求模:15536/256=60装入TH0中,把15536对256求余:15536%256=176装入TL0中,因为这是两个八位28*28的容器。
用定时器,就必须开启中断了,关于中断,需要用到中断允许寄存器:
  IE
   
                    位序号      
      
                    D7      
      
                    D6      
      
                    D5      
      
                    D4      
      
                    D3      
      
                    D2      
      
                    D1      
      
                    D0      
      
                    位符号      
      
                    EA      
      
                    -      
      
                    ET2      
      
                    ES      
      
                    ET1      
      
                    EX1      
      
                    ET0      
      
                    EX0      
      
                    位地址      
      
                    AFH      
      
                    -      
      
                    ADH      
      
                    ACH      
      
                    ABH      
      
                    AAH      
      
                    A9H      
      
                    A8H      
      

51单片机内的寄存器还蛮多的。。。
  定时器中断需要的是:
  总中断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;就开启了定时器。
每次的中断函数就填入初值,如果不装入初值,那定时器中断服务完成后,按原理就会从0开始重新计时,并执行自己的事件就可以了。
另外:一般中断服务程序中不要写过多的处理语句,否则程序会来不及执行代码,下一次中断又来袭,结果程序久而久之就乱套了。解决方法就是多线程,不是吗。看下面





说这样就没关系。。。
方式0(13位定时器),的用法和方式1的用法一样,但是值得注意的是:





  方式0是13位的定时器,它的低位TL0是五位的(兼容8048单片机的13位定时器,现在很少用到了 ),所以它的总值是28*25=8192。它能装的值也不能那么多了,于是就装入5ms:
  TH0(8192-5000)/32;
  TL0(8192-5000)%32;
  32是5位寄存器的容量。
  所以要中断200次才能达到1s。
  这个方式0可以用来做短时间中断。
方式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次。
在设计51系列的单片机系统时,一般选用11.0592MHz的晶振而不选用12MHz的晶振,为什么?12M的晶振,振荡频率明显高于11.0592M的,按理说12MHz的晶振可以提高单片机的性能,而且整数更好算,那么我们为什么不用12M的呢?这个问题与单片机的串口波特率有关。由于在进入中断、装值、出中断这个过程中,很容易产生时间上的微小误差,当多次操作时微小误差不断累积,终会产生错误。而方式2,由于当定时器计满溢出后单片机自动为其装载初值,并且无需进入中断服务程序进行任何处理,这样定时器溢出的速率就会相对更稳定。说白了,用12M晶振会有8%的误差,用11M晶振的误差为0.
理论上,要使采集的数为正确的,则第8位必须正确(采样16次,取第7,8,9次),则允许发送一字节累加误差不能超过50%,单个的位误差不能超过50/10*100% = 5%,由此可知在9600的波特率下,使用12MHz的晶振时,单个位超过5%,必定会出现传错的位。使用12MHz的晶振在2400波特率下还是可以忍受的,但是超过2400后通信变得极不可靠。(为了保证有效通讯,根据电、传输介质等的物理特性结合串口设备的使用要求,确定RS232最大传输速率只能是115200,然后逐级二分得到57600、28800、19200。。。。为适应这些速率设计的相应的晶振频率。不管哪种说法都是先有波特率在有晶振频率的,也就是,波特率是前人在试验下得出的最佳的通信速率,我们使用的时候直接用现有的通信速率就行,但是要注意单片机使用的晶振频率,使用时会不会使串口产生误差,如果误差太大就会产生通信错误。)
以上还是根据方式2来讨论的,因此对于串口传输来说,必须使用自动方式,方式2,用方式1误差就不知道差到哪里去了。
用11.0592晶振的原因是51单片机的定时器导致的,用51单片机的定时器做波特率发生器时,如果用11.0592Mhz的晶振,根据公式算下来需要定时器设置的值都是整数;如果用12Mhz晶振,则波特率都是有偏差的。用12MHz,最高也就4800,而且有0.16%误差率,但在允许范围,所以没多大影响。
如果用于串口通信,建议选用11.0592M的或22.184M,选择晶振最主要还是参照说明书。
对单片机而言一个机器周期等于12个时钟周期,51单片机串口工作在方式1(自己控制装载的16位)上时,给串口使用的时钟频率要先除2,再除16,为什么要除2呢?因为实际上对于单片机的串口及外部的通信模块来说,单片机的晶振频率即使在12分频后,依然太快,所以先除2,降低串口模块所使用的的时钟频率。为什么要除16呢?因为在串口通信中为了保证所接收的数据的正确性,先对每位信号采集16次,再取其中的7、8、9次,如果有两次是高电平,就认定这一位是1,如果有2位是低电平,就认定这一位是0,所以,公式中频率要除16,。至于为什么要除12是因为公式中的频率Fosc是晶振频率(固件发出的原始频率),但是单片机所使用的的频率是经过了12分频的。所以对单片机而言一个机器周期等于12个时钟周期
1个时钟周期  =1晶振周期 = 1Fosc(如常见的外接12M晶振,那它的时钟周期=1/12M。)
1个机器周期 =  12*(1Fosc)(8051系列单片机的机器周期=12*时钟周期。之所以这样分是因为单个时钟周期根本干不了一件完整的事情(如取指令、写寄存器、读寄存器等),而12个时钟周期就能基本完成一项基本操作了。)
定时器T1的计数值每经过一个机器周期加1,即每经过12*(1Fosc)秒,TL1加1,当TL1等于256就溢出,TH1将值重新赋给TL1,TL1开始重新计数。
方式3不同于其他三个方式,它只能用于T0,也就是定时器0,和方式2差不多,也是把TL0、TH0分成两个独立的寄存器,但是TH0也参与计数,也就是两个独立的8位定时器/计数器。
TL0计数溢出后置位TF0,并申请中断,之后重装。但是由于TL0占用了TR0和TF0,所以TH0只能占用定时器T1的TR1和TF1。所以同时要用定时器T1的话,一定不要用在有中断的场合(emmm,可能就是波特率发生器吧),当然,T1同样可以正常工作在方式0、1、2下。通常这种情况,T1都被用来当做串行口的波特率发生器。波特率发生器的作用是从输入时钟转换出需要的波特率clk,即波特率时钟频率。所以这时候T1更多表示一个时钟功能。T表示Timer,反正就是这么个概念,干什么都行。
  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     
     
注意TH0是直接占据T1的中断,就连终中断号也占据了。
用法就是这样的。
说了这么多,其实最保险的做法,就是用外置定时器,因为单片机本身定时器作用来做时钟是不准的,单片机内部指令执行也是要花一些时间的,而DS1302是专门的时钟芯片,DS1302是由美国DALLAS公司推出的具有涓细电流充电能力的低功耗实时时钟芯片。它可以对年、月、日、周、时、分、秒进行计时,且具有闰年补偿,可以在断电的时候 继续计时,一节纽扣电池做备用电源工作一两年,操作简便等多种功能。这么香怎么能不用呢?



举报

更多回帖

发帖
×
20
完善资料,
赚取积分