找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1367|回复: 14
收起左侧

求助:中断函数问题

[复制链接]
ID:1059305 发表于 2022-12-28 14:30 | 显示全部楼层 |阅读模式
目的:单片机上电后,显示流水灯,按下按键后小灯全亮,然后返回主函数,继续显示流水灯。
目前问题:按下按键后,小灯全亮,但松开按键后小灯还是保持全亮,没有恢复中断前的状态。
请问这是什么原因导致,以下是代码
#include <reg52.h>
#include <intrins.h>
#define LED P0

sbit K1=P3^2;
int a;

void delay(ms)
{
        int i;
        while(ms--)
        {
                for (i=0;i<100;i++)
                {
                        ;
                }
        }
}

void zhongduan()
{
        EA=1;
        EX0=1;
}

void main()
{
        a=0;
        zhongduan();
        LED=0xfe;
        delay(200);
        while(1)
        {
               
                for(a=0;a<7;a++)
                {
                        LED=_crol_(LED,1);

                        delay(250);
                }
               
                for(a=0;a<7;a++)
                {
                        LED=_cror_(LED,1);

                        delay(250);
                }
      
}
}
void init0() interrupt 0
{
        if(K1==0)
        {
                delay(10);
                if(K1==0)
                {
                        LED=0x00;
                        delay(200);
                }
        }
      
}
回复

使用道具 举报

ID:213173 发表于 2022-12-28 20:17 | 显示全部楼层
你在中断中已经改变LED状态0x00,出中断后LED没有恢复之前状态,主函数继续左(右)移0x00能有什么意义?

void init0() interrupt 0
{
        unsigned char num;

        if(K1==0)
        {
                delay(10);
                if(K1==0)
                {
                        num=LED;//保存当前状态
                        LED=0x00;
                        delay(200);
                        LED=num;//恢复之前状态
                }
        }
}
回复

使用道具 举报

ID:1056573 发表于 2022-12-29 05:30 | 显示全部楼层
void zhongduan()函数里少了个外部中断触发方式IT0=1;。
回复

使用道具 举报

ID:94031 发表于 2022-12-29 07:01 | 显示全部楼层
中断处理要求时间越短越好,不要在中断里延时。
回复

使用道具 举报

ID:1059305 发表于 2022-12-29 09:31 | 显示全部楼层
wulin 发表于 2022-12-28 20:17
你在中断中已经改变LED状态0x00,出中断后LED没有恢复之前状态,主函数继续左(右)移0x00能有什么意义?
...

谢谢!!!!我明白了
回复

使用道具 举报

ID:1059305 发表于 2022-12-29 09:35 | 显示全部楼层
ytchfp163 发表于 2022-12-29 05:30
void zhongduan()函数里少了个外部中断触发方式IT0=1;。

我也试过加上这个IT0=1但还是不行,按照上一楼修改代码,可以不写IT0=1也可以实现
回复

使用道具 举报

ID:1059305 发表于 2022-12-29 09:36 | 显示全部楼层
xuyaqi 发表于 2022-12-29 07:01
中断处理要求时间越短越好,不要在中断里延时。

好的,好的下一步我试试用个定时器代替延时
回复

使用道具 举报

ID:624769 发表于 2022-12-29 13:34 来自手机 | 显示全部楼层
了解一下什么叫现场保护,恢复现场,学会push,pop的用法。
回复

使用道具 举报

ID:1059305 发表于 2022-12-29 14:20 | 显示全部楼层
188610329 发表于 2022-12-29 13:34
了解一下什么叫现场保护,恢复现场,学会push,pop的用法。

谢谢,我看了一下,好像了解现场保护和恢复现场,但目前我对这堆栈空间的使用理解并不深,比较熟悉的就只是使用指针,但怎么释放堆的内存我还没懂,目前打算学一学基础知识,然后做点小项目,一边做一边学,相互印证。
回复

使用道具 举报

ID:384109 发表于 2022-12-29 14:42 | 显示全部楼层
需要检测按键的释放,需要一个变量来保存按键按下时LED的状态
回复

使用道具 举报

ID:77589 发表于 2022-12-29 15:07 | 显示全部楼层
中断响应后,执行中断响应程序后,需要清除中断标志,如果没有清除中断标志位,单片机就会一直重复响应中断,其它代码就不会执行。
好久没用51单片机了,不知道说的对不对,但可以试试。
回复

使用道具 举报

ID:1059305 发表于 2022-12-29 16:42 | 显示全部楼层
Longan.Wang 发表于 2022-12-29 15:07
中断响应后,执行中断响应程序后,需要清除中断标志,如果没有清除中断标志位,单片机就会一直重复响应中断 ...

我刚刚试了一下,在中断结束后清除中断标志位,但还是没有恢复中断前状态,我觉得问题还是在2楼所说的,在中断时改变了LED的状态,然后没有恢复之前的状态。按照2楼所说的操作,我成功实现中断后LED恢复原来的状态。这是我添加的清除中断标志位,不知道有没有错。
  1. void init0() interrupt 0
  2. {

  3.         if(K1==0)
  4.         {
  5.                 delay(10);
  6.                 if(K1==0)
  7.                 {
  8.       LED=0x00;
  9.                         delay(200);
  10.                         IE0=0;
  11.                
  12.                 }
  13.         }
  14.        
  15. }
复制代码
回复

使用道具 举报

ID:1059305 发表于 2022-12-29 16:44 | 显示全部楼层
人中狼 发表于 2022-12-29 14:42
需要检测按键的释放,需要一个变量来保存按键按下时LED的状态

是的,需要保存中断前的状态,然后再恢复状态
回复

使用道具 举报

ID:1059578 发表于 2022-12-29 17:37 | 显示全部楼层
不要在中断里延时
回复

使用道具 举报

ID:624769 发表于 2022-12-30 20:52 | 显示全部楼层
LLL2022 发表于 2022-12-29 14:20
谢谢,我看了一下,好像了解现场保护和恢复现场,但目前我对这堆栈空间的使用理解并不深,比较熟悉的就只 ...

以你的代码为例, 你要在主函数中 不断 改变 "LED"    而中断中又要 “临时的” 改变“LED”,而退出中断后又希望恢复“LED”本来的内容。虽然不建议这种中断中 Delay 的写法,但是,先不说这个。 这其中的“LED” 就是你需要保护的现场。这个时候一般需要用到  入栈 和 出栈 比如:

void init0() interrupt 0
{
        _push_(LED);          //入栈
        if(K1==0)
        {
                delay(10);
                if(K1==0)
                {
                        LED=0x00;
                        delay(200);
                }
        }
        _pop_(LED);          //出栈      
}

当然,沙发的那个方法也可以,但是,如果有中断嵌套,多个涉及到 相同的“现场”,就不如 出入栈来的稳妥了。


回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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