中断与定时计数

一、概念简述

1、中断

中断是指计算机系统中发生的一种事件,可以打断正常的程序执行流程。中断可以由硬件或软件触发,用于处理紧急事件、外部设备请求、错误处理等。在中断发生时,当前正在执行的程序会被暂停,系统会转而执行中断处理程序来响应中断事件,处理完毕后再返回到原程序继续执行。这种机制可以提高系统的响应速度和效率。

2、定时器

定时器是计算机系统中的一种重要组件,用于在特定的时间间隔或特定时间点触发事件。定时器可以用于各种用途,例如调度任务、测量时间间隔、生成时钟信号等。

在计算机系统中,定时器通常由硬件和/或操作系统提供支持。硬件定时器是一个计数器,可以在每个时钟周期递增,当计数器达到预设的值时触发中断。操作系统也可以通过软件定时器来实现类似的功能,通过编程设置定时器的计时器和中断处理程序来实现定时功能。

定时器在计算机系统中有着广泛的应用,例如在操作系统中用于任务调度、在网络通信中用于超时处理、在实时系统中用于实时任务的处理等。定时器的准确性和稳定性对系统的性能和可靠性都有着重要的影响。

二、按键中断控制流水灯

1、单一外中断

实验原理:

在单片机P1口上接有8只LED。在外部中断0输入引脚(P3.2)接一只按钮开关K1。要求将外部中断0设置为电平触发。程序启动时,P1口上的8只LED全亮。每按一次按钮开关K1,使引脚接地,产生一个低电平触发的外中断请求,在中断服务程序中,让低4位的LED与高4位的LED交替闪烁5次。然后从中断返回,控制8只LED再次全亮。

Proteus原理图:

C语言代码:

#include <reg51.h>
#define uchar unsigned char

// 延时函数Delay( ),i形式参数,不能赋初值
void Delay(unsigned int i) 
{	
    unsigned int j;
    for(; i > 0; i--)        
        for(j = 0; j < 333; j++)     // 晶振为12MHz,j的选择与晶振频率有关
        {;}                          // 空函数
}

// 主函数
void main()         
{
    EA = 1;           // 总中断允许
    EX0 = 1;          // 允许外部中断0中断
    IT0 = 1;          // 选择外部中断0为跳沿触发方式
    while(1)          // 循环
    {                
        P1 = 0;       // P1口的8只LED全亮
    }                
}

// 外中断0的中断服务函数
void int0() interrupt 0 using 0   
{
    uchar m;
    EX0 = 0;          // 禁止外部中断0中断
    for(m = 0; m < 5; m++)    // 交替闪烁5次
    {
    P1 = 0x0F;      // 低4位LED灭,高4位LED亮     
    Delay(400);       // 延时
    P1 = 0xF0;        // 高4位LED灭,低4位LED亮
    Delay(400);       // 延时
	}
    EX0 = 1;          // 中断返回前,打开外部中断0中断
}

Proteus仿真效果图:

开发板效果:

2、双外中断

实验原理:

在单片机P1口上接有8只LED.在外部中断0输入引脚(P3.2)接有一只按钮开关K1.在外部中断1输入引脚(P3.3)接有一只按钮开关K2。要求K1和K2都未按下时,P1口的8只LED呈流水灯显示,仅K1 (P3.2)按下再松开时,上下各4只LED交替闪烁10次,然后再回到流水灯显示如果按下再松开K2 (P3. 3)时,P1口的8只LED全部闪烁10次,然后再回到流水灯显示。设置两个外中断的优先级相同。

Proteus原理图:

C语言代码:

#include <reg51.h>
#define uchar unsigned char

void Delay(unsigned int i) // 延时函数Delay( ), i为形式参数,不能赋初值
{
    uchar j;
    for (; i > 0; i--)
        for (j = 0; j < 125; j++)
            ; // 空函数
}

void main() // 主函数
{
    uchar display[9] = {0xff, 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; // 流水灯显示数据数组

    unsigned int a;
    for (;;)
    {
        EA = 1; // 总中断允许
        EX0 = 1; // 允许外部中断0中断
        EX1 = 1; // 允许外部中断1中断
        IT0 = 1; // 选择外部中断0为跳沿触发方式
        IT1 = 1; // 选择外部中断1为跳沿触发方式
        
        IP = 0; // 两个外部中断均为低优先级
        for (a = 0; a < 9; a++)
        {
            Delay(500); // 延时
            P1 = display[a]; // 将已经定义的流水灯显示数据送到P1口
        }
    }
}

void int0_isr(void) interrupt 0 using 1 // 外中断0的中断服务函数
{
    uchar n;
    for (n = 0; n < 10; n++) // 高、低4位显示10次
    {
        P1 = 0x0f; // 低4位LED灭,高4位LED亮
        Delay(500); // 延时
        P1 = 0xf0; // 高4位LED灭,低4位LED亮
        Delay(500); // 延时
    }
}

void int1_isr(void) interrupt 2 using 2 // 外中断1中断服务函数
{
    uchar m;
    for (m = 0; m < 10; m++) // 闪烁显示10次
    {
        P1 = 0xff; // 全灭
        Delay(500); // 延时
        P1 = 0; // 全亮
        Delay(500); // 延时
    }
}

Proteus仿真效果图:

开发板效果:

3、嵌套中断

实验原理:

中断嵌套只发生正执行一个低优先级中断,此时又有一高优先级中断产生,就会去执行高优先级中断服务程序。高优先级中断服务程序完成后,再继续执行低优先级中断程序。
设计一中断嵌套程序:要求K1和K2都未按下时,P1口8只LED呈流水灯显示,当按一下K1时,产生一个低优先级外中断0请求(跳沿触发),进入外中断0中断服务程序,上下4只LED交替闪烁。此时按一下K2时,产生一个高优先级的外中断1请求(跳沿触发),进入外中断1中断服务程序,使8只LED全部闪烁。当显示5次后,再从外中断1返回继续执行外中断0中断服务程序,即P1口控制8只LED,上、下4只LED交替闪烁。设置外中断0为低优先级,外中断1为高优先级。

Proteus原理图如双中断所示

C语言代码:
 

#include <reg51.h>
#define uchar unsigned char

// 延时函数
void Delay(unsigned int i)		// Delay function
{	
    unsigned int j;
    for(; i > 0; i--)		
        for(j = 0; j < 125; j++)		
            ; // 空函数
}
// 主函数
void main( )					
{
    uchar display[9]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
                                // 流水灯显示数据组

    uchar a;
    for(;;)				
    {
        EA=1;                  // 总中断允许
        EX0=1;                 // 允许外部中断0中断
        EX1=1;                 // 允许外部中断1中断
        IT0=1;                 // 选择外部中断0为跳沿触发方式
        IT1=1;                 // 选择外部中断1为跳沿触发方式
        PX0=0;                 // 外部中断0为低优先级
        PX1=1;                 // 外部中断1为高优先级

        for(a=0; a<9; a++)		
        {						
            Delay(500);       // 延时
            P1=display[a];    // 流水灯显示数据送到P1口驱动LED显示
        } 	
    }
}

// 外中断0中断函数
void int0_isr(void)  interrupt 0  using 0   
{	
    for(;;)
    {
        P1=0x0f;              // 低4位LED灭,高4位LED亮
        Delay(400);           // 延时
        P1=0xf0;              // 高4位LED灭,低4位LED亮
        Delay(400);           // 延时
    }                         
}

// 外中断1中断函数
void int1_isr (void)  interrupt 2  using 1  
{
    uchar m;
    for(m=0; m<5; m++)          // 8位LED全亮全灭5次
    {
        P1=0;                    // 8位LED全亮
        Delay(500);              // 延时
        P1=0xff;                 // 8位LED全灭
        Delay(500);              // 延时
    }
}

Proteus仿真效果图:

开发板效果:

4、定时器控制

实验原理:
定时器控制LED灯每隔1s周期性亮灭,并用Keil仿真中的虚拟逻辑仪对LED管脚进行波形观察,测量真实的周期数,并与上次采用软件循环进行周期定时的精度进行对比,看哪一种方式更加精准。

Proteus原理图:

C语言代码:
 

#include<reg51.h>
char i = 100;
void main ()
{
    TMOD = 0x01;            // 定时器T0为方式1
    TH0 = 0xee;             // 设置定时器初值
    TL0 = 0x00;
    P1 = 0x00;               // P1口8个LED点亮
    EA = 1;                   // 总中断开
    ET0 = 1;                  // 开T0中断
    TR0 = 1;                  // 启动T0
    while (1)                 // 循环等待
    {
        ;
    }
}
void timer0 () interrupt 1      // T0中断程序
{
    TH0 = 0xee;                // 重新赋初值
    TL0 = 0x00;
    i--;                       // 循环次数减1
    if (i <= 0)
    {
        P1 = ~P1;              // P1口按位取反
        i = 100;                // 重置循环次数
    }
}

Proteus仿真效果图:

开发板效果:

Keil波形图:

5、计数器控制

实验原理:

T1采用计数模式,方式1中断,计数输入引脚T1(P3.5)上外接按钮开关,作为计数信号输入。按4次按钮开关后,P1口的8只LED闪烁不停。

Proteus原理图:

C语言代码:

 #include <reg51.h>
    void Delay(unsigned int i)		//定义延时函数Delay( ),i是形     					             //式参数,不能赋初值
{	
	unsigned int j;		
	for(;i>0;i--)			//变量i由实际参数传入一个值					//因此i不能赋初值
	for(j=0;j<125;j++)		
	{;}				//空函数
 }

void  main( )				//主函数
 {
	TMOD=0x50;			//设置定时器T1为方式1计数
	TH1=0xff;			//向TH1写入初值的高8位
	TL1=0xfc;			//向TL1写入初值的低8位
	EA=1;    				//总中断允许
	ET1=1;                  //定时器T1中断允许
	TR1=1;                  //启动定时器T1
	while(1);				//无穷循环,等待计数中断
}

void T1_int(void) interrupt 3  //T1中断函数
{
	for(;;)                   //无限循环
	{
		P1=0xff;             //8位LED全灭
		Delay(500);          //延时500ms
		P1=0;				 //8位LED全亮
		Delay(500);			 //延时500ms
	}
}

Proteus仿真效果图:

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值