原创 【博客大赛】MCU之心路分享--定时器和中断(六)

2013-11-22 00:13 3991 19 23 分类: MCU/ 嵌入式 文集: MCU之心路分享

本小节目录:

              6.1,单片机中断及寄存器

              6.2,单片机定时器/计数器介绍

              6.3,定时器程序编写及介绍            

      首先必须提醒:初学单片机定时器和中断时,是比较难理解的,难于知识点多,乱,杂,但又是必须去学会的!否则,不算学会单片机!所以,耐心,坚持学下去,慢慢的总会懂的!

     

6.1)单片机中断及寄存器

一)什么是中断呢?

     生活中例如你正在电脑旁敲击程序中,突然有人敲门,你停止敲击键盘,去开门,这个停止敲击键盘去开门就是中断。

     

     中断的概念
    CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生);
    CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);
    待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断。

  

其流程图如下图。

 

1.jpg

                                                图1  中断流程示意图

 二)中断源 

在52单片机中有6个中断源

    中断号       优先级                中断源                          中断入口地址

 

       0            1(最高)       INT0---外部中断0                0003H

      1            2                       T0 --- 定时器/计数器0          000BH

      2            3                      INT1---外部中断1                0013H

      3            4                        T1 ---定时器/计数器1          0018H

      4            5                      TI/RI  串行口中断                 0023H

      5            6                     T2--- 定时器/计数器2           002BH

                      表 6-1 中断源,中断号及优先级别

 

52单片机的6个中断源简述如下:

INT0—外部中断0,引入端口:P3.2,触发方式:低电平、下降沿。

INT1—外部中断1,引入端口:P3.3,触发方式:低电平、下降沿。

T0—定时器/计数器0中断,触发方式:TO计数器记满归零。

T1—定时器/计数器1中断,触发方式:T1计数器记满归零。

T2—定时器/计数器2中断,触发方式:T2计数器记满归零。

TI/RI—串口中断,触发方式:串口完成一帧字符发送或接收完。

 

三)中断寄存器

    单片机在使用中断功能时,通常需要设置两个与中断有关的寄存器:中断允许寄存器IE和中断优先级寄存器IP

 

所谓的中断允许寄存器就是控制各个中断是开还是关,就是要使用哪个中断,就必须将其打开,也即允许该中断。

IE在特殊功能寄存器中,字节地址为A8H,位地址分别是AFH~A8H(由高到低),由于该字节地址(A8)能被8整除(单片机中能被8整除的地址都可以位寻址),因而可进行位寻址,即可对该寄存器的每一位进行单独操作。IE复位值:0x00,各个位定义如表7-2所示。

 

1)IE—中断允许寄存器

                                    表6-2  IE:中断允许寄存器

Bit

D7

D6

D5

D4

D3

D2

D1

D0

Name

EA

--

ET2

ES

ET1

EX1

ET0

EX0

Address

AFH

--

ADH

ACH

ABH

AAH

A9H

A8H

 

EA:  CPU的总中断允许控制位,

     EA = 1,  CPU开总中断;

     EA = 0,CPU屏蔽所有中断申请。

ET2:定时/计数器T2的溢出中断允许位。

     ET2 = 1,允许T2中断;

     ET2 = 0,禁止T2中断。

ES:串行口中断允许位。

      ES = 1,允许串行口中断;

      ES = 0,禁止串行口中断。

ET1:定时/计数器T1的溢出中断允许位。

      ET1 = 1,允许T1中断;

      ET1 = 0,禁止T1中断。

EX1:外部中断1允许位。

      EX1 = 1,允许外部中断1中断;

      EX1 = 0,禁止外部中断1中断。

ET0:定时/计数器T0的溢出中断允许位。

      ET0 = 1,允许T0中断;

      ET0 = 0,禁止T0中断。

EX0:外部中断0允许位。

          EX0 = 1,允许外部中断0中断;

          EX0 = 0,禁止外部中断0中断。

 

    单片机具有两个中断优先级,即高级优先级和低级优先级,可以实现两级中断嵌套。中断优先级在特殊功能寄存器中,可以通过设置实现各个中断属于中断的哪一级,该寄存器字节地址为:B8H,也能位寻址,即可对每一位单独操作。IP复位值:0x00,各个位定义如表6-3所示。

 

2)IP—中断优先级寄存器

                        表6-3 IP:中断优先级寄存器

Bit

D7

D6

D5

D4

D3

D2

D1

D0

Name

--

--

--

PS

RT1

PX1

PT0

PX0

Address

--

--

--

BCH

BBH

BAH

B9H

B8H

 

PS:串行口中断优先级控制位。

     PS = 1,串行口中断为高优先级中断;

     PS = 0,串行口中断为低优先级中断。

PT1:定时/计数器T1中断优先级控制位。

     PT1 = 1,T1中断定义为高优先级中断;

     PT1 = 0,T1中断定义为低优先级中断。

PX1:外部中断1中断优先级控制位。

     PX1 = 1,外部中断1中断定义为高优先级中断;

     PX1 = 0,外部中断1中断定义为低优先级中断。

PT0:定时/计数器T0的溢出中断允许位。

     PT0 = 1,T0中断定义为高优先级中断;

         PT0 = 0,T0中断定义为低优先级中断

PX0: 外部中断0中断优先级控制位

     PX0 = 1,外部中断0定义为高优先级中断:

     PX0 = 0,外部中断0定义为低优先级中断。

 

在单片机程序执行中

 1)高优先级中断能打断低优先级中断以形成中断嵌套,

 2)同优先级中断间,或低级对高级中断则不能形成中断嵌套,

 3)在没有设置中断优先级情况下,按照默认中断级别执行中断,若设置中断优先级,则按设置顺序先后执行。(上表6.1中可看到各个中断优先级别)

 

 个人感觉:很多刚学的人看到上面那些中断以及IE,IP寄存器时,肯定都蒙了,完全不知道是干什么用的,当然也包括本人刚开始学这些东西时也一样,完完全全不知道天南地北,其实,这些东西不需要去记它,只需要大概去了解,用得时候去查就可以了,然后久而久之就会记住了!当然,也包括下面的定时器的工作方式和寄存器!都不需要去死记,

 

6.2)单片机定时器/计数器

     

 介绍前有几个非常重要的说明:

      1,定时器和计数器的实质都是加1计数器,千万不要理解为计数器是用来计时的,定时器是用来定时的。只是定时器的加1触发源来自单片机内部,而计数器的加1触发源来自单片机外部。计数是指对外部事件进行计数,外部事件的发生以输入脉冲的形式表示,因此计数功能的实质就是对外来的脉冲进行计数。

 

      2,补充一下C语言的“/”和“%”运算,例:73除10等于7余3,也可以看做为:73/10=7  // 求模运算;    73%10=3   // 求余运算。

      3,本人所用STC89C52单片机晶振是12T的,意思是单片机将晶振12分频之后作为自己的主时钟,那么单片机运行的频率:工作频率 = 12MHz / 12 = 1MHz。机器周期 = 1 / 1MHz = 1us,当然大家可以自己算出11.0592MHz对应的机器周期(1.085us)。那要铭记的一个值就是1us。

      

1)定时器/计数器工作方式寄存器TMOD

该寄存器也属于特殊功能寄存器,其字节地址为:89H,该寄存器不能位寻址,定时和计数功能由控制位C/进行选择,TMOD寄存器的各位信息如表6-5所示。可以看出,2个定时/计数器有4种操作模式,通过TMOD的M1和M0选择。2个定时/计数器的模式0、1和2都相同,模式3不同,各个模式下的功能如表6-4所示。

                  表6-4:定时器/计数器工作方式寄存器

2.jpg

每个定时/计数器都有4中工作方式,就是通过设置M1M0来设定,对应关系如表6-5所示。

GATE -- 门控位

   GATE = 0,定时/计数器的启动和禁止仅有TRX(X = 0/1)决定。

   GATE = 1,定时/计数器的启动和禁止由TRX(X = 0/1)和外部中断引脚(INT0/INT1)上的电平(必须是高电平)决定共同决定。

  C/T-- 选择计数器模式还是定时器模式选择位

   C/T = 1,设置为计数器模式;

   C/T = 0,设置为定时器模式。

M1 M0—工作方式选择位

表6-5 TMOD:定时器/计数器工作方式设置表

M1

M0

定时/计数器工作方式

0

0

设置为方式0,为13位定时/计数器

0

1

设置为方式1,为16位定时/计数器

1

0

设置为方式2,8位初值自动重装的8位定时/计数器

1

1

设置为方式3,仅T0工作,分成两个8为计数器,T1停止

 

每个定时/计数器都有4中工作方式,就是通过设置M1M0来设定,对应关系如表6-5所示。

 具体介绍: 

          1)工作方式0(M1M0为00)和1(M1M0为01),分别为13位和16位计数,最多能装(213)=8192和(216)=65536个数就会溢出定时器,且装的数都在,TH0,和TL0寄存器里,需要人为重装初值(具体如何使用,看下面程序介绍)

           2)工作方式2(M1M0为10)为8位初值自动重装,最多能装(28)=256个数,不需要人为重装初值。

          3)关于工作方式3,是将定时器T0分为两个独立的计数器,因为不常用,在此不介绍了!    

 

2)定时/计数器控制寄存器TCON

该寄存器也是特殊功能寄存器,字节地址为88H,位地址由低到高分别是88H~8FH,该寄存器可进行位寻址。TCON的主要功能就是控制定时器是否工作、标志那个定时器产生中断或者溢出等等。复位值:0x00,其各个位的定义如表7-6所示。

                     表6-6TCON:定时器/计数器控制寄存器表

Bit

D7

D6

D5

D4

D3

D2

D1

D0

Name

TF1

TR1

TF0

TR0

IE1

IT1

IE0

IT0

Address

8FH

8EH

8DH

8CH

8BH

8AH

89H

88H

 

外部中断:

     IE0(IE1):外部中断请求标志位

     当INT0(INT1)引脚出现有效的请求信号,此位由单片机自动置1,cpu开始响应,处理终端,而当入中断程序后由单片机自动置0.(外部中断,即外部中断相应的引脚接入低电平或下降沿信号时,中断开始响应。)

        T0(IT1):外部中断触发方式控制位        //选择有效信号

         IT0(IT1)=1:脉冲触发方式,下降沿有效。

     IT0(IT1)=0:电平触发方式,低电平有效。

内部中断:

      TF0(TF1):内部定时器/计数器溢出中断标志位

      当定时器、计数器计数溢出的时候,此位由单片机自动置1,cup开始响应,处理中断,而当进入中断程序后由单片机自动置0.(内部中断实际上就是利用内部的计数器,只不过提供计数的脉冲来自单片机自身。)

  TRO(TR1):定时器/计数器启动位          //启动定时器

      TRO(TR1)=1; 启动定时器/计数器0

      TR0(TR1)=0; 关闭定时器/计数器0

 

     看了上面一大堆的什么中断啊,寄存器啊,EA啊,TR0啊,等等,相信菜鸟都头昏眼花了,显然,当初本人也是晕了好久好久,学单片机当初还差点断送在这里了啊,不过现在回过头了看看,其实也没有什么,也不是很难呀,一句话,用到什么去查什么,程序哪里不懂就看上面哪里,记住哪里,慢慢的日子久了,都会懂的,万里长征需多日走完的啊! 

 

6.3)定时器程序的编写及介绍

下面以定时器0工作方式0为例介绍,别的工作方式1,2,3大同小异!懂0也会容易懂1,2,3呀!

 

介绍一个发光二极管以1S亮灭闪烁程序:

#include

#define Uchar8 unsigned char

#define Uint16 unsigned int

sbit Led1 = P2^0;

Uint16 Counter;

void main(void)

{

1)  TMOD = 0x00;  // 设置定时器0工作方式1

2)  TH0 = (8192-5000)/32;  // 装初值,晶振为12MHZ,定时5ms数为5000

3)  TL0 = (8192-5000)%32;

4)  EA = 1;  // 开总中断         

5)  ET0 = 1;  // 开定时器0中断

6)  TR0 = 1;  // 启动定时器0

7)  while(1);  // 程序在此停留等待中断的发生

}

void Time0_ISR(void) interrupt 1

{

8)    TH0 = (65536-50000)/256; //重装初值

9)    TL0 = (65536-50000)%256;

10) Counter++;

11)    if(Counter==200)  // 累计到200次,说明1秒时间到(200*5ms=1s)

            {

12)       Counter = 0;  // 将变量Counter清0,用于下次计数

13)       Led1 = ~Led1;  // Led取反,LED灯闪烁

            }

}

对于定时器以及中断的学习,上面已经说过,知识点是很乱,多,杂的,但不需要去背,用到了就去查,查多了,用多了就自然熟了!

 

详细介绍程序:

     

     1)TMOD=0x00; 设置定时器0工作方式1,可查上面表6-4和表6-5的介绍

     2)TH0 = (8192-5000)/32;  // 装初值,晶振为12MHZ,定时5ms数为5000

     3)TL0 = (8192-5000)%32;

              a,定时器必须要有一个初值,然后开启定时器的时候,才能从那个初值开始加1计数,例如一杯水要装8192滴才能满,然后溢出杯子,假设1滴水代表1微秒,那么如果你想让杯子5000微秒满,那么就应该先往杯子里装入8192-5000=3192滴水呀!想想是否是这个道理呢?同理,如果我想让定时器满5000微秒(5毫秒)溢出,那就需装一个初值3192呀!

             b,8192-5000=3192为什么对32求模和求余?

            因为这里用到的工作方式0是13位定时器,为高8位TH0和低5位TL0寄存器,需要将3192分解为一个高8位的数,和一个低5位的数,装入TH0和TL0寄存器中

             c, 8),9)中为什么还要重装初值呢?

     上面已经介绍过,工作方式0是不能自动重装初值的,必须人为写程序去装初值,也就是说,水杯里水满后溢出,把水全部倒掉,再装入一定的水,让水把杯子重新滴满!

             d,2),3)还可以写为 TH0=(8192-5000)》5;

                          TL0=(8192-5000)& 0x1F;

 

      4),5),6)查上面表6-2可知,同时必须知道,定时器的使用,必须首先开启总中断,然后开定时器中断,接着开定时器。例如你回你家里的房间上网,必须首先开你家大门,然后**间的门,接着才能上网!

 

      7)while(1);  程序执行到这里后,会一直停留等待中断的发生,中断来了就往下面执行,否则一直等待

 

     10),11),12)Counter自加,当counter满200次时,证明1秒到了(200*5ms=1s),然后先把Counter清0 ,为什么呢?因为清0后,用于下次计数呀!然后才是LED灯闪烁。

 

特别注意:  中断服务程序的写法

void 函数名(void)interrupt 中断号 (using 工作组)

{

   中断服务程序内容

}

关于中断函数说明如下几点,望铭记:

1) 中断函数无返回值,所以前面为void

2) 中断函数命名随便,但一定不能是C语言的关键字,如if、case等,建议大家用:Timer0_ISR、EX0_ISR等

3) 中断函数不带任何参数,所以小括号内写了void

4) 中断函数的关键词interrupt,一定要写且必须正确无误

5) 定时器的中断号见上面的表6—1,必须一一对应,确保准确无误,错了伤不起啊

6) 后面的using 工作组(),通常不写,具体依个人习惯

 

 下面来个小总结:   

  在使用定时器及中断时,必须的过程:

            1)对TMOD赋值,设置使用定时器几,工作方式为几

            2)计算初值,将初值写入TH0,TL0或者TH1,TL1中

           3)设置中断方式时,设置IE中断允许寄存器,用于开放总中断,定时器中断

           4)开启TCON控制寄存器的TR1或者TR0,开始定时或者计数

 

     即使单片机有无数次中断,但永远别对单片机的学习中断和放弃!

 

      本系列《MCU之心路分享》博文,本人将尽自己所能,以菜鸟的身份,写下初学者最详细,最具体的入门博客,同时分享DIY的乐趣,如有误之处,欢迎拍砖,本人也很乐意接受各位大神的批评和指点,在此谢谢啦!

 

                                                                                                2013年11月21日 夜

PARTNER CONTENT

文章评论4条评论)

登录后参与讨论

zhujun74_602010376 2015-8-4 06:26

理解后写出来的文字是有活力的。

zhujun74_602010376 2015-8-4 06:25

理解后写出来的文字是有活力的。

用户342917 2015-4-18 14:45

beaglebone black的CPU就是am335x

DiracFatCat 2015-3-24 15:00

谢谢~

用户1324913 2015-3-24 13:28

都是成长的必经之路,一路走来一路记录,系列的主题不错,是个好习惯.你会做的更好的,加油.

DiracFatCat 2015-3-19 09:01

还没换呢,就是在原来的公司的职业角色变了~

hot.summer_2010_438634915 2015-3-18 14:20

换工作了?去哪家公司啊?给大家分享一下跳槽的经历啊。

用户403664 2014-4-4 15:09

去QQ邮箱的垃圾邮箱看看

用户1745671 2014-4-4 10:48

为什么我老是收不到【QQ邮件的确认信息】,怎么下载程序???哪位可以帮助一下?谢谢。
相关推荐阅读
流年一束光 2014-05-20 13:32
有时候,我也不知道我是否还能坚持下去
       退学?真的要退学么? 这个问题伴随着我整个大学,从第一天开始就一直到现在!       一面是对未来,或许说是梦想的追求,渐渐清晰地看见,并学会接受现实,走在自己选择未来的电子路...
流年一束光 2014-04-07 00:55
【博客大赛】MCU之心路分享-----前言
        如果你想要得到从未有过的东西,那就去做你从未做过的事情!!!                                                          ...
流年一束光 2014-04-07 00:46
【博客大赛】MCU之心路分享--倾听你的改变--AD/DA转换(十一)
         用勇气来改变可以改变的事情,用胸怀来接受不可改变的事情,用智慧来分辨两者的不同                                                  ...
流年一束光 2014-04-05 17:28
【博客大赛】MCU之心路分享—有种爱叫:IIC(十)
         在工科男的世界里,连IIC都能想象成浪漫的牵手,而一个对单片机充满热爱的工科男,有什么理由不去认识它,学会它,并去驾驭它啊!当然,在我知道的世界里,貌似大学老师从来都没有真正教过...
流年一束光 2014-03-20 00:34
【博客大赛】MCU之心路分享—你小小的心令我感动(九)
          如果说,学过单片机,却连单片机最小系统都没有焊接过或者搭建过!甚至连电烙铁都没有摸过,那是个多么巨大的笑话呀?          但现实不幸的是,这样的笑话,一直重演在许多...
流年一束光 2014-03-10 20:29
【博客大赛】MCU之心路分享—偷偷爱你--12864液晶(八)
       时隔3个月没有更新《MCU之心路分享》了,不知道我是否有幸,让胖螃蟹小编对我拍拍砖呢?嘿嘿…….这3个月,一直都没有离开过EDN,一直都潜伏着,这3个月中,见证,陪伴,小小地参与...
EE直播间
更多
我要评论
4
19
关闭 站长推荐上一条 /1 下一条