一、实验要求
【实验目的】
1、熟悉51单片机的5个中断源;
2、掌握外部中断的中断初始化和中断服务函数的程序编写方法,编程实现实现数码管上显示外部中断计数。
【实验内容】
1、用Proteus绘制硬件原理图,并设置元件参数;
2、用KeilC51软件编程实现数码管上显示外部中断计数。
【硬件要求】
连接方法:P2.0-P2.7连接一只共阳型7段LED数码管,按键K1连接至单片机P3.2(INT0)引脚。
二、知识要点
(一)数码管
数码管是一种半导体发光器件,基本单元是发光二极管,玻璃管中包括一个金属丝网制成的阳极和多个阴极,它可以显示数字和其他信息。
按其内部结构即发光二极管单元连接方式不同可分为共阳极和共阳极两种数码管,共阳级数码管是指将数码管内部的发光二极管的阳极接到一起形成一个公共阳极(COM),当某一字段的发光二极管的阴极为低电平时,相对应的字段点亮,而当某一字段的阴极为高电平时,相对应的字段就不亮;共阴极数据管与共阳极数码管相反。
共阳的LED数码管在应用时应将公共极COM接到+5V;共阴的LED数码管在应用时应将公共极COM接到地线GND上。
(二)八段数码管的字形编码
以下是八段数码管的字形编码表,在使用时方便查阅:
字符 | 共阳极 | 共阴极 |
0 | C0H | 3FH |
1 | F9H | 06H |
2 | A4H | 5BH |
3 | B0H | 4FH |
4 | 99H | 66H |
5 | 92H | 6DH |
6 | 82H | 7DH |
7 | F8H | 07H |
8 | 80H | 7FH |
9 | 90H | 6FH |
(三)C51变量定义的四要素
C51变量定义的四要素如下:
1、存储种类(重点!)
存储种类分为四类:auto(自动型)、extern(外部型)、static(静态型)、register(寄存器型),默认的存储种类为自动型变量(auto),一般情况下不用写出来。
自动型变量的作用范围在定义它的函数体或语句块内,执行结束后,变量所占用的内存会被释放;
外部型的变量在其源文件中定义之后,在其它源文件中需要通过extern说明后才能使用该变量;
静态型与自动型相反,在执行结束后其占用的内存单元继续保留;
寄存器型变量是指将变量对应的存储单元指定为通用寄存器,从而可提高程序的运行速度。
2、数据类型
数据类型分为整型、长整型、字符型、浮点型和指针型五种数据类型。
3、存储类型(重点!)
C51编译器三种编译方式对应三种默认的存储类型:SMALL对应data类型、COMPACT对应pdata类型、LARGE对应xdata类型,一般情况下若无特殊声明,为SMALL编译模式。
data类型变量的存储区域位于直接寻址区(片内低128B RAM),其访问数据的速度最快且容量较小,作为常用变量或临时性变量存储器;
idata类型变量的存储区域位于间接寻址区(片内高128B RAM);
xdata类型变量的存储区域位于外部寄存器(片外64KB RAM),常用于存放不常用的变量或者待处理的数据;
pdata类型变量的存储区域位于分页寻址区(片外低256B RAM),常用于外部设备访问;
code类型变量的存储区域位于程序存储区(ROM),常用于存放数据表格等固定信息;
bdata类型变量的存储区域位于位寻址区(片内可位寻址区),其允许位与字节混合访问。
(四)中断源
C51单片机的中断系统有五个中断源,分为2个外部中断源和3个内部中断源,它们是两个外部中断INT0(P3.2)和INT1(P3.3)、两个片内定时器/计数器T0和T1和一个片内串行口的发送或接收中断请求源T1或R1。
另外具有两级中断优先级,由中断优先级控制寄存器IP控制,每个中断源的优先级高低都可以通过编程控制,中断允许受到CPU开中断和中断源开中断的两级控制。
(五)相关的特殊功能寄存器
1、定时器/计数器控制寄存器TCON
定时器/计数器控制寄存器TCON控制定时器/计数器的启动与停止以及标志定时器的溢出和中断情况,对TCON既可以采用字节寻址也可以采用位寻址,当51单片机系统复位时,TCON的所有位都会清零。
TCON的格式如下,高4位用于控制定时器/计数器的启动和中断请求,低4位控制外部中断:
(1)TR1和TR0为运行控制位,等于0时停止定时器工作,等于1时启动定时器工作(例启动定时器T1工作:TR1=1);
(2)TF1和TF0为溢出中断标志位,定时器溢出由硬件自动置为1,CPU响应中断后,硬件自动清零(例TF1=0无溢出,TF1=1时溢出);
(3)IT1和IT0为外部中断INT0、INT1的触发方式控制位,由软件来置1或清0,以控制外部中断的触发方式。(例IT1=1时,外部中断INT1为下降沿触发,IT1=0时,外部中断INT1为低电平触发);
(4)IE1和IE0为外部中断的请求标志位,当引脚上出现中断请求信号(低电平或脉冲下降沿)时,硬件自动将IEX置1,从而产生中断请求标志,而当CPU响应中断时,由硬件消除(例外部中断INT0P3.2引脚有中断请求信号时,IE0置1,即IE0=1)。
2、中断允许控制寄存器IE
在中断系统中,中断源向CPU发出中断请求后,由中断允许控制寄存器IE和中断优先级控制寄存器IP(本次实验未使用)来管理CPU。
中断允许控制寄存器IE控制中断源的开放或屏蔽,它共6位,字节地址为A8H,如下:
(1)EA为中断允许总控位,控制CPU的开放中断,当EA=0时,CPU屏蔽所有中断请求;EA=1时,CPU开放中断(5个中断源的中断请求是否允许,要根据其中断请求允许控制位来决定)。
(2)EX0、EX1分别为外部中断0允许位和外部中断1允许位,EX0=0时,禁止外部中断0中断,EX0=1时,允许外部中断0中断;EX1=0时,禁止外部中断1中断,EX1=1时,允许外部中断1中断。
(3)ET0、ET1分别为定时器/计数器Tx(x=0,1)溢出中断允许位,等于0时禁止Tx(x=0,1)中断,等于1时允许Tx(x=0,1中断。
(4)ES为串行口中断允许位,ES=0时禁止串行口中断,ES=1时允许串行口中断。
(六)中断程序
中断程序分为中断初始化和中断服务两个部分组成。
1、中断初始化步骤
中断初始化是指用户对特殊功能寄存器中的各控制位进行赋值,其步骤如下:
第一步,开相应中断源的中断,经中断允许控制寄存器IE;
第二步*(两个以上中断需设定优先级),设定所用中断源的中断优先级,经中断优先级控制寄存器IP;
第三步,若为外部中断,则应规定采取的触发方式,即采取的触发方式是电平触发方式或脉冲触发方式,经定时器控制寄存器TCON。
当外部中断采用电平触发方式时,CPU在每个机器周期的S5P2时刻都检测INT0和INT1引脚的输入电平,若检测到低电平,则认为由中断信号,且在中断服务结束前低电平必须清楚,否则中断返回之前将再次产生中断。
当外部中断采用脉冲触发方式时,CPU在每个机器周期的S5P2时刻都检测INT0和INT1引脚的输入电平,需连续检测两次(第一次检测为高电平,第二次检测为低电平),即检测一个下降沿才被认为是一个有效的中断请求信号。
2、中断服务程序函数
中断服务是指单片机检测到中断后响应中断事件,中断服务的步骤如下:
第一步,在中断向量入口放置一条跳转指令,让程序从该入口跳转到实际代码的起始位置;
第二步,保存当前寄存器的内容;
第三步,清除中断标志位,处理中断事件;
第四步,恢复寄存器的内容,返回到原来主程序的执行处;
也就是创建中断服务程序函数,该函数的定义格式如下,其中n为中断源编号,可以为0-31之间的整数,前面跟上interrupt表示将函数声明为中断服务函数,而using m由于实现工作寄存器组的切换,m即为中断服务子程序中选用的工作寄存器组号(0-3):
返回值 函数名称([参数])interrupt n[using m]{ }
要注意中断服务函数不能进行参数传递,且它没有返回值(可以将中断服务函数定义为void类型),另外不能调用中断服务函数,因为会导致编译错误。
三、Proteus仿真软件画原理图
原理图如下,其中的八段数码管为7SEG-MPX1-CA,按键与P3端的P3.2INT0相连(外部中断0请求输入端,低电平有效,这里采用电平触发方式):
四、Keil编程软件编写程序
首先创建一个数组Tab[],根据C51变量定义的四要素,将数组Tab定义为unsigned char code Tab[],其中的code的含义是用code把数组Tab[]定义在程序存储器中,总的来说就是定义一个无符号字符型(自动变量)数组Tab[],且该变量位于ROM中,根据共阳极数码管段码,即unsigned char code Tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
。
设置一个延时函数,依然还是设置一个有参数的函数,调用函数delay(1000)即延时1秒:
//延时函数 void delay(unsigned int x) { unsigned int i,j; for(i=0;i<x;i++) for(j=0;j<125;j++); }
编写中断服务程序函数,如下:
unsigned char m; ... //中断服务程序函数 void counter(void) interrupt 0 { EX0=0; //禁止外部中断0中断 m++; //中断计数 P2=Tab[m]; //依次取数组Tab内的元素 if(m==10) { m=0; P2=Tab[m]; } EX0=1; //允许外部中断0中断 }
完整程序代码如下:
#include<reg51.h> unsigned char m; unsigned char code Tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //共阳极,对应八段数码管的数字0-9 void delay(unsigned int x) //延时函数 { unsigned int i,j; for(i=0;i<x;i++) for(j=0;j<125;j++); } void counter(void) interrupt 0 { EX0=0; //禁止外部中断0中断 m++; //中断计数 P2=Tab[m]; //依次取数组Tab内的元素 if(m==10) { m=0; P2=Tab[m]; } EX0=1; //允许外部中断0中断 } void main() { EX0=1; //允许外部中断0中断 IT0=1; //外部中断INT0为下降沿触发 EA=1; //使能CPU,CPU开放中断 while(1) { P2=Tab[m]; //依次取数组Tab内的元素 delay(1000); //调用延时函数,参数为1000,即1s } }
五、实验结果
(一)仿真结果
导入可执行文件,点击开始仿真:
按下按键一次:
按下第二次:
……依次到第九次,数字到9:
(二)连接电路
注意排线的接线方式,否则数码管会显示错误:
(三)烧录并观察实验现象
烧录后,实验现象如下,按下按键:
再次按下按键,数字变为2:
……依次,按第九次按键,显示数字9: