单片机实验:外部中断系统实验
Date: March 23, 2022
具体代码直接见最下面:
总结:
总结本次实验:
本次学会 单片机的外部中断响应
即通过 外部中断 来实现不同功能
实验内容:
1
当我们切换开关,比如切换SW2,从高电频到低电频,就会产生下降沿,即,中断,从而引发相应功能
外部中断编程说明:
(1)选中何种方式触发中断————选微信铃声
本实验采用 边沿触发有效:
TCON:定时器控制寄存器
如下图上行八位,这里注意IT1和IT0:
其中,IT1设置外部中断1,IT0设置外部中断0
若我们想要让外部中断0设置为边沿触发有效,那就让 IT0 = 1
若我们想要让外部中断0设置为低电频有效,那就让 IT0 = 0
(2)响应中断—————是否接电话
本实验采用开中断,即一中断,就响应
IE寄存器设置:
EA = 1, EX = 1, EX0 = 1 以上三者都设置为1,CPU才会响应中断
(3)设置中断优先级
本实验并没有设置
注意:外部中断0的优先级最高,外部中断1是其次
由于本次实验,需要设置边沿触发方式有效,所以需要让 IT0 = 1 , IT1 = 1
程序分析:
注意:uchar flag 默认为0
流水灯:1111 1110 ~ 0111 1111
void int1() interrupt 0 interrupt 0指外部中断0的函数
这是一个中断函数,至于它是几的中断函数,看interrupt后的数
关于interrupt()函数的补充:
interruput X 语句 X是中断标号 计算公式是 :(地址-3)/8=中断标号,其中“地址”*/
指的是 中断服务程序 的入口地址,比如:
外部中断0,入口地址为0003H,对应的中断标号为0
外部中断1,入口地址为0013H(十进制为19),对应中断标号为2
定时器0中断,入口地址为000BH(十进制为11),对应中断标号为1
定时器1中断,入口地址为001BH(十进制为27),对应标号为3
串口中断,入口地址为0023H(十进制为35),对应中断标号4
入口地址在数据手册里有
void int2() interrupt 2 interrupt 2指外部中断1的函数
注意:EA EX1 EX0 = 1 意味着会响应边沿触发
IT1 IT0 = 1 意味着选择边沿触发方式
注意一开始 flag = 0, 当有 边沿触发时,即我们将开关从高电位切到低电位时,会有中断产生,具体情况如下:
比如切换开关SW2,从高电频到低电频,即 边沿触发,会有中断产生,
当产生中断时,程序又会自动跳到中断函数处:
此时会改变flag = 0x01
从而当程序再次进入main函数中时,switch就会切换到 flag = 1,从而选择case1
即选择 流水灯
case 1: for(i=0;i<8;i++){ if(flag==0x02) break; P2=tab[i]; delay(1); } if(flag==0x02) break; //也许是异常处理 P2=0x00; //全亮 delay(1); break;
思考题:
操作步骤:
程序设计思路:
1357亮
延时函数
2468亮
延时函数:
修改程序即可,加1s的延时即可,借助于STC的延时函数
注意:0为低电位,7为高电位
最终代码:
#include "reg51.h" #include<intrins.h> //可以使用_nop_函数的头文件 #define uchar unsigned char const tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f} ; //正向流水灯 uchar flag; void delay(int x){ //延时程序 unsigned i,j,k; while(x--){ for(i=0;i<0x01;i++) for(j=0;j<0xff;j++) for(k=0;k<0xff;k++); } } //延时1s: void Delay1000ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); _nop_(); i = 43; j = 6; k = 203; do { do { while (--k); } while (--j); } while (--i); } void int1()interrupt 0 //外部中断0的中断服务函数 { flag=0x01; } void int2()interrupt 2 //外部中断1的中断服务函数 { flag=0x02; } void main(){ uchar i; EA=1; //总中断允许 EX0=1; //允许外部中断0中断 EX1=1; //允许外部中断1中断 IT0=1; //选择外部中断0为跳沿触发方式 IT1=1; //选择外部中断1为跳沿触发方式 P2=0xff; while(1) { switch(flag){ case 1: for(i=0;i<8;i++){ if(flag==0x02) break; P2=tab[i]; delay(1); } if(flag==0x02) break; P2=0x00; delay(1); break; case 2: //功能:要让1357灯亮,2468灯灭 P2 = 0xaa; Delay1000ms(); P2 = 0x55; Delay1000ms(); break; //test: success! //拓展:所有灯全亮,过1s,全灭 /* P2=0x00; delay(1); P2=0xff; delay(1); break; */ } } }