沉浸式学习51单片机(4)——中断与定时记数

目录

 一.作者小课堂

(一)什么是AT89S51中断技术?

1.概述 

2.中断系统结构

3.中断请求标志寄存器 

(1)TCON寄存器(Timing Control Register)

(2)SCON寄存器(Serial Control Register)

(二)定时器/计数器的工作原理及应用 

1. 定时器/计数器的结构  

二.实践出真知

(一)按键中断控制流水灯的实验

1.单一外中断的应用

(1)实验内容

(2)代码示例

(3)proteus电路图示例

​编辑

(4)仿真结果及实验结果演示

①proteus仿真结果

②普中开发板实验结果

2.两个外中断的应用

(1)实验内容

(2)代码示例

(3)proteus电路图示例

​编辑

(4)仿真结果及实验结果演示

①proteus仿真结果

②普中开发板实验结果

3.中断嵌套的应用

(1)实验内容

(2)代码示例

①proteus仿真结果

②普中开发板实验结果

(二)采用定时计数器控制LED灯每隔1s周期性亮灭的实验

(1)实验内容

(2)代码示例

(3)proteus电路图示例

​编辑

(4)仿真结果及实验结果演示

①proteus仿真结果

②普中开发板实验结果

(三)采用计数器中断,实现 按4次按钮开关后,P1口的8只LED闪烁不停

(1)实验内容

(2)代码示例

(3)proteus电路图示例

​编辑

(4)仿真结果及实验结果演示

①proteus仿真结果

三.你好,gitee!

四.总结


 一.作者小课堂

在上一篇博客里,我们已经充分了解学习了普中51单片机实验开发板的开发使用方法,那么现在让我们共同进入中断与定时记数的学习中吧!同时本篇博客将会迎来新的朋友:gitee代码版本仓库网站

(一)什么是AT89S51中断技术?

1.概述 

中断技术主要用于实时监测与控制,要求单片机能及时地响应中断请求源提出的服务请求,并快速响应与及时处理。 当中断请求源发出中断请求时,如中断请求被允许,单片机暂时中止当前正在执行的主程序,转到中断服务处理程序处理中断服务请求,处理完中断服务请求后,再回到原来被中止的程序之处(断点),继续执行被中断的主程序。

如没有中断系统,单片机大量时间可能会浪费在查询是否有服务请求的定时查询操作上,即不论是否有服务请求,都必须去查询。采用中断技术完全消除查询方式的等待,大大提高单片机工作效率和实时性。

图1.中断响应和处理过程  

2.中断系统结构

中断系统有5个中断请求源(简称中断源),2个中断优先级,可实现2级中断服务程序嵌套。每一中断源可用软件独立控制为允许中断或关闭中断状态;每一个中断源的优先级均可用软件设置。 

图2.中断系统结构 

表1.中断请求源

INT0*

外部中断请求0,外部中断请求信号(低电平或负跳变有效)由INT0*引脚输入,中断请求标志为IE0。

INT1*

外部中断请求1,外部中断请求信号(低电平或负跳变有效)由INT1*引脚输入,中断请求标志为IE1。     

TF0

定时器/计数器T0计数溢出的中断请求

TF1                    

定时器/计数器T1计数溢出的中断请求   

发送中断TI/接     收中断RI 串行口中断请求

3.中断请求标志寄存器 

5个中断请求源的中断请求标志分别由特殊功能寄存器TCON和SCON相应位锁存

(1)TCON寄存器(Timing Control Register)

图3.特殊功能寄存器TCON的格式 

(2)SCON寄存器(Serial Control Register)

图4. SCON中的中断请求标志位

(二)定时器/计数器的工作原理及应用 

1. 定时器/计数器的结构  

AT89S51定时器/计数器结构见图 7-1,定时器/计数器T0由特殊功能寄存器TH0、TL0构成,T1由特殊功能寄存器TH1、TL1构成。

图5. 定时器/计数器结构框图

二.实践出真知

(一)按键中断控制流水灯的实验

1.单一外中断的应用

(1)实验内容

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

(2)代码示例
 #include <reg51.h>
  #define uchar  unsigned char
  void Delay(unsigned int i)	//延时函数Delay( ),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)		//循环		
Delay(400) ;		//延时
   	P1=0xf0;		//高4位LED灭,低4位LED亮
   	Delay(400); 		//延时
   	EX0=1;			//中断返回前,打开外部中断0中断
  }
(3)proteus电路图示例

图6.

(4)仿真结果及实验结果演示
①proteus仿真结果

 本例程包含两部分,一部分是主程序段,完成中断系统初始化,并把8个LED全部点亮。另一部分是中断函数部分,控制4个LED交替闪烁1次,然后从中断返回。


图7 

②普中开发板实验结果

图8 

2.两个外中断的应用

(1)实验内容

当需要多个中断源时,只需增加相应的中断服务函数即可。

(2)代码示例
#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); 				//延时
  	}
  }
(3)proteus电路图示例

图9 

(4)仿真结果及实验结果演示
①proteus仿真结果

图10 

②普中开发板实验结果

图11 

3.中断嵌套的应用

(1)实验内容

中断嵌套只发生正执行一个低优先级中断,此时又有一高优先级中断产生,就会去执行高优先级中断服务程序。高优先级中断服务程序完成后,再继续执行低优先级中断程序。

(2)代码示例
#include <reg51.h>
#define uchar unsigned char
void Delay(unsigned int i)		//延时函数Delay( )
{	
  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显示
} 	
}
}

void int0_isr(void)  interrupt 0  using 0   //外中断0中断函数
{	
  for(;;)
  {
  	P1=0x0f;		//低4位LED灭,高4位LED亮
  	Delay(400);		//延时
  	P1=0xf0;		//高4位LED灭,低4位LED亮
 	Delay(400);		//延时
  } 							
}
void int1_isr (void)  interrupt 2  using 1  //外中断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仿真结果

图12 

②普中开发板实验结果

图13 

(二)采用定时计数器控制LED灯每隔1s周期性亮灭的实验

(1)实验内容

在AT89S51的P1口上接有8只LED,原理电路见图7-13。采用T0方式1的定时中断方式,使P1口外接的8只LED每0.5s闪亮一次。

(2)代码示例
#include <REGX52.H>
 
void Timer0_Init()
{
	//设置定时器工作模式TMOD为方式1
	TMOD&=0xF0;//高四位不变,低四位清零
	TMOD|=0x01;//最低位置1,其余位不变 //TOMD=0x01
	           //定时时间=(2^16-X)*12/晶振频率
	TL0=0x66;
	TH0=0xFC;//定时1ms
	//设置定时器控制寄存器TCON
	TF0=0; //中断溢出标志位先清0,避免刚配置好就中断
	TR0=1; //定时器开始工作
	//中断
	EA=1;//允许总中断
	ET0=1;//T0的中断溢出允许位,T0=1,允许中断
}
 
void main()
{
	Timer0_Init();
	while(1)
	{}
}
 
void Timer0_Runtine() interrupt 1
{
	unsigned int a;//计数
	TL0=0x66;
	TH0=0xFC;
	Count++;
	if(a>=1000)//计数累加到1000,定时器定时1000ms=1s
	{
		P2_0=~P2_0;//LED状态取反
		a=0;
	}
}
(3)proteus电路图示例

图14 

(4)仿真结果及实验结果演示
①proteus仿真结果

图15 

②普中开发板实验结果

图16 

(三)采用计数器中断,实现 按4次按钮开关后,P1口的8只LED闪烁不停

(1)实验内容

采用计数器中断,实现 按4次按钮开关后,P1口的8只LED闪烁不停

(2)代码示例
#include <REGX51.H>
 
void Delay1ms(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}
 
 
void Count0_Init()	//计数器
{
	//设置计数器0工作模式1
	TMOD&=0xf0;
	TMOD|=0x05;// C/T置1为计数器模式
	TL0=0xfc;
	TH0=0xff;//计数4次,65536-4=65532
	//设置计数器控制寄存器TCON
	TF0=0;
	TR0=1;
	//中断
	EA=1;
	ET0=1;
}
 
void main()
{
	Count0_Init();
	while(1)
	{
		
	}
}
 
void Count0_Routine() interrupt 1
{
	while(1)
	{
		P2=~P2;
		Delay1ms(500);
		P2=~P2;
		Delay1ms(500);
	}
 
}
(3)proteus电路图示例

图 17

(4)仿真结果及实验结果演示
①proteus仿真结果

图18 

三.你好,gitee!

在本期的博客,我们将认识一个新的学习平台——gitee。

图19 

注册之后,我们就可以在这个平台进行一些列的学习活动了!

四.总结

通过此次的学习,我掌握了一下知识:深入了解51单片机中断原理,掌握外部中断、定时器/计数器中断的编程方式;了解中断响应、中断优先级、中断标志位复位等原理,掌握二级中断、中断嵌套的具体应用编程;了解定时器/计数器的工作原理,掌握计数器初值计算方法,定时/计数中断服务的编程开发。

  • 10
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Proteus是一种电子电路仿真软件,其中包含了多种电子元件的模型和仿真功能。在Proteus中使用串口中断可以模拟实际电路中的串口通信。 串口中断是指当某个外部设备传输数据给单片机时,单片机能够及时地中断当前程序的执行,去处理接收到的数据,提高单片机的响应速度和数据处理能力。 在Proteus中设置串口中断可以通过以下步骤进行: 1. 在电路图中选择需要使用串口的单片机元件,如8051单片机。 2. 右键单击单片机元件,选择“Edit Properties”或类似选项,进入单片机的属性设置界面。 3. 在属性设置界面中找到串口中断相关的选项,如“中断使能”或“串口中断使能”等,将该选项勾选上。 4. 根据具体需求,设置串口的通信参数,包括波特率、数据位、校验位等。 5. 将其他与串口相关的元件连接到单片机的串口引脚上,如串口转USB模块或串口调试器等。 6. 编写单片机的程序代码,包括中断服务函数和数据接收处理部分。 7. 在仿真界面中启动仿真,观察串口中断是否能够正常工作,即当有数据传输到单片机时,仿真能否中断当前程序执行,并处理接收到的数据。 通过以上步骤,就可以在Proteus中实现串口中断的仿真。在实际应用中,可以利用串口中断来实现与外部设备的数据通信,如与计算机、传感器等进行数据交互,从而完成更复杂的电子系统设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值