中断使得高低速设备能够协调工做(低速设备完成工做后经过中断的方式通知高速设备一次处理一批数据),中断还能够根据不一样的优先级实现嵌套执行。web
定时器本质上是个 16 位的自增计数器,当发生溢出时,若是开启了溢出中断,单片机会自动向 CPU 报告这个溢出中断,处理相应的中断任务。svg
TCON 的低 4 位用做外部中断,高 4 位用做定时控制。地址是 88H。spa
TCON 定时器控制寄存器各个位的意义以下:code
所在位 bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
CPU 对中断源的开启或屏蔽的控制,是经过 IE 寄存器来设置的,IE 既可按字节地址寻址(其字节地址为 A8H),又可按位寻址。某个中断对应的位设为 1 则表示容许中断,不然禁止。xml
IE 中断容许控制寄存器各个位的意义以下:blog
所在位 bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | EA | - | ET2 | ES | ET1 | EX1 | ET0 | EX0 |
定时器工做在中断方式时,当定时器的值计满溢出时,会触发定时器溢出中断。token
只要想使用中断,就必须开启 EA 总中断。例如,若是想使用定时器/计数器0,须要添加下面一段 Keil C51 代码来开启 EA 和 ET0:事件
EA = 1; // 开启总中断 ET0 = 1; // 开启定时器/计数器0 中断
或者使用字节操做:图片
IE |= 0x82; // 设置 IE 寄存器为 10000010,即开启总中断和定时器/计数器0中断
若是使用汇编语言,开启外部中断 0 的汇编代码,字节操做为:string
MOV IE,#81H ;MOV 0A8H,#81H; 这里也能够直接使用 IE 寄存器的地址 A8H
或者使用汇编语言的位操做:
SETB EA SETB EX0
TMOD 用于控制定时器的工做模式,低4位用于 T0,高4位用于 T1。各个位的意义以下:
所在位 bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
所在位 bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | - | - | PT2 | PS | PT1 | PX1 | PT0 | PX0 |
所在位 bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
名称 | SM0 | SM1 | SM2 | REN | TB8 | RB8 | TI | RI |
SM0 | SM1 | 方式 | 说明 | 波特率 |
---|---|---|---|---|
0 | 0 | 0 | 8位数据发送 | fosc/12 |
0 | 1 | 1 | 10位数据发送,包括起始位,中止位 | 可变 |
1 | 0 | 2 | 11位数据发送,包括起始位,中止位 ,校验位 | fosc/64 |
1 | 1 | 3 | 同方式2 |
51单片机有5个中断源,5个中断源分别是:
中断能够根据优先级实现嵌套,51 系列能够实现 2 级嵌套(对应优先级寄存器 IP),52 系列能够实现 4 级嵌套(对应优先级寄存器 IP 和 IPH)。
中断名称 | 中断标志位 | 中断号 | 默认优先级 | 中断入口地址 |
---|---|---|---|---|
外部中断0 | IE0 | 0 | 高 | 0003H |
定时/计数器0溢出中断 | TF0 | 2 | ↓ | 000BH |
外部中断1 | IE1 | 1 | ↓ | 0013H |
定时/计数器1溢出中断 | TF1 | 3 | ↓ | 001BH |
串口发送或接收中断 | RI/TI | 4 | 低 | 0023H |
任何中断的使用都要知足 3 个条件:
EX = 1
EX0=1
中断系统有一个总的开关 EA(IE 寄存器中),若是想使用中断,必须打开总开关。
每一个中断都有一个单独的开关,这些单独的开关跟总开关 EA 同样,都在 IE 寄存器中。
假设我要每计数 24 次触发一次溢出中断,定时器工做在模式 1,则计数初始值为 65536 - 24 = 65512。
下面代码使用了外部中断0,上电后 P1 端口 0 号引脚的 LED 会一直闪烁,首次触发外部中断时,P1 端口全部 LED 点亮,再次触发外部中断时,0号引脚的 LED 再次开始闪烁,以此循环:
#include <reg52.h> int flag = 1; void delay() { unsigned int a = 50000; while(a--); } void main() { EA = 1;// 开启中断总开关 IT0 = 1;// 设置外部中断0触发方式,降低沿触发 EX0 = 1;// 开启外部中断0 while(1) { while(flag & 0x01 == 1) { P1 = 0xfe; delay(); P1 = 0xff; delay(); } P1 = 0x00; } } void externelInterrupt() interrupt 0 { flag++; }
电路图:
/*9600@11.0592M*/ #include <reg52.h> void InitUART(void) { TMOD = 0x20; SCON = 0x50; TH1 = 0xFD; TL1 = TH1; PCON = 0x00; EA = 1; ES = 1; TR1 = 1; } void SendOneByte(unsigned char c) { SBUF = c; while(!TI); TI = 0; } void main(void) { InitUART(); } void UARTInterrupt(void) interrupt 4 { if(RI) { RI = 0; } else TI = 0; }