找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6611|回复: 28
打印 上一主题 下一主题
收起左侧

C51单片机如何通过外部中断INT0,跳出主程序中的while死循环?

  [复制链接]
跳转到指定楼层
楼主
ID:888259 发表于 2021-3-5 11:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 17826075805 于 2021-3-6 10:14 编辑

如何通过外部中断INT0,跳出主程序中的while死循环?1.问题背景
由于项目需要,选择相应的程序运行后如果不是人为打断,功能函数内的while循环是一直运行下去的。
2.需求实现
需要通过外部中断INT0,使程序能够跳出功能函数内的while死循环。


求助,希望论坛大佬能够提供一下思路。

捕获2.PNG (24.84 KB, 下载次数: 93)

功能函数存在死循环

功能函数存在死循环

捕获.PNG (88.76 KB, 下载次数: 97)

中断服务中的处理

中断服务中的处理
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:235200 发表于 2021-3-5 12:36 | 只看该作者
while(1)循环内分类做两个循环,无中断在一类循环中,有中中断在另一类循环中
回复

使用道具 举报

板凳
ID:888259 发表于 2021-3-5 13:37 | 只看该作者
csmyldl 发表于 2021-3-5 12:36
while(1)循环内分类做两个循环,无中断在一类循环中,有中中断在另一类循环中

有中断的while循环要怎样做呢?我的程序中的while循环都是有中断类循环
回复

使用道具 举报

地板
ID:888259 发表于 2021-3-5 13:41 | 只看该作者
问题补充:可否利用goto语句在中断中做跳转呢?
回复

使用道具 举报

5#
ID:716656 发表于 2021-3-5 14:35 | 只看该作者
需求2:功能函数跳出用break就行,如果用中断,就在中断函数里给变量赋值,在功能函数里加if(变量==y){变量=x;break;} 这样就解决了。       需求1:打断主函数while(1)运行……这我就不会了还能这样么?确实没有见过。。。。主要不知道打断了要干什么?程序复位么?

评分

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

查看全部评分

回复

使用道具 举报

6#
ID:888259 发表于 2021-3-5 14:42 | 只看该作者
压着我头发啦 发表于 2021-3-5 14:35
需求2:功能函数跳出用break就行,如果用中断,就在中断函数里给变量赋值,在功能函数里加if(变量==y){变 ...

是需求1的意思,类似于程序复位,好比正在播放歌曲,这个时候按下退出按键,正在播放的歌曲就退出了。并不是复位。
回复

使用道具 举报

7#
ID:304608 发表于 2021-3-5 14:44 | 只看该作者
有两种思路:
1.设置一个全局变量(flag), 在中断过响应中改变flag的值,然后在while轮询,监测到flag改变后break就跳出来了。
2.使用goto语句, 简单粗暴,不推荐使用,破坏程序完整性。

评分

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

查看全部评分

回复

使用道具 举报

8#
ID:888259 发表于 2021-3-5 14:48 | 只看该作者
profile5 发表于 2021-3-5 14:44
有两种思路:
1.设置一个全局变量(flag), 在中断过响应中改变flag的值,然后在while轮询,监测到flag改变 ...

goto语句只能用在函数内部,不能跳转到函数的外部
采用中断轮询响应flag也要等待一次while循环完成后程序运行到判断flag的地方才行。这样做响应速度太慢了。而且会影响到while循环内部的延时。
回复

使用道具 举报

9#
ID:879348 发表于 2021-3-5 15:45 | 只看该作者
感觉你中断的概念都没搞清楚
回复

使用道具 举报

10#
ID:304608 发表于 2021-3-5 15:58 | 只看该作者
17826075805 发表于 2021-3-5 14:48
goto语句只能用在函数内部,不能跳转到函数的外部
采用中断轮询响应flag也要等待一次while循环完成后程 ...

思路要开阔,

你可以把while中的内容切片成无数个小的执行单元,比如传送一首歌数据,你可以在while中每ms调用一次数据传递函数啊,这样监测到flag的变化也仅仅需要1ms的时间哇,

咳。。咳, 要不,换芯片,上操作系统吧。。
回复

使用道具 举报

11#
ID:883031 发表于 2021-3-5 16:05 | 只看该作者
goto指令
回复

使用道具 举报

12#
ID:822755 发表于 2021-3-5 22:26 | 只看该作者
实在需要这样,可以使用push, pop来修改中断返回地址。
但是,实际上,可以更合理设计程序结构来避免这样操作。
回复

使用道具 举报

13#
ID:858964 发表于 2021-3-5 23:50 | 只看该作者
本帖最后由 Kxuan163 于 2021-3-6 00:00 编辑


#include<reg51.h>   

int flag;  //定义全局变量


// 外中断INT0的中断服务程序:
void int0(void) interrupt 0 using 0  //INT0的中断号为0
{
  flag = 0;        //使循环条件不成立
  ;
}

void main(void)   //主程序
  {
   EA=1;   / /开中断
   EX0=1;  //允许使用INT0外中断
   IT0=1;  //选择负跳变来触发外中断

   flag =1; //首先使循环条件成立
   while(flag==1)  //无限循环
    {
           // 循环体的语句

         ;
     }

}


// 以上程序,我用Keil 编译通过。
回复

使用道具 举报

14#
ID:213173 发表于 2021-3-6 08:38 | 只看该作者
17826075805 发表于 2021-3-5 14:42
是需求1的意思,类似于程序复位,好比正在播放歌曲,这个时候按下退出按键,正在播放的歌曲就退出了。并 ...

如果按楼主的思路设计程序构架,可以采用软复位的方式轻松实现。
1.主函数设两个互不关联的while死循环,其它子函数当然都可以调用。main初始化时读取EEPROM保存的分支信息确定运行哪个循环。
2.外部中断INT0函数中,判断正在运行中的是哪个死循环,改写EEPROM,启动软复位。
3.重启,读EEPROM,进入另一个死循环。
4.掉电后再上电,运行的是掉电前的循环。
回复

使用道具 举报

15#
ID:888259 发表于 2021-3-6 08:59 | 只看该作者
Kxuan163 发表于 2021-3-5 23:50
#include   

int flag;  //定义全局变量

我开始也是这样做的,只是while循环内部的所要做的工作很多,并且有3h的大延迟,如果中断错过while开始时的flag判断,那么必须要等到下次while循环后程序才能停止。
回复

使用道具 举报

16#
ID:888259 发表于 2021-3-6 09:04 | 只看该作者
KongQuan 发表于 2021-3-5 22:26
实在需要这样,可以使用push, pop来修改中断返回地址。
但是,实际上,可以更合理设计程序结构来避免这样 ...

实际上我的需求是这样的,项目需要进入一种电源模式,然后通过控制继电器阵列通断。这个电源模式的切换是周期性的,闭合2.5h,断开0.5小时,一直循环运行下去。现在要做的就是通过外部中断可以随时跳出这个循环。
回复

使用道具 举报

17#
ID:888259 发表于 2021-3-6 09:07 | 只看该作者
wulin 发表于 2021-3-6 08:38
如果按楼主的思路设计程序构架,可以采用软复位的方式轻松实现。
1.主函数设两个互不关联的while死循环 ...

我的硬件电路暂时没上E^2PROOM
回复

使用道具 举报

18#
ID:888259 发表于 2021-3-6 09:14 | 只看该作者
本帖最后由 17826075805 于 2021-3-6 09:18 编辑
wufa1986 发表于 2021-3-5 15:45
感觉你中断的概念都没搞清楚

所谓中断,就是在主程序运行过程中停下来去处理中断服务,中断服务结束后,重新返回程序入口接着主函数继续执行。更为底层的操作,就是中断触发时,将当前主程序的下一条程序地址通过PC压入栈中(现场保护),然后将中断服务函数地址(中断向量地址)放入PC,CPU在PC中取指令,主程序跳转到中断服务函数入口执行中断,当中断服务函数执行完毕后,PC再将栈中的程序入口地址取出栈,CPU在PC中取指令,程序跳转到中断前的主函数断点处继续执行主程序(现场恢复)。
回复

使用道具 举报

19#
ID:888259 发表于 2021-3-6 09:34 | 只看该作者
profile5 发表于 2021-3-5 15:58
思路要开阔,

你可以把while中的内容切片成无数个小的执行单元,比如传送一首歌数据,你可以在w ...

还是想尝试去搞一下,实在不行,我也打算换芯片,上操作系统了
回复

使用道具 举报

20#
ID:213173 发表于 2021-3-6 09:42 | 只看该作者
17826075805 发表于 2021-3-6 09:07
我的硬件电路暂时没上E^2PROOM

上面所述只是按你的思路设想的构架。其实不论多少个分支,每个分支运行多长时间,都可以在一个主循环内处理。关键在于解决问题的思路和设计程序的构架。难道你一个分支就有上万条代码?
回复

使用道具 举报

21#
ID:888259 发表于 2021-3-6 09:48 | 只看该作者
我这边想通过替换栈中中断产生所保存的主程序入口地址来实现。通俗一点的讲就是趁单片机处理中断服务的时候(趁它不注意),偷偷把它当时存放的东西调包,当它回过神来,拿着那个东西就走了。也就是实现了利用外部中断来跳出死循环的功能,现在重点问题是要找到外部中断产生时,主函数程序入口地址被保存在栈中的哪个位置。然后如何通过汇编指令做程序的跳转。
回复

使用道具 举报

22#
ID:888259 发表于 2021-3-6 10:57 | 只看该作者

goto不能再函数间跳转,只能在函数内部跳转
回复

使用道具 举报

23#
ID:888259 发表于 2021-3-6 11:40 | 只看该作者
wulin 发表于 2021-3-6 09:42
上面所述只是按你的思路设想的构架。其实不论多少个分支,每个分支运行多长时间,都可以在一个主循环内处 ...

我上传的部分代码截图,方便看下?
回复

使用道具 举报

24#
ID:858964 发表于 2021-3-6 17:11 | 只看该作者
17826075805 发表于 2021-3-6 09:07
我的硬件电路暂时没上E^2PROOM

你的硬件电路用的51单片机型号是什么,可否用有EEPROM的兼容型号芯片代替?
回复

使用道具 举报

25#
ID:517951 发表于 2021-3-7 19:50 | 只看该作者
解决思路:设置一个全局变量(flag), 在中断过响应中改变flag的值,然后在while(flag==1);轮询,监测到flag=0改变后break就跳出来了。
回复

使用道具 举报

26#
ID:822755 发表于 2021-3-7 21:41 | 只看该作者
Jinbw 发表于 2021-3-6 09:04
实际上我的需求是这样的,项目需要进入一种电源模式,然后通过控制继电器阵列通断。这个电源模式的切换是 ...

这个解决起来很简单, 把2.5h, 0.5h用计时来做。
大概就是开启定时器中断, 中断中做志。在循环中检查定时标志,不停累加计时就行。同时以检查外部中断,随时都可以中止循环,不存在在2.5h中,无法检查标志的问题。
回复

使用道具 举报

27#
ID:888259 发表于 2021-3-8 11:38 | 只看该作者
KongQuan 发表于 2021-3-7 21:41
这个解决起来很简单, 把2.5h, 0.5h用计时来做。
大概就是开启定时器中断, 中断中做志。在循环中检查定 ...

好的,我试一下
回复

使用道具 举报

28#
ID:885009 发表于 2021-3-8 12:06 | 只看该作者
设置一个全局变量 = 1
while(全局变量)
{
}
在中断中使 全局变量 = 0
功能想稍微有用点的可以
设置一个 二进制 全局变量 = 1
while(全局变量 )
{
}
while(~全局变量)
{
}
在中断中使 全局变量 = ~全局变量
回复

使用道具 举报

29#
ID:63132 发表于 2021-5-14 16:15 来自手机 | 只看该作者
把按键值作为while的判断条件
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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