找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7100|回复: 8
收起左侧

单片机外部中断实验程序有错误

[复制链接]
ID:243437 发表于 2017-10-27 15:17 | 显示全部楼层 |阅读模式
实验二:外部中断实验
一、实验目的
1掌握外部中断技术的基本使用方法;
2掌握中断处理程序的编写方法;
3、进一步掌握KeilProteus软件的用法。
二、实验说明
1.外部中断的初始化设置共有三项内容:中断总允许即EA=1,外部中断允许即EXi=1i=01),中断方式设置。中断方式设置一般有两种方式:电平方式和脉冲方式,本实验选用后者,其前一次为高电平后一次为低电平时为有效中断请求。因此高电平状态和低电平状态至少维持一个周期,中断请求信号由引脚INT0(P3.2)INT1(P3.3)引入,本实验由INT0(P3.2)引入。
2.中断服务的关键:
A.保护进入中断时的状态。
堆栈有保护断点和保护现场的功能使用PUSH指令,在转中断服务程序之前把单片机中有关寄存单元的内容保护起来。
B.必须在中断服务程序中设定是否允许中断重入,即设置EX0位。
C.用POP指令恢复中断时的现场。
3.中断控制原理:
中断控制是提供给用户使用的中断控制手段。实际上就是控制一些寄存器,51系列用于此目的的控制寄存器有四个:TCON IE SCON IP
4.中断响应的过程:
首先中断采样然后中断查询最后中断响应。采样是中断处理的第一步,对于本实验的脉冲方式的中断请求,若在两个相邻周期采样先高电平后低电平则中断请求有效,IE0IE11;否则继续为0。所谓查询就是由CPU测试TCONSCON中各标志位的状态以确定有没有中断请求发生以及是那一个中断请求。中断响应就是对中断请求的接受,是在中断查询之后进行的,当查询到有效的中断请求后就响应一次中断。
INT0端接单次脉冲发生器。P1LED并行口JD3,以查看LED在每次中断时的移位过程。
三、实验内容及步骤
1、用Keil软件编辑中断控制应用程序,采用P3.2接入开关K0P3.3接入开关K1引入外部中断01,外部中断0服务程序点亮8LED,外部中断1服务程序实现P1口驱动流水灯,0.5s变换一次。
2、用proteus软件绘制实验所需硬件电路,并进行仿真运行。
3用试验箱载入程序并运行程序:
P1口做输出口,接八位逻辑电平显示,P3.2P3.3接开关输入外部中断信号,中断程序功能使发光二极管循环点亮。
1最小系统中插上80C51核心板,用扁平数据线连接MCUP1口与八位逻辑电平显示模块JD3
2)用串行数据通信线连接计算机与实验箱的RS232串口,将实验箱RS232串口的端子RXD和TXD插到实验芯片模块的P3.0和P3.1插孔中,建立PC机与实验箱单片机芯片的串行通信联系。
3)打开电脑桌面上的Keil uVision4仿真软件,建立实验的项目文件夹和项目文件,在项目文件的源文件界面上输入实验源程序,并对源程序进行编译,直到编译无误,并连接生成hex目标文件。
4)打开电脑桌面上的STC烧录软件,下载并装载目标程序到实验单片机芯片,然后上电全速运行程序,观察程序运行的结果:程序功能使发光二极管循环点亮的流水灯的效果。
四、源程序
实验程序一:
#include<reg51.h>
void delay(unsigned int d)  //定义延时子函数
{
while(--d>0);
}
void main()
{
P1=0xff;    //熄灭LED
EA=1;
EX0=1;
EX1=1;
IT0=1;
IT1=1;
for(;;)
{;}
}
void INT0_ISR() interrupt 0   //外中断0服务函数
{
P1=0x00;
PX0=0;
PX1=1;
}
void INT1_ISR() interrupt 2   //外中断1服务函数
{
while(1)
{
delay(15000);
P1=0xfe;
delay(15000);
P1=0xfd;
delay(15000);
P1=0xfb;
delay(15000);
P1=0xf7;
delay(15000);
P1=0xef;
delay(15000);
P1=0xdf;
delay(15000);
P1=0xbf;
delay(15000);
P1=0x7f;
PX0=1;
PX1=0;
}
}

这个程序错在哪里?

回复

使用道具 举报

ID:243562 发表于 2017-10-27 23:39 | 显示全部楼层
51单片机里的独立按键中的k3,k4接着的是单片机里的中断IO口INT0和INT1,所以你打开的中断对应着的是开发板独立按键中的k3和k4。
但是在中断子程序中,你没有写按键的程序。
从你的课题里可以看出,你是想写流水灯的程序。但是流水灯的程序并不是用延迟函数写的,是用左移右移函数或者是定时器写的。
建议你重新写程序吧,尤其是你要知道自己所写程序的每一行代码的含义。

评分

参与人数 1黑币 +60 收起 理由
admin + 60 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:237210 发表于 2017-10-27 22:13 | 显示全部楼层
不要在中断函数内部搞这种延时工作,中断在执行过程中是不会响应其它中断的,除非手动打开和高级中断

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:243562 发表于 2017-10-27 23:30 | 显示全部楼层
你的led灯都没有定义IO口啊,而且你想学的是外部中断但是外部中断里却没有中断程序啊。
回复

使用道具 举报

ID:213173 发表于 2017-10-28 10:09 | 显示全部楼层
这个例程只是演示两个外部中断功能,只要有此功能就无所谓对和错,不足之处是是可以从INT0转到INT1,反之不行,是因为while(1)下面死循环出不来。
回复

使用道具 举报

ID:228284 发表于 2017-10-28 11:11 | 显示全部楼层
中断里面不能写while(1)
回复

使用道具 举报

ID:243655 发表于 2017-10-28 12:41 | 显示全部楼层
d没有初始定义
回复

使用道具 举报

ID:212797 发表于 2017-10-28 14:58 | 显示全部楼层
外部中断1的服务程序写的很糟糕,里面不断有长时间的延时程序还有while(1)这样的死循环,另外按键程序没有延时消抖。根据以上,我建议将程序如下修改:
1、设置两个中断触发标志位全局变量,当外部中断触发以后,在中断服务程序中只是将标志位置位即可;
2、主函数中外部中断初始化后,在主循环中查询中断触发标志位,如果变量置位则处理相关的动作;
3、由于外部中断是和独立按键相连,在中断触发后,需要延时消抖确认按键触发,防止是误动作;
程序的整体结构如下:
void main()
{
    sys_init();
    while (1)
    {
        if(int0_flag)
        {
            int0_flag = 1;
            delay to debounce;
            light up all the lights;
        }

         if(int1_flag)
        {
            delay to debounce;
            flowing water light;
        }
    }
}

void int0_isr() interrupt 0
{
    int0_flag = 1;
}

void int1_isr() interrupt 0
{
    int1_flag = 1;
}
回复

使用道具 举报

ID:111634 发表于 2017-10-28 22:12 | 显示全部楼层
本帖最后由 zl2168 于 2017-10-28 22:16 编辑

多学学正确的东西,脱离正确的东西,自己瞎想,会走人误区。给你介绍一本书,《80C51单片机仿真设计实例教程——基于Keil C和Proteus》清华大学出版社ISBN 978-7-302-41682-1,内有常用的单片机应用100案例,用于仿真实验操作,电路与程序真实可靠可信可行,可演示,可观测,程序语句条条有注解。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表