×
单片机 > 单片机程序设计 > 详情

C51单片机学习(二):中断系统和定时器

发布时间:2020-08-31 发布时间:
|

中断系统:

中断概念

CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断发生); 

CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务); 

待CPU将事件B处理完毕后,再回到原来事件A被中断的地方继续处理事件A(中断返回),这一过程称为中断 。


中断的结构图

  

其中一些说明: 

1、(P3.2)可由IT0(TCON.0)选择其为低电平有效还是下降 

沿有效。当CPU检测到P3.2引脚上出现有效的中断信号时, 

中断标志IE0(TCON.1)置1,向CPU申请中断。 

2、(P3.3)可由IT1(TCON.2)选择其为低电平有效还是下降沿有效。当CPU检测到P3.3引脚上出现有效的中断信号时,中断标志IE1(TCON.3)置1,向CPU申请中断。 

3、TF0(TCON.5),片内定时/计数器T0溢出中断请求标志。当定时/计数器T0发生溢出时,置位TF0,并向CPU申请中断。 

4、TF1(TCON.7),片内定时/计数器T1溢出中断请求标志。当定时/计数器T1发生溢出时,置位TF1,并向CPU申请中断。 

5、RI(SCON.0)或TI(SCON.1),串行口中断请求标志。当串行口接收完一帧串行数据时置位RI或当串行口发送完一帧串行数据时置位TI,向CPU申请中断。


TCON的中断标志

  

说明: 

T0(TCON.0),外部中断0触发方式控制位。 

当IT0=0时,为电平触发方式。 

当IT0=1时,为边沿触发方式(下降沿有效)。 

IE0(TCON.1),外部中断0中断请求标志位。 

IT1(TCON.2),外部中断1触发方式控制位。 

IE1(TCON.3),外部中断1中断请求标志位。 

TF0(TCON.5),定时/计数器T0溢出中断请求标志位。 

TF1(TCON.7),定时/计数器T1溢出中断请求标志位。


SCON中断标志

  

RI(SCON.0),串行口接收中断标志位。当允许串行口接收数据时,每接收完一个串行帧,由硬件置位RI。注意,RI必须由软件清除。 

TI(SCON.1),串行口发送中断标志位。当CPU将一个发送数据写入串行口发送缓冲器时,就启动了发送过程。每发送完一个串行帧,由硬件置位TI。CPU响应中断时,不能自动清除TI,TI必须由软件清除。


关于优先级:

51单片机中断优先级: 

CPU同时接收到几个中断时,首先响应优先级别最高的中断请求。 

正在进行的中断过程不能被新的同级或低优先级的中断请求所中断。 

正在进行的低优先级中断服务,能被高优先级中断请求所中断。


为了实现上述后两条原则,中断系统内部设有两个用户不能寻址的优先级状态触发器。其中一个置1,表示正在响应高优先级的中断,它将阻断后来所有的中断请求;另一个置1,表示正在响应低优先级中断,它将阻断后来所有的低优先级中断请求。


同一优先级中的中断申请不止一个时,则有中断优先权排队问题。同一优先级的中断优先权排队,由中断系统硬件确定的自然优先级形成,其排列如所示:


中断响应条件:

中断源有中断请求; 

此中断源的中断允许位为1; 

CPU开中断(即EA=1)。


实例(外部中断0)

 /*以下设置的时候数码管开始从0到f循环,当触发中断(杜邦线将GND和P3^2口连接)

 此时因为IT0默认为0,所以是低电平触发,由此LED灯亮,松开时,灯灭。将IT0置为1是,即下降沿有效

 此时将P3^2引脚杜邦线接入瞬间LED灯亮,继续接入或者拔开灯灭*/

#include

#define uint unsigned int 

#define uchar unsigned char 

sbit dula=P2^6;

sbit wela=P2^7;

sbit d1=P1^0;

uchar num,flag = 0;

uchar code table[]={

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71};

void delay(uint z);

void init(){

    EA=1;//开总中断

    EX0=1;//开外部中断0

    //IT0=1;   //寄存器内默认全为0,IT0为1则是下降沿有效,否则是低电平有效,可以通过杜邦线和GND接口连接达到测试目的

    //TCON=0x01;  //和上面一句含义一样,具体看上面TCON的说明

    wela=1;//11111110   //位选第一个数码管

    P0=0xfe;

    wela=0;


}

void main(){

    init();

    while(1){

        for(num=0;num<16;num++){

                d1=1;

                dula=1;

                P0=table[num];

                dula=0;

                delay(1000);    

            }


    }

}


void delay(uint z){

    uint x,y;

    for(x=z;x>0;x--)

        for(y=110;y>0;y--); 

}


void exter0() interrupt 0{ //中断控制的函数

    d1=0;

}


定时/计数器

51单片的定时器可以使用1.软件中断(就是上面的delay函数),2.可编程芯片定时,3.时基电路定时(定时值和范围不能由软件控制)


这里主要阐述第二种:


定时/计数器的工作原理

加1计数器输入的计数脉冲有两个来源,一个是由系统的时钟振荡器输出脉冲经12分频后送来;一个是T0或T1引脚输入的外部脉冲源。每来一个脉冲计数器加1,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使TCON中TF0或TF1置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。 

可见,由溢出时计数器的值减去计数初值才是加1计数器的计数值。


设置为定时器模式时,加1计数器是对内部机器周期计数(1个机器周期等于12个振荡周期,即计数频率为晶振频率的1/12)。计数值N乘以机器周期Tcy就是定时时间t 。 

设置为计数器模式时,外部事件计数脉冲由T0或T1引脚输入到计数器。在每个机器周期的S5P2期间采样T0、T1引脚电平。当某周期采样到一高电平输入,而下一周期又采样到一低电平时,则计数器加1,更新的计数值在下一个机器周期的S3P1期间装入计数器。由于检测一个从1到0的下降沿需要2个机器周期,因此要求被采样的电平至少要维持一个机器周期。当晶振频率为12MHz时,最高计数频率不超过1/2MHz,即计数脉冲的周期要大于2 s。 (了解下就好)


50c51主要由两个寄存器TMOD,TCON控制


TMOD

  

GATE:门控位。GATE=0时,只要用软件使TCON中的TR0或TR1为1,就可以启动定时/计数器工作;GATA=1时,要用软件使TR0或TR1为1,同时外部中断引脚或也为高电平时,才能启动定时/计数器工作。即此时定时器的启动多了一条件。(一般置为0) 

:定时/计数模式选择位。 =0为定时模式; =1为计数模式。 

M1M0:工作方式设置位。定时/计数器有四种工作方式,由M1M0进行设置。


定时器4种工作方式

TCON

  

TF1(TCON.7):T1溢出中断请求标志位。T1计数溢出时由硬件自动置TF1为1。CPU响应中断后TF1由硬件自动清0。T1工作时,CPU可随时查询TF1的状态。所以,TF1可用作查询测试的标志。TF1也可以用软件置1或清0,同硬件置1或清0的效果一样。 

TR1(TCON.6):T1运行控制位。TR1置1时,T1开始工作;TR1置0时,T1停止工作。TR1由软件置1或清0。所以,用软件可控制定时/计数器的启动与停止。 

TF0(TCON.5):T0溢出中断请求标志位,其功能与TF1类同。 

TR0(TCON.4):T0运行控制位,其功能与TR1类同。


关于定时器的初始化

推荐:定时器的初始化


定时器实例(定时器工作方式1)


//关键:init函数和中断的time0函数

//通过定时器控制数码管从0到f循环显示

#include

#define uint unsigned int 

#define uchar unsigned char 

sbit dula=P2^6;

sbit wela=P2^7;

sbit d1=P1^0;

uchar num,num1;tt;

uchar code table[]={

0x3f,0x06,0x5b,0x4f,

0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,

0x39,0x5e,0x79,0x71};

void delay(uint z);

void init(){    

    TMOD=0x1;//设置定时器0为工作方式1

    TH0=(65536-10000)/256;

    TL0=(65536-10000)%256;

    EA=1;//开总中断

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

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

    wela=1;//11101010

    P0=0xea;

    wela=0;

    dula=1;

    P0=0x3f;

    dula=0;

}

void main()

{

    num=0;

    tt=0;

    init();

    while(1){

        if(tt==100)

           {

                tt=0;

                num++;

                if(num==16)

                num=0;

                dula=1;

                P0=table[num];

                dula=0; 

            }

    }

}


void delay(uint z)

{

    uint x,y;

    for(x=z;x>0;x--)

        for(y=110;y>0;y--); 

}


void time0() interrupt 1

{

    TH0=(65536-10000)/256;

    TL0=(65536-10000)%256;

    tt++;

}


声明

大多数代码实例借鉴郭天祥的视频,我只是添加了部分注释,看起来更清晰。^-^



『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
AVR熔丝位操作时的要点和需要注意的相关事项