這是我父親一直問我的問題。 “ 為什麼不只執行所有指令並在最後停下來?”
我們來看一個病理示例。以下代碼是在Microchip的PIC18的C18編譯器中編譯的:
void main(void){}
它會產生以下彙編輸出:
addr opco指令---- ---- ----------- 0000 EF63 GOTO 0xc60002 F000 NOP0004 0012返回0 ..為簡潔起見,刪除了一些指令.00C6 EE15 LFSR 0x1,0x50000C8 F000 NOP00CA EE25 LFSR 0x2,0x50000CC F000 NOP ..為簡潔起見刪除了一些指令.00D6 EC72 CALL 0xe4,0 //調用初始化代碼00D8 F000 NOP // 00DA EC71 CALL 0xe2,0 //在這裡我們稱為main() 00DC F000 NOP // // 00DE D7FB BRA 0xd6 //跳轉回地址00D6 ..為了簡潔起見刪除了一些指令.00E2 0012 RETURN 0 //這是main()00E4 0012 RETURN 0 //這是初始化代碼
如您所見,main()i稱為,最後包含一個return語句,儘管我們自己沒有明確地將它放在那裡。當main返回時,CPU執行下一條指令,即GOTO,返回到代碼的開頭。簡單地反複調用main()。
現在,儘管如此,這不是人們通常會做的事情。我從未寫過任何允許main()退出的嵌入式代碼。通常,我的代碼如下所示:
void main(void){while(1){wait_timer(); do_some_task(); }}
所以我通常不會讓main()退出。
您說“好吧好”。所有這些非常有趣,因為編譯器確保永遠不會有最後一個return語句。但是,如果我們強制執行該問題會怎樣?如果我手工編碼了我的彙編程序,但又沒有跳回開頭怎麼辦?
很明顯,CPU只會繼續執行下一條指令。看起來像這樣:
addr opco指令---- ---- ----------- 00E6 FFFF NOP00E8 FFFF NOP00EA FFFF NOP00EB FFFF NOP ..為簡潔起見,刪除了一些指令。7EE8FFFF NOP7FFA FFFF NOP7FFC FFFF NOP7FFE FFFF NOP
main()中最後一條指令之後的下一個內存地址為空。在具有閃存的微控制器上,空指令包含值0xFFFF。至少在PIC上,該操作碼被解釋為“ nop”或“ no operation”。它根本什麼也沒做。 CPU將從內存一直一直執行到所有末尾。
這之後是什麼?
在最後一條指令中,CPU的指令指針為0x7FFe。當CPU在其指令指針上加2時,它得到0x8000,這在只有32k FLASH的PIC上被認為是溢出,因此它迴繞回0x0000,CPU高興地在代碼開始處繼續執行指令,就像已將其重置一樣。
您還詢問了是否需要關機。基本上,您可以做任何您想做的事,這取決於您的應用程序。
如果您確實有一個應用程序,該應用程序在開機後只需要做一件事,然後什麼也不做,那麼您就可以放一會兒(1);在main()的末尾,以便CPU停止執行任何明顯的操作。
如果應用程序需要關閉CPU的電源,則取決於CPU,可能會有各種可用的睡眠模式。但是,CPU有重新喚醒的習慣,因此您必須確保睡眠沒有時間限制,也沒有看門狗定時器處於活動狀態,等等。
您甚至可以組織一些外部設備。電路完成後,將允許CPU完全切斷自身的電源。看到以下問題:使用瞬時按鈕作為閂鎖開關按鈕。