นี่เป็นคำถามที่พ่อของฉันมักจะถามฉันเสมอ " ทำไมมันไม่ทำงานตามคำแนะนำทั้งหมดและหยุดในตอนท้าย "
ลองมาดูตัวอย่างทางพยาธิวิทยา โค้ดต่อไปนี้รวบรวมในคอมไพเลอร์ C18 ของ Microchip สำหรับ PIC18:
void main(void)
{
}
มันสร้างผลลัพธ์แอสเซมเบลอร์ดังต่อไปนี้:
addr opco instruction
---- ---- -----------
0000 EF63 GOTO 0xc6
0002 F000 NOP
0004 0012 RETURN 0
.
. some instructions removed for brevity
.
00C6 EE15 LFSR 0x1, 0x500
00C8 F000 NOP
00CA EE25 LFSR 0x2, 0x500
00CC F000 NOP
.
. some instructions removed for brevity
.
00D6 EC72 CALL 0xe4, 0 // Call the initialisation code
00D8 F000 NOP //
00DA EC71 CALL 0xe2, 0 // Here we call main()
00DC F000 NOP //
00DE D7FB BRA 0xd6 // Jump back to address 00D6
.
. some instructions removed for brevity
.
00E2 0012 RETURN 0 // This is main()
00E4 0012 RETURN 0 // This is the initialisation code
อย่างที่คุณเห็นมีการเรียก main () และท้ายที่สุดจะมีคำสั่ง return แม้ว่าเราจะไม่ได้ใส่ไว้ในนั้นเอง เมื่อผลตอบแทนหลัก CPU ดำเนินการคำสั่งต่อไปซึ่งเป็นเพียง GOTO เพื่อกลับไปที่จุดเริ่มต้นของรหัส main () ถูกเรียกอย่างง่าย ๆ ซ้ำแล้วซ้ำอีก
ตอนนี้ต้องบอกว่านี่ไม่ใช่วิธีที่คนทั่วไปจะทำสิ่งต่าง ๆ ฉันไม่เคยเขียนโค้ดที่ฝังไว้ใด ๆ ซึ่งจะทำให้ main () ออกจากนั้น ส่วนใหญ่รหัสของฉันจะเป็นดังนี้:
void main(void)
{
while(1)
{
wait_timer();
do_some_task();
}
}
ดังนั้นฉันจะไม่ปล่อยให้ทางออกหลัก ()
"ตกลงตกลง" คุณพูด ทั้งหมดนี้น่าสนใจมากที่คอมไพเลอร์ทำให้แน่ใจว่าจะไม่มีคำสั่งการส่งคืนล่าสุด แต่จะเกิดอะไรขึ้นถ้าเราบังคับให้ปัญหาเกิดขึ้น? ถ้าฉันเขียนรหัสแอสเซมเบลอร์ของฉันด้วยมือและไม่ได้กระโดดกลับไปที่จุดเริ่มต้น
เห็นได้ชัดว่าซีพียูจะยังคงรันคำสั่งต่อไป สิ่งเหล่านั้นจะมีลักษณะเช่นนี้:
addr opco instruction
---- ---- -----------
00E6 FFFF NOP
00E8 FFFF NOP
00EA FFFF NOP
00EB FFFF NOP
.
. some instructions removed for brevity
.
7EE8 FFFF NOP
7FFA FFFF NOP
7FFC FFFF NOP
7FFE FFFF NOP
ที่อยู่หน่วยความจำถัดไปหลังจากคำสั่งสุดท้ายใน main () ว่างเปล่า บนไมโครคอนโทรลเลอร์ที่มีหน่วยความจำ FLASH คำสั่งเปล่าประกอบด้วยค่า 0xFFFF อย่างน้อยใน PIC นั้นรหัส op นั้นถูกตีความว่าเป็น 'nop' หรือ 'no operation' มันไม่ทำอะไรเลย ซีพียูจะยังคงดำเนินการ nops เหล่านั้นต่อไปจนสุดความทรงจำ
หลังจากนั้นจะเกิดอะไรขึ้น
ที่คำสั่งสุดท้ายตัวชี้คำสั่งของ CPU คือ 0x7FFe เมื่อ CPU เพิ่ม 2 เข้ากับตัวชี้คำสั่งมันจะได้รับ 0x8000 ซึ่งถือว่าเป็นโอเวอร์โฟลว์บน PIC ที่มี 32k FLASH เท่านั้นและมันจะล้อมรอบกลับไปที่ 0x0000 และ CPU ก็ดำเนินการตามคำแนะนำที่จุดเริ่มต้นของรหัสต่อไปอย่างมีความสุข ราวกับว่ามันถูกรีเซ็ต
คุณยังถามเกี่ยวกับความจำเป็นในการปิดเครื่อง โดยทั่วไปคุณสามารถทำสิ่งที่คุณต้องการและมันขึ้นอยู่กับใบสมัครของคุณ
หากคุณมีแอปพลิเคชันที่จำเป็นต้องทำสิ่งใดสิ่งหนึ่งหลังจากเปิดเครื่องแล้วไม่ทำอะไรเลยคุณสามารถทำได้เพียงสักครู่ (1); ในตอนท้ายของ main () เพื่อให้ CPU หยุดทำสิ่งที่เห็นได้ชัดเจน
หากแอปพลิเคชันต้องการให้ CPU ปิดเครื่องแล้วขึ้นอยู่กับ CPU อาจมีโหมดสลีปต่างๆ อย่างไรก็ตามซีพียูมีนิสัยตื่นขึ้นมาอีกครั้งดังนั้นคุณต้องตรวจสอบให้แน่ใจว่าไม่มีการ จำกัด เวลาในการนอนและไม่ต้องใช้ Watch Dog Timer ทำงาน ฯลฯ
คุณสามารถจัดระเบียบวงจรภายนอกบางอย่างที่จะช่วยให้ CPU ตัดพลังงานของตัวเองเมื่อเสร็จสิ้น ดูคำถามนี้: การใช้ปุ่มกดชั่วขณะเป็นล็อคเปิดปิดสวิทช์สลับ