单片机中断系统

单片机中断系统有外部中断和定时计数器中断

接下来我将为大家介绍中断系统之外部中断的理论和程序部分,以及中断系统之定时计数器理论和程序部分

1:中断系统之外部中断

理论部分

我们通过以下图片来进行讲解

 INT0和INT1为单片机的外部中断接下来我将讲解其中的一种另一种类似从INT0开始,当IT0=0时为低电平触发,当IT0=1时为下降沿触发(从高电平转为低电平)这些都在TCOM中设置,IEO=0中断处理后硬件清0无需程序清0,IEO=1外部中断源向CPU请求中断(IEO无需配置),当EX0=1时打开外部中断,当EX0=0时关闭外部中断,EA=1打开总中断,EA=0不打开(EX0,EA在IE中配置)

下面我们来写中断函数的格式

void 函数名()interrupt 中断号 using 寄存器组号 

 程序部分

#include<reg52.h>
typedef signed char int8;         //8位有符号字符型
typedef signed int int16;         //16位有符号整型
typedef signed long int32;        //32位有符号长整型
typedef unsigned char uint8;      //8位无符号字符型
typedef unsigned int uint16;      //16位无符号整型
typedef unsigned long uint32;     //32位无符号长整型
sbit DATA_A_595      = P1^0;  //74HC595 串行数据输入引脚
sbit SHIFT_CLOCK_595 = P1^4;  //74HC595 移位寄存器时钟信号输入引脚
sbit LATCH_CLOCK_595 = P2^3;  //74HC595 锁存器时钟信号输入引脚
sbit duanxuan = P2^5;            //数码管驱动芯片74HC573 段选 
sbit weixuan  = P2^6;            //数码管驱动芯片74HC573 位选
sbit RS_Lcd_1602 = P2^5;    //1602液晶屏 RS端口
sbit RW_Lcd_1602 = P2^6;    //1602液晶屏 RW端口
sbit E_Lcd_1602  = P2^4;    //1602液晶屏 E 端口

#define LCD_1602_IO   P0    //1602液晶屏并行总线端口
uint8 *x;
uint32 *x1;
uint8 test=0; //测试外部中断进入次数
void delay(uint16 x_ms);             //延迟  x_ms*1  毫秒
void write_byte_74hc595(uint8 dat);  //给595芯片写一字节数据函数
void Init_Lcd_1602();                //1602液晶屏初始化函数
void Busy_Lcd_1602();                //1602液晶屏判忙函数
void Write_Order_Lcd_1602(uint8 Order_Dat);//1602液晶屏写指令函数
void Write_Data_Lcd_1602(uint8 Data_Dat);  //1602液晶屏写数据函数
void Display_Lcd_1602(uint8 X_1602,uint8 Y_1602,uint8 *P_1602,uint8 Count_1602); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串
void Display_1602_Lcd_Number(uint8 X_1602,uint8 Y_1602,uint32 Number,uint8 Count_1602);//在1602液晶屏,任意行,任意列,写一个任意位数,的十进制数

/*********************************************************************
*函数名称:main
*函数功能:主函数
*函数调用:
*参数列表:无
*返 回 值:无
*结    果:
*备    注:
*********************************************************************/
void main(void)
{
//*******************************************************************
//外部中断 0 位控制
/*
IT0 = 0;    //0 低电平触发  1 下降沿触发 
EX0 = 1;    //打开外部中断0开关 0关闭  1打开
EA  = 1;    //打开总中断开关    0关闭  1打开

*/
//*******************************************************************
  //外部中断总线控制
 // TCON &= 0XFE;  // 对IT0 位置 0  0 低电平触发
  TCON |= 0X01;  // 对IT0 位置 1  1 下降沿触发
  
  IE   |=0X01;   //EX0 =1     打开外部中断0开关
 // IE   &=0XFE;   //EX0 =0   关闭外部中断0开关  

  IE   |=0X80;   //EA =1   打开总中断开关
 // IE   &=0X7F;  //EA =0  关闭总中断开关 
 
//*******************************************************************
/*********************************************************************
  //测试1602底层函数
  Init_Lcd_1602();  //1602液晶屏初始化函数
  Write_Order_Lcd_1602(0X80+0X00);//1602液晶屏写指令函数
  Write_Data_Lcd_1602(0X61);  //1602液晶屏写数据函数	 写 a 

  Write_Order_Lcd_1602(0X80+0X01);//1602液晶屏写指令函数
  Write_Data_Lcd_1602(0X62);  //1602液晶屏写数据函数	 写 b

  Write_Data_Lcd_1602(0X63);  //1602液晶屏写数据函数	 写 c
  Write_Data_Lcd_1602(0X64);  //1602液晶屏写数据函数	 写 d 
  Write_Data_Lcd_1602(0X65);  //1602液晶屏写数据函数	 写 e
**********************************************************************/
/*********************************************************************
  //测试字符串显示
Init_Lcd_1602();  //1602液晶屏初始化函数
Display_Lcd_1602(1,1," LCD_1602_TEST  ",16); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串
Display_Lcd_1602(2,1,"                ",16); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串 

//Display_Lcd_1602(1,1,"0123456789abcdef",16); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串
//Display_Lcd_1602(2,1,"0123456789abcdef",16); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串
//Display_Lcd_1602(2,3,"+-AB",4); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串

**********************************************************************/

/*********************************************************************
Init_Lcd_1602();  //1602液晶屏初始化函数
Display_1602_Lcd_Number(2,1,1234567890,10);//在1602液晶屏,任意行,任意列,写一个任意位数,的十进制数
**********************************************************************/
Init_Lcd_1602();  //1602液晶屏初始化函数 
Display_Lcd_1602(1,1,"  INT0/1 TEST   ",16); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串
Display_Lcd_1602(2,1,"INT0:    INT1:  ",16); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串


while(1)
	{
		Display_1602_Lcd_Number(2,6,test,2);//在1602液晶屏,任意行,任意列,写一个任意位数,的十进制数
		Display_1602_Lcd_Number(2,15,00,2);//在1602液晶屏,任意行,任意列,写一个任意位数,的十进制数 
	  
	}
}



/*********************************************************************
*函数名称:write_byte_74hc595
*函数功能:74HC595芯片数据输入
*函数调用:write_byte_74hc595(uint8 dat); 
*参数列表:dat
*返 回 值:无
*结    果:把一个字节数 dat 写到 74HC595芯片的八个输出引脚上
*备    注:dat 数据对应的功能
           蜂鸣器         0X04            继电器           0X80
           时钟芯片片选   0X10            流水灯           0X40
*********************************************************************/
void write_byte_74hc595(uint8 dat)  //给595芯片写一字节数据函数
{
  uint8 i; 
	for(i=0;i<8;i++)
	 {
	    DATA_A_595      =(dat<<i)&0x80;  //74HC595 串行数据输入引脚
		  SHIFT_CLOCK_595 = 0;  //74HC595 移位寄存器时钟信号输入引脚
		  SHIFT_CLOCK_595 = 1;  //74HC595 移位寄存器时钟信号输入引脚
		  
	 }
	 LATCH_CLOCK_595 = 0;  //74HC595 锁存器时钟信号输入引脚
	 LATCH_CLOCK_595 = 1;  //74HC595 锁存器时钟信号输入引脚
}
/*********************************************************************
*函数名称:delay
*函数功能:延时函数
*函数调用:delay(uint16 x_ms); 
*参数列表:x_ms
*返 回 值:无
*结    果:延迟时间=1* x_ms(毫秒)
*备    注:
*********************************************************************/
void delay(uint16 x_ms) //延迟  x_ms*1  毫秒
{
   uint16 i,j;
	for(i=x_ms;i>0;i--)
		 for(j=114;j>0;j--);

	  
}

/*********************************************************************
*函数名称:nit_Lcd_1602
*函数功能:1602液晶屏初始化函数
*函数调用:Init_Lcd_1602();   
*参数列表:无
*返 回 值:无
*结    果:
*备    注:
*********************************************************************/
//1602液晶屏初始化函数
void Init_Lcd_1602()  //1602液晶屏初始化函数 
{
   delay(15); //延迟 15ms   延迟  x_ms*1  毫秒 
   Write_Order_Lcd_1602(0X38); //写指令 38H  显示模式设置
   delay(5); //延迟 15ms   延迟  x_ms*1  毫秒 
   Write_Order_Lcd_1602(0X38);//写指令 38H  显示模式设置
   delay(15); //延迟 15ms   延迟  x_ms*1  毫秒 
   Write_Order_Lcd_1602(0X38);//写指令 38H  显示模式设置
   
   Write_Order_Lcd_1602(0X38);//写指令 38H   显示模式设置
   Write_Order_Lcd_1602(0X08);//写指令 08H   显示关闭
   Write_Order_Lcd_1602(0X01);//写指令 01H   显示清屏 
   Write_Order_Lcd_1602(0X06);//写指令 06H   显示光标移动设置 光标坐标自动加1
   Write_Order_Lcd_1602(0X0C);//写指令 0CH   显示光标设置
   
}

/*********************************************************************
*函数名称:Busy_Lcd_1602
*函数功能:1602液晶屏判忙函数
*函数调用:Busy_Lcd_1602();   
*参数列表:无
*返 回 值:无
*结    果:
*备    注:
*********************************************************************/
//1602液晶屏判忙函数
void Busy_Lcd_1602() 
{
    uint8 Busy_Dat=0;   //读取1602 总线端口数据 暂存局部变量 
    LCD_1602_IO = 0XFF; //释放总线 
    RS_Lcd_1602 = 0;    //1602液晶屏 RS端口
    RW_Lcd_1602 = 1;    //1602液晶屏 RW端口
   // E_Lcd_1602  = 1;    //1602液晶屏 E 端口

    do
      {
         E_Lcd_1602  = 1;          //1602液晶屏 E 端口
         Busy_Dat = LCD_1602_IO;   //1602液晶屏并行总线端口
         E_Lcd_1602  = 0;          //1602液晶屏 E 端口
      
      }  
    while(Busy_Dat & 0X80); 
    LCD_1602_IO = 0XFF; //释放总线 
}

/*********************************************************************
*函数名称:Write_Order_Lcd_1602 
*函数功能:1602液晶写指令函数
*函数调用:Write_Order_Lcd_1602(uint8 Order_Dat);   
*参数列表:uint8 Order_Dat  //被写进去的指令
*返 回 值:无
*结    果:
*备    注:
*********************************************************************/
void Write_Order_Lcd_1602(uint8 Order_Dat) //1602液晶写指令函数
{
	Busy_Lcd_1602(); //1602液晶屏判忙函数
	E_Lcd_1602  = 0;          //1602液晶屏 E 端口
	RS_Lcd_1602 = 0;    //1602液晶屏 RS端口
	RW_Lcd_1602 = 0;    //1602液晶屏 RW端口
  LCD_1602_IO = Order_Dat ; //释放总线 
  E_Lcd_1602  = 1;          //1602液晶屏 E 端口
  E_Lcd_1602  = 0;          //1602液晶屏 E 端口
  LCD_1602_IO = 0XFF; //释放总线 
}

/*********************************************************************
*函数名称:Write_Data_Lcd_1602
*函数功能:1602液晶写数据函数
*函数调用:Write_Data_Lcd_1602(uint8 Data_Dat);   
*参数列表:uint8 Data_Dat  //被写进去的数据 -数据就是我们写在1602上的字符
*返 回 值:无
*结    果:
*备    注:
*********************************************************************/
void Write_Data_Lcd_1602(uint8 Data_Dat)
{
	Busy_Lcd_1602(); //1602液晶屏判忙函数
	E_Lcd_1602  = 0;          //1602液晶屏 E 端口
	RS_Lcd_1602 = 1;    //1602液晶屏 RS端口
	RW_Lcd_1602 = 0;    //1602液晶屏 RW端口
  LCD_1602_IO = Data_Dat ; //释放总线 
  E_Lcd_1602  = 1;          //1602液晶屏 E 端口
  E_Lcd_1602  = 0;          //1602液晶屏 E 端口
  LCD_1602_IO = 0XFF; //释放总线 
}

/*********************************************************************
*函数名称:Display_Lcd_1602
*函数功能:在1602液晶屏,任意行,任意列,写一个任意位数,的字符串
*函数调用:Display_Lcd_1602(uint8 X_1602,uint8 Y_1602,uint8 *P_1602,uint8 Count_1602);   
*参数列表: 
            X_1602       行坐标  取值范围 1-2 
            Y_1602       列坐标  取值范围 1-16
            *P_1602      字符串指针变量  要求字符串位数,不能超过16位  取值范围 1-16
            Count_1602   字符串位数 取值范围 1-16 

*返 回 值:无
*结    果:
*备    注:
*********************************************************************/
void Display_Lcd_1602(uint8 X_1602,uint8 Y_1602,uint8 *P_1602,uint8 Count_1602)
{
   uint8 i =0;
/*
    if(X_1602==1)
     Y_1602 = Y_1602 +0X80;   //第一行坐标 0X80 +0X00 =0X80 
    else
     Y_1602 = Y_1602 +0XC0;   //第二行坐标  0X80+0X40 =0XC0
*/
   for(i=0;i<=Count_1602-1;i++)
   {
    if(X_1602==1)      
     Y_1602 |= 0X80;   //第一行坐标 0X80 +0X00 =0X80   //Y_1602 = Y_1602|0X80;   //第一行坐标 0X80 +0X00 =0X80
    else      
     Y_1602 |= 0XC0;   //第二行坐标  0X80+0X40 =0XC0  //Y_1602 = Y_1602|0XC0;   //第二行坐标  0X80+0X40 =0XC0 
		Write_Order_Lcd_1602(Y_1602-1);//1602液晶屏写指令函数
    
		Write_Data_Lcd_1602(*P_1602);  //1602液晶屏写数据函数
    P_1602++;
    Y_1602++;	  

   }      
}

/*********************************************************************
*函数名称:Display_1602_Lcd_Number
*函数功能:在1602液晶屏,任意行,任意列,写一个任意位数,的十进制数
*函数调用:Display_1602_Lcd_Number(uint8 X_1602,uint8 Y_1602,uint32 Number,uint8 Count_1602);   
*参数列表: 
            X_1602       行坐标  取值范围 1-2 
            Y_1602       列坐标  取值范围 1-16
            Number       任意的10位十进制数

            Count_1602   十进制数位数 取值范围 1-10 

*返 回 值:无
*结    果:
*备    注:
*********************************************************************/
void Display_1602_Lcd_Number(uint8 X_1602,uint8 Y_1602,uint32 Number,uint8 Count_1602)
{
   uint8 numbercode[10];
   uint8 i=0;
   uint8 Count_1602_Flag=0;
   numbercode[0] = Number%10;                         //个
   numbercode[1] = Number%100/10;                     //十
   numbercode[2] = Number%1000/100;                   //百
   numbercode[3] = Number%10000/1000;                 //千
   numbercode[4] = Number%100000/10000;               //万
   numbercode[5] = Number%1000000/100000;             //十万
   numbercode[6] = Number%10000000/1000000;           //百万
   numbercode[7] = Number%100000000/10000000;         //千万
   numbercode[8] = Number%1000000000/100000000;       //亿
   numbercode[9] = Number%10000000000/1000000000;     //十亿
   Count_1602_Flag = Count_1602-1;
   for(i=0;i<=Count_1602-1;i++)
   {
    if(X_1602==1)      
     Y_1602 |= 0X80;   //第一行坐标 0X80 +0X00 =0X80   //Y_1602 = Y_1602|0X80;   //第一行坐标 0X80 +0X00 =0X80
    else      
     Y_1602 |= 0XC0;   //第二行坐标  0X80+0X40 =0XC0  //Y_1602 = Y_1602|0XC0;   //第二行坐标  0X80+0X40 =0XC0 
		Write_Order_Lcd_1602(Y_1602-1);//1602液晶屏写指令函数
    
		Write_Data_Lcd_1602(0X30+numbercode[Count_1602_Flag]);  //1602液晶屏写数据函数
    Y_1602++;	  
    Count_1602_Flag--;

   } 


}

void Int0() interrupt 0 using 1
{
   test++;
   if(test>=100)
   test=0;
   delay(10);
}

2:中断系统之定时计数器

定时器内部工作原理分析

 定时/计数模式设置(在TMOD寄存器里设置)

1.TMOD=0X01(定时器0 方式1 16位定时/计数器)

2.装初值TL0(低八位)和TH0(高八位)

3.开关定时/计数器TR0=1(打开定时计数器),TR0=0(关闭定时计数器)(在TCON寄存器中设置)

4.打开定时计数器中断允许位(在IE寄存器里设置)ET0=0(不允许),ET0=1(允许)

5.定时计数器中断请求中断标志TF0=1(定时计数器向CPU请求中断)TF0=0(中断处理后由硬件清0)

6.EA=1打开总中断,EA=0不打开(EX0,EA在IE中配置)

程序代码

用定时器0实现原子钟,在1602液晶显示屏上以00:00:00:(时:分:秒)这种格式显示,开始计时

#include<reg52.h>

/*
**********************************************************************
*                       本地数据类型/宏定义
**********************************************************************
*/
typedef signed char int8;         //8位有符号字符型
typedef signed int int16;         //16位有符号整型
typedef signed long int32;        //32位有符号长整型
typedef unsigned char uint8;      //8位无符号字符型
typedef unsigned int uint16;      //16位无符号整型
typedef unsigned long uint32;     //32位无符号长整型

/*
**********************************************************************
*                        单片机IO口位定义
**********************************************************************
*/
//*******************************************************
  //该部分为了关闭数码管和 LED流水灯
sbit DATA_A_595      = P1^0;  //74HC595 串行数据输入引脚
sbit SHIFT_CLOCK_595 = P1^4;  //74HC595 移位寄存器时钟信号输入引脚
sbit LATCH_CLOCK_595 = P2^3;  //74HC595 锁存器时钟信号输入引脚

sbit duanxuan = P2^5;            //数码管驱动芯片74HC573 段选 
sbit weixuan  = P2^6;            //数码管驱动芯片74HC573 位选
//*******************************************************

sbit RS_Lcd_1602 = P2^5;    //1602液晶屏 RS端口
sbit RW_Lcd_1602 = P2^6;    //1602液晶屏 RW端口
sbit E_Lcd_1602  = P2^4;    //1602液晶屏 E 端口

#define LCD_1602_IO   P0    //1602液晶屏并行总线端口
/*
**********************************************************************
*                      本地全局变量/数组定义
**********************************************************************
*/
uint8 time_1s =0;   //1s 时间单位
/*
**********************************************************************
*                         函数原型声明
**********************************************************************
*/
void delay(uint16 x_ms);             //延迟  x_ms*1  毫秒
void write_byte_74hc595(uint8 dat);  //给595芯片写一字节数据函数
void Init_Lcd_1602();                //1602液晶屏初始化函数
void Busy_Lcd_1602();                //1602液晶屏判忙函数
void Write_Order_Lcd_1602(uint8 Order_Dat);//1602液晶屏写指令函数
void Write_Data_Lcd_1602(uint8 Data_Dat);  //1602液晶屏写数据函数
void Display_Lcd_1602(uint8 X_1602,uint8 Y_1602,uint8 *P_1602,uint8 Count_1602); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串
void Display_1602_Lcd_Number(uint8 X_1602,uint8 Y_1602,uint32 Number,uint8 Count_1602);//在1602液晶屏,任意行,任意列,写一个任意位数,的十进制数

/*********************************************************************
*函数名称:main
*函数功能:主函数
*函数调用:
*参数列表:无
*返 回 值:无
*结    果:
*备    注:
*********************************************************************/
void main(void)
{
//*******************************************************************
//定时器 0 中断法
// TMOD = 0X01;  //总线控制法直接赋值 设置定时器0 方式1 
 /*
  TMOD &=0XF0;  //第四位全部置0   设置定时器0 方式1
  TMOD |=0X01;  //最低位置 1

  TH0 = 0X4C;   //定时器 0 装初值 定时时间 50ms
  TL0 = 0X00;
 
  TR0 =  1;     //定时器0 启动计数
  ET0 =  1;     //打开定时器0 中断允许位
  TF0 =  0;     //清零定时/计数器中断标志位
  EA  =  1;     //打开总中断开关
*/
//*******************************************************************
//定时器 0 查询法
// TMOD = 0X01;  //总线控制法直接赋值 设置定时器0 方式1 
 
  TMOD &=0XF0;  //第四位全部置0   设置定时器0 方式1
  TMOD |=0X01;  //最低位置 1

  TH0 = 0X4C;   //定时器 0 装初值 定时时间 50ms
  TL0 = 0X00;
 
  TR0 =  1;     //定时器0 启动计数
  TF0 =  0;     //清零定时/计数器中断标志位
    
//**********************************************************************
Init_Lcd_1602();  //1602液晶屏初始化函数 
Display_Lcd_1602(1,1," Timer0/1 TEST  ",16); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串
Display_Lcd_1602(2,1,"    00:00:00    ",16); //在1602液晶屏,任意行,任意列,写一个任意位数,的字符串

write_byte_74hc595(0X00);  //给595芯片写一字节数据函数
while(1)
	{
//*****************************************************
  //定时/计数器0 查询法		
   if(TF0 == 1)     //清零定时/计数器中断标志位
     {
			 static uint8 time=0;
			 TF0 =  0;     //清零定时/计数器中断标志位 
       TH0 = 0X4C;   //定时器 0 装初值 定时时间 50ms
			 TL0 = 0X00;
       
			 time++;
			 if(time>=20)
			 {
					time_1s++;  //1s 时间单位
					time=0;        
			 }
		
     }
//*****************************************************  


     //1s 时间单位
     Display_1602_Lcd_Number(2,11,time_1s,2);//在1602液晶屏,任意行,任意列,写一个任意位数,的十进制数
     if(time_1s>=60)
       time_1s=0;
		
	  
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值