protues仿真+C51+外部中断
C51的外部中断只用到TCON寄存器、IE寄存器、IP寄存器。
1. TCON定时器控制寄存器:
TCON | 8FH | 8EH | 8DH | 8CH | 8BH | 8AH | 89H | 88H |
88H | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
外部中断用到TCON的低4位:IE1、IT1、IE0、IT0。
IE0:外部中断0的中断请求标志。
当外部中断引脚0上存在有效的中断请求信号时,由硬件使IE1置1。
CPU响应该中断请求时,由硬件使IE1清0。
IT0:外部中断0的中断触发方式控制位
IT0=0时:外部中断0为低电平触发方式。
CPU在每一个机械周期S5P2期间采样外部中断0引脚的输入电平。
当引脚为低电平时IE0=1,引脚为高电平时IE0=0。
IT0=1时:外部中断0为下降沿触发方式。
CPU在每一个机械周期S5P2期间采样外部中 断0引脚的输入电平。
如果相继两个机械周期采用过程中,一个为高电平,下一个为低电平。
则使IE1=1,直到CPU响应该中断时,才由硬件使IE0清0。
同理,IE1,IT1的功能与IE0、IT0的完全一样,但分别控制外部中断1、外部中断0。
2. IE中断允许寄存器
IE | AFH | AEH | ADH | ACH | ABH | AAH | A9H | A8H |
88H | EA | 未使用 | 未使用 | ES | ET1 | EX1 | ET0 | EX0 |
外部中断使用到IE中断允许寄存器的:EA、EX1、EX0。
EA:中断允许总控制位。
EA=0屏蔽所有中断请求;EA=1,CPU开放中断。
EX0:外部中断0中断允许位。
EX0=0屏蔽外部中断0中断请求;EX0=1,CPU开放外部中断0中断请求。
EX1:外部中断1中断允许位。
EX1=0屏蔽外部中断1中断请求;EA=1,CPU开放外部中断1中断请求。
3. IP中断优先级寄存器
IP | BCH | BBH | BAH | B9H | D8H | |||
D8H | 未使用 | 未使用 | 未使用 | PS | PT1 | PX1 | PT0 | PX0 |
外部中断用到IP中断优先级寄存器的PX0、PX1
PX0:外部中断0中断优先级控制位;
PX1:外部中断1中断优先级控制位;
对应控制位置1则相应的中断源就规定为高优先级,反之为低优先级。
当同时接收到几个同一优先级中断请求时,优先响应哪个中断源则取决于内部硬件查询顺序。
查询顺序:外部中断0、定时器0、外部中断1、定时器1、串行口中断。
例如:设置外部中断0和外部中断1为高优先级,当两个外部中断同时触发时,根据查询方式可确定优先响应外部中断0。
4.外部中断0和外部中断1——下降沿触发、低电平触发
4.1 main.c文件
#include "reg51.h"
#include "ExternalInterrupt.h"char Flag=0;
char Led_array[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,0xFF};void main(){ExternalInterrupt_Init(Ex_Interrupt0_1,Low_Trigger);while(1){P1=Led_array[Flag];
}}
通过修改ExternalInterrupt_Init(Ex_Interrupt0,Low_Trigger);函数的参数,达到开启不同外部中断,不同触发方式。
参数1:设置开启的外部中断 参数2:设置触发方式
Ex_Interrupt0 | Ex_Interrupt1 | Ex_Interrupt0_1 | Low_Trigger | Falling_Trigger |
开启外部中断0 | 开启外部中断1 | 开启外部中断0和1 | 下降沿触发 | 低电平触发 |
Ex_Interrupt0、Ex_Interrupt1、Ex_Interrupt0_1,Low_Trigger、Falling_Trigger
都声明在ExternalInterrupt.h文件中。
4.2 ExternalInterrupt.c文件
#include "ExternalInterrupt.h"
#include "intrins.h"
extern char Flag;void Delay50ms() //@11.0592MHz
{unsigned char i, j, k;_nop_();_nop_();i = 3;j = 26;k = 223;do{do{while (--k);} while (--j);} while (--i);
}void ExternalInterrupt_Init(char Flag,char Mode){if (Flag == 0) { // 外部中断0IE |= 0x81; // 使能外部中断0if (Mode == 1) {TCON |= 0x01;} // 设置外部中断0为下降沿触发else {TCON &= ~0x01;}} // 设置外部中断0为低电平触发 else if (Flag == 1) { // 外部中断1IE |= 0x84; // 使能外部中断1if (Mode == 1) {TCON |= 0x04;} // 设置外部中断1为下降沿触发else {TCON &= ~0x04;}} // 设置外部中断1为低电平触发else if (Flag == 2) { // 外部中断1且设置为高优先级IE |= 0x85; // 使能外部中断1、外部中断0if (Mode == 1) {TCON |= 0x05;} // 设置外部中断1为下降沿触发else {TCON &= ~0x05;} // 设置外部中断1为低电平触发IP |= 0x04;} // 设置外部中断1为高优先级else IE &= 0x7F;
}void ExternalInterrupt0() interrupt 0 {Delay50ms(); // 延时一段时间Flag++;if(Flag>7){Flag=0;}}void ExternalInterrupt1() interrupt 2 {Delay50ms(); // 延时一段时间Flag--;if(Flag<0){Flag=7;}}
可以在 void ExternalInterrupt0() interrupt 0 和 void ExternalInterrupt1() interrupt 2 中断函数编写自己想要的功能函数。
4.3 ExternalInterrupt.h
#ifndef __EXTERNALINTERRUPT__H
#define __EXTERNALINTERRUPT__H
#include "reg51.h"
#define Ex_Interrupt0 0
#define Ex_Interrupt1 1
#define Ex_Interrupt0_1 2
#define Low_Trigger 0
#define Falling_Trigger 1
void ExternalInterrupt_Init(char Flag,char Mode);#endif
4.4 protues仿真
5.注意事项
当设置外部中断0和外部中断为低电平触发时,按下触发按键会导致发生多次触发中断。所以提供的代码中进行简单的延时消抖,快
速按下松开按键不会触发多次中断,但是长时间按下按键,还是会出发多次中断。
6. protues仿真文件下载
.........