找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

帖子
查看: 10585|回復(fù): 28
收起左側(cè)

C51單片機(jī)如何通過外部中斷INT0,跳出主程序中的while死循環(huán)?

  [復(fù)制鏈接]
ID:888259 發(fā)表于 2021-3-5 11:42 | 顯示全部樓層 |閱讀模式
本帖最后由 17826075805 于 2021-3-6 10:14 編輯

如何通過外部中斷INT0,跳出主程序中的while死循環(huán)?1.問題背景
由于項(xiàng)目需要,選擇相應(yīng)的程序運(yùn)行后如果不是人為打斷,功能函數(shù)內(nèi)的while循環(huán)是一直運(yùn)行下去的。
2.需求實(shí)現(xiàn)
需要通過外部中斷INT0,使程序能夠跳出功能函數(shù)內(nèi)的while死循環(huán)。


求助,希望論壇大佬能夠提供一下思路。

功能函數(shù)存在死循環(huán)

功能函數(shù)存在死循環(huán)

中斷服務(wù)中的處理

中斷服務(wù)中的處理
回復(fù)

使用道具 舉報(bào)

ID:235200 發(fā)表于 2021-3-5 12:36 | 顯示全部樓層
while(1)循環(huán)內(nèi)分類做兩個(gè)循環(huán),無中斷在一類循環(huán)中,有中中斷在另一類循環(huán)中
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-5 13:37 | 顯示全部樓層
csmyldl 發(fā)表于 2021-3-5 12:36
while(1)循環(huán)內(nèi)分類做兩個(gè)循環(huán),無中斷在一類循環(huán)中,有中中斷在另一類循環(huán)中

有中斷的while循環(huán)要怎樣做呢?我的程序中的while循環(huán)都是有中斷類循環(huán)
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-5 13:41 | 顯示全部樓層
問題補(bǔ)充:可否利用goto語句在中斷中做跳轉(zhuǎn)呢?
回復(fù)

使用道具 舉報(bào)

ID:716656 發(fā)表于 2021-3-5 14:35 | 顯示全部樓層
需求2:功能函數(shù)跳出用break就行,如果用中斷,就在中斷函數(shù)里給變量賦值,在功能函數(shù)里加if(變量==y){變量=x;break;} 這樣就解決了。       需求1:打斷主函數(shù)while(1)運(yùn)行……這我就不會(huì)了還能這樣么?確實(shí)沒有見過。。。。主要不知道打斷了要干什么?程序復(fù)位么?

評(píng)分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-5 14:42 | 顯示全部樓層
壓著我頭發(fā)啦 發(fā)表于 2021-3-5 14:35
需求2:功能函數(shù)跳出用break就行,如果用中斷,就在中斷函數(shù)里給變量賦值,在功能函數(shù)里加if(變量==y){變 ...

是需求1的意思,類似于程序復(fù)位,好比正在播放歌曲,這個(gè)時(shí)候按下退出按鍵,正在播放的歌曲就退出了。并不是復(fù)位。
回復(fù)

使用道具 舉報(bào)

ID:304608 發(fā)表于 2021-3-5 14:44 | 顯示全部樓層
有兩種思路:
1.設(shè)置一個(gè)全局變量(flag), 在中斷過響應(yīng)中改變flag的值,然后在while輪詢,監(jiān)測(cè)到flag改變后break就跳出來了。
2.使用goto語句, 簡(jiǎn)單粗暴,不推薦使用,破壞程序完整性。

評(píng)分

參與人數(shù) 1黑幣 +20 收起 理由
admin + 20 回帖助人的獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-5 14:48 | 顯示全部樓層
profile5 發(fā)表于 2021-3-5 14:44
有兩種思路:
1.設(shè)置一個(gè)全局變量(flag), 在中斷過響應(yīng)中改變flag的值,然后在while輪詢,監(jiān)測(cè)到flag改變 ...

goto語句只能用在函數(shù)內(nèi)部,不能跳轉(zhuǎn)到函數(shù)的外部
采用中斷輪詢響應(yīng)flag也要等待一次while循環(huán)完成后程序運(yùn)行到判斷flag的地方才行。這樣做響應(yīng)速度太慢了。而且會(huì)影響到while循環(huán)內(nèi)部的延時(shí)。
回復(fù)

使用道具 舉報(bào)

ID:879348 發(fā)表于 2021-3-5 15:45 | 顯示全部樓層
感覺你中斷的概念都沒搞清楚
回復(fù)

使用道具 舉報(bào)

ID:304608 發(fā)表于 2021-3-5 15:58 | 顯示全部樓層
17826075805 發(fā)表于 2021-3-5 14:48
goto語句只能用在函數(shù)內(nèi)部,不能跳轉(zhuǎn)到函數(shù)的外部
采用中斷輪詢響應(yīng)flag也要等待一次while循環(huán)完成后程 ...

思路要開闊,

你可以把while中的內(nèi)容切片成無數(shù)個(gè)小的執(zhí)行單元,比如傳送一首歌數(shù)據(jù),你可以在while中每ms調(diào)用一次數(shù)據(jù)傳遞函數(shù)啊,這樣監(jiān)測(cè)到flag的變化也僅僅需要1ms的時(shí)間哇,

咳。�?�, 要不,換芯片,上操作系統(tǒng)吧。。
回復(fù)

使用道具 舉報(bào)

ID:883031 發(fā)表于 2021-3-5 16:05 | 顯示全部樓層
goto指令
回復(fù)

使用道具 舉報(bào)

ID:822755 發(fā)表于 2021-3-5 22:26 | 顯示全部樓層
實(shí)在需要這樣,可以使用push, pop來修改中斷返回地址。
但是,實(shí)際上,可以更合理設(shè)計(jì)程序結(jié)構(gòu)來避免這樣操作。
回復(fù)

使用道具 舉報(bào)

ID:858964 發(fā)表于 2021-3-5 23:50 | 顯示全部樓層
本帖最后由 Kxuan163 于 2021-3-6 00:00 編輯


#include<reg51.h>   

int flag;  //定義全局變量


// 外中斷INT0的中斷服務(wù)程序:
void int0(void) interrupt 0 using 0  //INT0的中斷號(hào)為0
{
  flag = 0;        //使循環(huán)條件不成立
  ;
}

void main(void)   //主程序
  {
   EA=1;   / /開中斷
   EX0=1;  //允許使用INT0外中斷
   IT0=1;  //選擇負(fù)跳變來觸發(fā)外中斷

   flag =1; //首先使循環(huán)條件成立
   while(flag==1)  //無限循環(huán)
    {
           // 循環(huán)體的語句

         ;
     }

}


// 以上程序,我用Keil 編譯通過。
回復(fù)

使用道具 舉報(bào)

ID:213173 發(fā)表于 2021-3-6 08:38 | 顯示全部樓層
17826075805 發(fā)表于 2021-3-5 14:42
是需求1的意思,類似于程序復(fù)位,好比正在播放歌曲,這個(gè)時(shí)候按下退出按鍵,正在播放的歌曲就退出了。并 ...

如果按樓主的思路設(shè)計(jì)程序構(gòu)架,可以采用軟復(fù)位的方式輕松實(shí)現(xiàn)。
1.主函數(shù)設(shè)兩個(gè)互不關(guān)聯(lián)的while死循環(huán),其它子函數(shù)當(dāng)然都可以調(diào)用。main初始化時(shí)讀取EEPROM保存的分支信息確定運(yùn)行哪個(gè)循環(huán)。
2.外部中斷INT0函數(shù)中,判斷正在運(yùn)行中的是哪個(gè)死循環(huán),改寫EEPROM,啟動(dòng)軟復(fù)位。
3.重啟,讀EEPROM,進(jìn)入另一個(gè)死循環(huán)。
4.掉電后再上電,運(yùn)行的是掉電前的循環(huán)。
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-6 08:59 | 顯示全部樓層
Kxuan163 發(fā)表于 2021-3-5 23:50
#include   

int flag;  //定義全局變量

我開始也是這樣做的,只是while循環(huán)內(nèi)部的所要做的工作很多,并且有3h的大延遲,如果中斷錯(cuò)過while開始時(shí)的flag判斷,那么必須要等到下次while循環(huán)后程序才能停止。
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-6 09:04 | 顯示全部樓層
KongQuan 發(fā)表于 2021-3-5 22:26
實(shí)在需要這樣,可以使用push, pop來修改中斷返回地址。
但是,實(shí)際上,可以更合理設(shè)計(jì)程序結(jié)構(gòu)來避免這樣 ...

實(shí)際上我的需求是這樣的,項(xiàng)目需要進(jìn)入一種電源模式,然后通過控制繼電器陣列通斷。這個(gè)電源模式的切換是周期性的,閉合2.5h,斷開0.5小時(shí),一直循環(huán)運(yùn)行下去。現(xiàn)在要做的就是通過外部中斷可以隨時(shí)跳出這個(gè)循環(huán)。
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-6 09:07 | 顯示全部樓層
wulin 發(fā)表于 2021-3-6 08:38
如果按樓主的思路設(shè)計(jì)程序構(gòu)架,可以采用軟復(fù)位的方式輕松實(shí)現(xiàn)。
1.主函數(shù)設(shè)兩個(gè)互不關(guān)聯(lián)的while死循環(huán) ...

我的硬件電路暫時(shí)沒上E^2PROOM
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-6 09:14 | 顯示全部樓層
本帖最后由 17826075805 于 2021-3-6 09:18 編輯
wufa1986 發(fā)表于 2021-3-5 15:45
感覺你中斷的概念都沒搞清楚

所謂中斷,就是在主程序運(yùn)行過程中停下來去處理中斷服務(wù),中斷服務(wù)結(jié)束后,重新返回程序入口接著主函數(shù)繼續(xù)執(zhí)行。更為底層的操作,就是中斷觸發(fā)時(shí),將當(dāng)前主程序的下一條程序地址通過PC壓入棧中(現(xiàn)場(chǎng)保護(hù)),然后將中斷服務(wù)函數(shù)地址(中斷向量地址)放入PC,CPU在PC中取指令,主程序跳轉(zhuǎn)到中斷服務(wù)函數(shù)入口執(zhí)行中斷,當(dāng)中斷服務(wù)函數(shù)執(zhí)行完畢后,PC再將棧中的程序入口地址取出棧,CPU在PC中取指令,程序跳轉(zhuǎn)到中斷前的主函數(shù)斷點(diǎn)處繼續(xù)執(zhí)行主程序(現(xiàn)場(chǎng)恢復(fù))。
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-6 09:34 | 顯示全部樓層
profile5 發(fā)表于 2021-3-5 15:58
思路要開闊,

你可以把while中的內(nèi)容切片成無數(shù)個(gè)小的執(zhí)行單元,比如傳送一首歌數(shù)據(jù),你可以在w ...

還是想嘗試去搞一下,實(shí)在不行,我也打算換芯片,上操作系統(tǒng)了
回復(fù)

使用道具 舉報(bào)

ID:213173 發(fā)表于 2021-3-6 09:42 | 顯示全部樓層
17826075805 發(fā)表于 2021-3-6 09:07
我的硬件電路暫時(shí)沒上E^2PROOM

上面所述只是按你的思路設(shè)想的構(gòu)架。其實(shí)不論多少個(gè)分支,每個(gè)分支運(yùn)行多長(zhǎng)時(shí)間,都可以在一個(gè)主循環(huán)內(nèi)處理。關(guān)鍵在于解決問題的思路和設(shè)計(jì)程序的構(gòu)架。難道你一個(gè)分支就有上萬條代碼?
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-6 09:48 | 顯示全部樓層
我這邊想通過替換棧中中斷產(chǎn)生所保存的主程序入口地址來實(shí)現(xiàn)。通俗一點(diǎn)的講就是趁單片機(jī)處理中斷服務(wù)的時(shí)候(趁它不注意),偷偷把它當(dāng)時(shí)存放的東西調(diào)包,當(dāng)它回過神來,拿著那個(gè)東西就走了。也就是實(shí)現(xiàn)了利用外部中斷來跳出死循環(huán)的功能,現(xiàn)在重點(diǎn)問題是要找到外部中斷產(chǎn)生時(shí),主函數(shù)程序入口地址被保存在棧中的哪個(gè)位置。然后如何通過匯編指令做程序的跳轉(zhuǎn)。
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-6 10:57 | 顯示全部樓層

goto不能再函數(shù)間跳轉(zhuǎn),只能在函數(shù)內(nèi)部跳轉(zhuǎn)
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-6 11:40 | 顯示全部樓層
wulin 發(fā)表于 2021-3-6 09:42
上面所述只是按你的思路設(shè)想的構(gòu)架。其實(shí)不論多少個(gè)分支,每個(gè)分支運(yùn)行多長(zhǎng)時(shí)間,都可以在一個(gè)主循環(huán)內(nèi)處 ...

我上傳的部分代碼截圖,方便看下?
回復(fù)

使用道具 舉報(bào)

ID:858964 發(fā)表于 2021-3-6 17:11 | 顯示全部樓層
17826075805 發(fā)表于 2021-3-6 09:07
我的硬件電路暫時(shí)沒上E^2PROOM

你的硬件電路用的51單片機(jī)型號(hào)是什么,可否用有EEPROM的兼容型號(hào)芯片代替?
回復(fù)

使用道具 舉報(bào)

ID:517951 發(fā)表于 2021-3-7 19:50 | 顯示全部樓層
解決思路:設(shè)置一個(gè)全局變量(flag), 在中斷過響應(yīng)中改變flag的值,然后在while(flag==1);輪詢,監(jiān)測(cè)到flag=0改變后break就跳出來了。
回復(fù)

使用道具 舉報(bào)

ID:822755 發(fā)表于 2021-3-7 21:41 | 顯示全部樓層
Jinbw 發(fā)表于 2021-3-6 09:04
實(shí)際上我的需求是這樣的,項(xiàng)目需要進(jìn)入一種電源模式,然后通過控制繼電器陣列通斷。這個(gè)電源模式的切換是 ...

這個(gè)解決起來很簡(jiǎn)單, 把2.5h, 0.5h用計(jì)時(shí)來做。
大概就是開啟定時(shí)器中斷, 中斷中做志。在循環(huán)中檢查定時(shí)標(biāo)志,不停累加計(jì)時(shí)就行。同時(shí)以檢查外部中斷,隨時(shí)都可以中止循環(huán),不存在在2.5h中,無法檢查標(biāo)志的問題。
回復(fù)

使用道具 舉報(bào)

ID:888259 發(fā)表于 2021-3-8 11:38 | 顯示全部樓層
KongQuan 發(fā)表于 2021-3-7 21:41
這個(gè)解決起來很簡(jiǎn)單, 把2.5h, 0.5h用計(jì)時(shí)來做。
大概就是開啟定時(shí)器中斷, 中斷中做志。在循環(huán)中檢查定 ...

好的,我試一下
回復(fù)

使用道具 舉報(bào)

ID:885009 發(fā)表于 2021-3-8 12:06 | 顯示全部樓層
設(shè)置一個(gè)全局變量 = 1
while(全局變量)
{
}
在中斷中使 全局變量 = 0
功能想稍微有用點(diǎn)的可以
設(shè)置一個(gè) 二進(jìn)制 全局變量 = 1
while(全局變量 )
{
}
while(~全局變量)
{
}
在中斷中使 全局變量 = ~全局變量
回復(fù)

使用道具 舉報(bào)

ID:63132 發(fā)表于 2021-5-14 16:15 來自觸屏版 | 顯示全部樓層
把按鍵值作為while的判斷條件
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表