网站开发与设计实训报告,最好看免费观看高清大全宫崎骏,可做笔记的阅读网站,wordpress外网无法访问单片机中断系统
中断的概念#xff1a;
CPU在处理某一事件A时#xff0c;发生了另一事件B请求CPU迅速去处理#xff08;中断发生#xff09;#xff1b;CPU暂时中断当前的工作#xff0c;转去处理事件B#xff08;中断响应和中断服务#xff09;#xff1b;待CPU将事…单片机中断系统
中断的概念
CPU在处理某一事件A时发生了另一事件B请求CPU迅速去处理中断发生CPU暂时中断当前的工作转去处理事件B中断响应和中断服务待CPU将事件B处理完毕后再回到原来事件A被中断的地方继续处理事件A中断返回这一过程称为中断 。 随着计算机技术的应用人们发现中断技术不仅解决了快速主机与慢速I/O设备的数据传送问题而且还具有如下优点
分时操作。 CPU可以分时为多个I/O设备服务提高了计算机的利用率
实时响应。 CPU能够及时处理应用系统的随机事件系统的实时性大大增强
可靠性高。 CPU具有处理设备故障及掉电等突发性事件能力从而使系统可靠性提高。 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、TF0TCON.5片内定时/计数器T0溢出中断请求标志。当定时/计数器T0发生溢出时置位TF0并向CPU申请中断。
4、TF1TCON.7片内定时/计数器T1溢出中断请求标志。当定时/计数器T1发生溢出时置位TF1并向CPU申请中断。
5、RISCON.0或TISCON.1串行口中断请求标志。当串行口接收完一帧串行数据时置位RI或当串行口发送完一帧串行数据时置位TI向CPU申请中断。
中断允许控制 EX0(IE.0)外部中断0允许位
ET0(IE.1)定时/计数器T0中断允许位
EX1(IE.2)外部中断0允许位
ET1(IE.3)定时/计数器T1中断允许位
ESIE.4)串行口中断允许位
EA (IE.7) CPU中断允许总允许位。 中断请求标志 IT0TCON.0外部中断0触发方式控制位。 当IT00时为电平触发方式。 当IT01时为边沿触发方式下降沿有效。
IE0TCON.1外部中断0中断请求标志位。
IT1TCON.2外部中断1触发方式控制位。
IE1TCON.3外部中断1中断请求标志位。
TF0TCON.5定时/计数器T0溢出中断请求标志位。
TF1TCON.7定时/计数器T1溢出中断请求标志位。
中断优先级 中断源 定时/计数器 51单片机定时/计数器的工作由两个特殊功能寄存器控制。TMOD用于设置其工作方式TCON用于控制其启动和中断申请。
工作方式寄存器TMOD 工作方式寄存器TMOD用于设置定时/计数器的工作方式低四位用于T0高四位用于T1。其格式如下 GATE是门控位, GATE0时用于控制定时器的启动是否受外部中断源信号的影响。只要用软件使TCON中的TR0或TR1为1就可以启动定时/计数器工作GATA1时要用软件使TR0或TR1为1同时外部中断引脚INT0/1也为高电平时才能启动定时/计数器工作。即此时定时器的启动条件加上了INT0/1引脚为高电平这一条件。 C/T :定时/计数模式选择位。C/T 0为定时模式;C/T 1为计数模式。 M1M0工作方式设置位。定时/计数器有四种工作方式。 控制其启动和中断申请TCON TCON的低4位用于控制外部中断,已在前面介绍。TCON的高4位用于控
制定时/计数器的启动和中断申请。其格式如下 TF1TCON.7T1溢出中断请求标志位。T1计数溢出时由硬件自动置TF1为1。CPU响应中断后TF1由硬件自动清0。T1工作时CPU可随时查询TF1的状态。所以TF1可用作查询测试的标志。TF1也可以用软件置1或清0同硬件置1或清0的效果一样。
TR1TCON.6T1运行控制位。TR1置1时T1开始工作TR1置0时T1停止工作。TR1由软件置1或清0。所以用软件可控制定时/计数器的启动与停止。
TF0TCON.5T0溢出中断请求标志位其功能与TF1类同。
TR0TCON.4T0运行控制位其功能与TR1类同。 TLx与THx之间的搭配关T0(TL0-0x8A,TH0-0x8C), T1(TL1-0x8B,TH1-0x8D)
1、TLx与THx之间32进制。即当TLx计到32个脉冲时TLx归0同时THx进1。这也称为方式0。
2、TLx与THx之间256进制。即当TLx计到256个脉冲时TLx归0同时THx进1。这也称为方式1。在方式1时最多计65536个脉冲产生溢出。在主频为11.0592M时每计一个脉冲为1.085us所以溢出一次的时间为1.085usx6553671.1ms。
3、THx用于存放TLx溢出后TLx下次计数的起点。这也称为方式2。
4、THx与TLx分别独立对自己的输入脉冲计数。这也称为方式3。
5、定时器初始化
1、确定定时器的计数模式。
2、确定TLx与THx之间的搭配关系。
3、确定计数起点值。即TLx与THx的初值。 STC单片机STC89C52RC定时器延时时间的计算延时时间要根据晶振频率计算不同板子可能有所不同。时钟周期1/时钟源在我现在这块板子上晶振频率是11.0592M也就是时钟周期是 1/11059200秒机器周期一般51单片机是12个时钟周期我的板子也就是 12/11059200秒单次定时最长时间如果是16位的计数器16位最大值是65535共可计数65536次。基本的常数一定要记住还要记住8位最大值是255共可计数256次还要记住8位上每位代表的数值。12 * 65536/11059200 0.0711 s,也就是71 ms内的定时可以单次定时就完成。如果定时时间超过71 ms就要循环了。一次定时需要几次机器周期计算公式定时秒数/机器周期比如我要定时1秒 1/12/11059200 921600次16位计数器最大可计数65536次921600次早就益出了。我们可以每次定时10 ms循环100次就可以定时1秒了1 s缩小100百倍就是10 ms, 也就是每次需要计数9216次。确实计数器初始值:定时10 ms时如果计数器从0开始计数我们就不知道什么时候到了9216次。所以应该计数了9216次16位计数器最多计数95536次然后就溢出一溢出TCON的TF位就会置1我们只要经常检测TF位就可以知道什么时候完成10ms的定时了。计算公式计数器初始值最大计数次数 - 需要计数次数如果定时10 ms计数器的初始值就是 65536 - 9216计算计数器的高位和低位16位的计数器也就是两个8位组成8位的最大计数次数是256。所以:计数器高位 初始值/256计数器低位 初始值%256 例如
设置 外部中断0 #include reg52.h //此文件中定义了单片机的一些特殊功能寄存器 typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8; sbit k3P3^2; //定义按键K3
sbit ledP2^0; //定义P20口是led void delay(u16 i)
{ while(i--);
} void Int0Init()
{ //设置INT0 IT01;//跳变沿出发方式下降沿 EX01;//打开INT0的中断允许。 EA1;//打开总中断
} void main()
{ Int0Init(); // 设置外部中断0 while(1);
} void Int0() interrupt 0 //外部中断0的中断函数
{ delay(1000); //延时消抖 if(k30) { led~led; }
} 例如
设置 定时器0 #include reg52.h //此文件中定义了单片机的一些特殊功能寄存器 typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8; sbit ledP2^0; //定义P20口是led void Timer0Init()
{ TMOD|0X01;//选择为定时器0模式工作方式1仅用TR0打开启动。 TH00XFC; //给定时器赋初值定时1ms TL00X18; ET01;//打开定时器0中断允许 EA1;//打开总中断 TR01;//打开定时器
} void main()
{ Timer0Init(); //定时器0初始化 while(1);
} void Timer0() interrupt 1
{ static u16 i; TH00XFC; //给定时器赋初值定时1ms TL00X18; i; if(i1000) { i0; led~led; }
} 例如
交通灯 #include reg52.h //此文件中定义了单片机的一些特殊功能寄存器 typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8; sbit LSAP2^2;
sbit LSBP2^3;
sbit LSCP2^4; //--定义使用的IO口--//
#define GPIO_DIG P0 #define GPIO_TRAFFIC P1 sbit RED10 P1^0; //上人行道红灯
sbit GREEN10 P1^1; //上人行道绿灯
sbit RED11 P1^2;
sbit YELLOW11 P1^3;
sbit GREEN11 P1^4; sbit RED00 P3^0; //右人行道红灯
sbit GREEN00 P3^1; //右人行道绿灯
sbit RED01 P1^5;
sbit YELLOW01 P1^6;
sbit GREEN01 P1^7; u8 code smgduan[17]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值 u8 DisplayData[8];
u8 Second; void delay(u16 i)
{ while(i--);
} void DigDisplay()
{ u8 i; for(i0;i8;i) { switch(i) //位选选择点亮的数码管 { case(0): LSA0;LSB0;LSC0; break;//显示第0位 case(1): LSA1;LSB0;LSC0; break;//显示第1位 case(2): LSA0;LSB1;LSC0; break;//显示第2位 case(3): LSA1;LSB1;LSC0; break;//显示第3位 case(4): LSA0;LSB0;LSC1; break;//显示第4位 case(5): LSA1;LSB0;LSC1; break;//显示第5位 case(6): LSA0;LSB1;LSC1; break;//显示第6位 case(7): LSA1;LSB1;LSC1; break;//显示第7位 } GPIO_DIGDisplayData[i];//发送段码 delay(100); //间隔一段时间扫描 GPIO_DIG0x00;//消隐 }
} void Timer0Init()
{ TMOD|0X01;//选择为定时器0模式工作方式1仅用TR0打开启动。 TH00XFC; //给定时器赋初值定时1ms TL00X18; ET01;//打开定时器0中断允许 EA1;//打开总中断 TR01;//打开定时器
} void main()
{ Second 1; Timer0Init(); while(1) { if(Second 70) { Second 1; } //--宝田路通行30秒--// if(Second 31) { DisplayData[0] 0x00; DisplayData[1] 0x00; DisplayData[2] smgduan[(30 - Second) % 100 / 10]; DisplayData[3] smgduan[(30 - Second) %10]; DisplayData[4] 0x00; DisplayData[5] 0x00; DisplayData[6] DisplayData[2]; DisplayData[7] DisplayData[3]; DigDisplay(); //--宝田路通行--// GPIO_TRAFFIC 0xFF; //将所有的灯熄灭 RED00 1; GREEN00 1; GREEN11 0; //宝田路绿灯亮 GREEN10 0; //宝田路人行道绿灯亮 RED01 0; //前进路红灯亮 RED00 0; //前进路人行道红灯亮 } //--黄灯等待切换状态5秒--// else if(Second 36) { DisplayData[0] 0x00; DisplayData[1] 0x00; DisplayData[2] smgduan[(35 - Second) % 100 / 10]; DisplayData[3] smgduan[(35 - Second) %10]; DisplayData[4] 0x00; DisplayData[5] 0x00; DisplayData[6] DisplayData[2]; DisplayData[7] DisplayData[3]; DigDisplay(); //--黄灯阶段--// GPIO_TRAFFIC 0xFF; //将所有的灯熄灭 RED00 1; GREEN00 1; YELLOW11 0; //宝田路黄灯亮 RED10 0; //宝田路人行道红灯亮 YELLOW01 0; //前进路红灯亮 RED00 0; //前进路人行道红灯亮 } //--前进路通行--// else if(Second 66) { DisplayData[0] 0x00; DisplayData[1] 0x00; DisplayData[2] smgduan[(65 - Second) % 100 / 10]; DisplayData[3] smgduan[(65 - Second) %10]; DisplayData[4] 0x00; DisplayData[5] 0x00; DisplayData[6] DisplayData[2]; DisplayData[7] DisplayData[3]; DigDisplay(); //--黄灯阶段--// GPIO_TRAFFIC 0xFF; //将所有的灯熄灭 RED00 1; GREEN00 1; RED11 0; //宝田路红灯亮 RED10 0; //宝田路人行道红灯亮 GREEN01 0; //前进路绿灯亮 GREEN00 0; //前进路人行道绿灯亮 } //--黄灯等待切换状态5秒--// else { DisplayData[0] 0x00; DisplayData[1] 0x00; DisplayData[2] smgduan[(70 - Second) % 100 / 10]; DisplayData[3] smgduan[(70 - Second) %10]; DisplayData[4] 0x00; DisplayData[5] 0x00; DisplayData[6] DisplayData[2]; DisplayData[7] DisplayData[3]; DigDisplay(); //--黄灯阶段--// GPIO_TRAFFIC 0xFF; //将所有的灯熄灭 RED00 1; GREEN00 1; YELLOW11 0; //宝田路黄灯亮 RED10 0; //宝田路人行道红灯亮 YELLOW01 0; //前进路红灯亮 RED00 0; //前进路人行道红灯亮 } }
} void Timer0() interrupt 1
{ static u16 i; TH00XFC; //给定时器赋初值定时1ms TL00X18; i; if(i1000) { i0; Second ; }
} 例如
脉冲发生器 #include reg52.h //此文件中定义了单片机的一些特殊功能寄存器 typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8; //--定义使用的IO--//
#define GPIO_DIG P0 sbit LSAP2^2;
sbit LSBP2^3;
sbit LSCP2^4; u8 code smgduan[17]{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值 u8 DisplayData[8]; //--定义全局变量--//
unsigned long Freq; //用来存放要显示的频率值
unsigned long TimeCount; //用于计算1S钟的 void delay(u16 i)
{ while(i--);
} void DigDisplay()
{ u8 i; for(i0;i8;i) { switch(i) //位选选择点亮的数码管 { case(0): LSA0;LSB0;LSC0; break;//显示第0位 case(1): LSA1;LSB0;LSC0; break;//显示第1位 case(2): LSA0;LSB1;LSC0; break;//显示第2位 case(3): LSA1;LSB1;LSC0; break;//显示第3位 case(4): LSA0;LSB0;LSC1; break;//显示第4位 case(5): LSA1;LSB0;LSC1; break;//显示第5位 case(6): LSA0;LSB1;LSC1; break;//显示第6位 case(7): LSA1;LSB1;LSC1; break;//显示第7位 } GPIO_DIGDisplayData[i];//发送段码 delay(10); //间隔一段时间扫描 GPIO_DIG0x00;//消隐 }
} void Timer_Config()
{ //--定时器T1做计数器工作方式116位定时器只由TRx打开计数器--// //--定时器T0做定时器工作方式116位定时器只由TRx打开定时器--// TMOD0x51; //--设置定时器晶振为12MHZ时定时50ms--// TH00x3C; TL00xB0; //--打开中断-// ET01; ET11; EA1; //--打开定时器*/ TR01; TR11;
} void main()
{ Timer_Config(); while(1) { if(TR1 0) //当计数器停下的时候表明计数完毕 { Freq Freq TL1; //读取TL的值 Freq Freq (TH1 * 256); //读取TH的值 //--求频率的个十百千万十万位--// DisplayData[0] smgduan[Freq%1000000/100000]; DisplayData[1] smgduan[Freq%100000/10000]; DisplayData[2] smgduan[Freq%10000/1000]; DisplayData[3] smgduan[Freq%1000/100]; DisplayData[4] smgduan[Freq%100/10]; DisplayData[5] smgduan[Freq%10]; //--显示完重新计算下一次频率。--// Freq 0;//将计算的频率清零 TH1 0; //将计数器的值清零 TL1 0; TR0 1; //开启定时器 TR1 1; //开启计数器 } //--显示求得的数值--// DigDisplay(); }
} void Timer0() interrupt 1
{ //--12MHZ设置定时50ms的初值--// TH00x3C; TL00xB0; TimeCount; if(TimeCount20)//计时到1S { TR00; TR10; TimeCount0; }
} void Timer1() interrupt 3
{ //--进入一次中断表明计数到了65536--// FreqFreq65536;
} 例如
串口通讯 #include reg52.h //此文件中定义了单片机的一些特殊功能寄存器 typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8; void UsartInit()
{ SCON0X50; //设置为工作方式1 TMOD0X20; //设置计数器工作方式2 PCON0X80; //波特率加倍 TH10XF3; //计数器初始值设置注意波特率是4800的 TL10XF3; ES1; //打开接收中断 EA1; //打开总中断 TR11; //打开计数器
} void main()
{ UsartInit(); // 串口初始化 while(1);
} void Usart() interrupt 4
{ u8 receiveData; receiveDataSBUF;//出去接收到的数据 RI 0;//清除接收中断标志位 SBUFreceiveData;//将接收到的数据放入到发送寄存器 while(!TI); //等待发送数据完成 TI0; //清除发送完成标志位
} 例如 485通讯 #include reg52.h //此文件中定义了单片机的一些特殊功能寄存器
typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
sbit RS485DIRP1^0; //RS485DIR0为接收状态 RS485DIR1为发送状态 void delay(u16 i)
{ while(i--);
} void UsartInit()
{ SCON0X50; //设置为工作方式1 TMOD0X20; //设置计数器工作方式2 PCON0X80; //波特率加倍 TH10XF3; //计数器初始值设置注意波特率是4800的 TL10XF3; ES1; //打开接收中断 EA1; //打开总中断 TR11; //打开计数器 RS485DIR0;
} void main()
{ UsartInit(); // 串口初始化 while(1);
} void Usart() interrupt 4
{ u8 receiveData; receiveDataSBUF;//出去接收到的数据 RI 0;//清除接收中断标志位 delay(100); RS485DIR1; SBUFreceiveData;//将接收到的数据放入到发送寄存器 while(!TI); //等待发送数据完成 TI0; //清除发送完成标志位 RS485DIR0;
}