Electoday 2025

ไมโครคอนโทรลเลอร์ => AVR and Arduino => Topic started by: tha on August 09, 2019, 01:36:22 PM

Title: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 09, 2019, 01:36:22 PM
17. EXINT - External Interrupts
The External Interrupts ถูกทริกโดย INT pins หรือพินใดพินหนึ่งของ PCINT pins. สังเกตได้ว่าถ้า enable แล้ว interrupts จะถูกทริก ถึงแม้ว่า INT หรือ PCINT pins ถูกกำหนดให้เป็น outputs ก็ตาม คุณสมบัติอย่างนี้จัดให้มีวิธีการสร้าง software interrupt

The Pin Change Interrupt Request 2 (PCI2) จะถูกทริก ถ้าพินใดพินหนึ่งใน PCINT[23:16] pin ที่ถูก enable มีการ toggles,  Pin Change Interrupt Request 1 (PCI1) จะถูกทริก ถ้าพินใดพินหนึ่งใน PCINT[14:8] pin ที่ถูก enable มีการ toggles,  Pin Change Interrupt Request 0 (PCI0) จะถูกทริก ถ้าพินใดพินหนึ่งใน PCINT[7:0] pin ที่ถูก enable มีการ toggles รีจีสเตอร์ PCMSK2, PCMSK1 และ PCMSK0 Registers ควบคุมว่าพินไหนบ้างที่ถูกทำให้เป็น pin change interrupts. Pin change interrupts บน PCINT ถูกตรวจจับแบบไมประสานเวลา(asynchronously) นี้หมายความว่า interrupts เหล่านี้สามารถใช้สำหรับปลุก(waking) sleep modes อื่นๆได้นอกเหนือจาก Idle mode
(ก็จะปลุก sleep mode แบบ power-down mode, power-save mode, standby mode ที่หยุด IO clock(CLKio) ด้วย ได้ด้วย ซึ่งทำให้ตรวจจับระดับสัญญานเป็น "0" ได้เท่านั้น (asynchronously) ไม่สามารถตรวจจับ ขอบขาขึ้น ขอบขาลง ที่ต้องใช้ IO clock ได้)

ปล. ดูตาราง sleep mode ร่วมด้วยนะ ว่า sleep mode แบบไหนหยุด IO clock(CLKio) บ้าง
ผมไม่ได้อยู่แอร์นะ วันนี้ครึ้มฟ้าครึ้มฝนอยู่ ก็ได้นิดหน่อยนะ พอดีช่วงเช้าไปธุระด้วย เลยได้แค่นี้  :D
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 09, 2019, 03:14:01 PM
External Interrupts (INT) สามารถถูกทริกโดยขอบขาลงหรือขอบขาขึ้นหรือระดับสัญญานเป็น "0" นี้สามารถเซทอัฟได้ดังที่แสดงในสเปคของ External Interrupt Control Register A (EICRA). เมื่อ External Interrupts ถูก enable และถูกกำหนดให้ระดับสัญญานเป็น "0" แล้วทริก interrupt จะถูกทริกตราบเท่าที่พินนั้นถูกทำให้อยู่ในระดับสัญญานเป็น "0" อยู่ บันทึกไว้ว่า การรู้ได้ของขอบขาลงหรือขอบขาขึ้น interrupt  บน INT นั้น ต้องการการมีอยู่ของสัญญานนาฬิกา IO clock ระดับสัญญานเป็น "0" interrupt  บน INT ถูกตรวจจับแบบไม่ประสานเวลา นี้หมายความว่า interrupts เหล่านี้สามารถใช้สำหรับปลุก(waking) sleep modes อื่นๆได้นอกเหนือจาก Idle mode,  I/O clock จะถูกหยุดในทุก sleep mode ยกเว้น Idle Mode

Note : ถ้าระดับสัญญานเป็น "0" ที่ทริก interrupt นั้น ถูกใช้สำหรับ wake-up จาก power-down mode ระดับสัญญานเป็น "0" ที่ต้องการนี้ จะต้องทำให้ยาวนานเพียงพอสำหรับ MCU wake-up เสร็จแล้วถึงจะทริก level interrupt ต่อ ถ้าระดับสัญญานเป็น "0" หายไปก่อนการสิ้นสุดของ start-up time, MCU จะยังคง wake-up แต่ interrupt จะไม่เกิดขึ้น start-up time นี้ถูกกำหนดโดย SUT และ CKSEL Fuses

ปล. วันนี้พอแค่นี้นะ พักสักหน่อย แล้วก็จะมาคิดเรื่องจิตใจบ้าง เรื่องธรรมะ ทำจิตใจให้ดีงาม นั่งสมาธิบ้างถ้าไม่ตึงเกินไป ใจสงบก็สุขไปอีกแบบ ดีกว่าความสุขแบบปกติสังคมเป็น อย่างดูฟุตบอลฟังเพลงเที่ยวกินเหล้าเที่ยวผู้หญิงฯลฯ
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 10, 2019, 02:35:49 PM
17.1. Pin Change Interrupt Timing
ตัวอย่างของ timing ของ pin change interrupt ถูกแสดงในรูปต่อไปนี้

(https://i.imgur.com/7lqDtIX.png)

ปล. ลองดูนะครับ ผมก็ไม่เป็นเท่าไหร่ ลืมไปบ้างแล้วลอจิก ก็ดูกราฟ timing พอผ่านๆ อย่างใช้เวลาไป 3 clock แล้ว PCIF ถึงเซท
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 10, 2019, 02:44:13 PM
17.2. Register Description

17.2.1. External Interrupt Control Register A
External Interrupt Control Register A บรรจุ control bits สำหรับ interrupt sense control.

(https://i.imgur.com/8SH1QXg.png)

Bits 3:2 – ISC1n: Interrupt Sense Control 1 [n = 1:0]
The External Interrupt 1 ถูกกระตุ้นให้ทำงาน(activate) โดยขา external pin INT1 ถ้า the SREG I-flag(Global Interrupt) และ the corresponding(ที่ตรงกัน) interrupt mask ถูกเซท ระดับสัญญานเป็น "0" และขอบขา(ขึ้น-ลง)บนขา external INT1 pin ที่กระตุ้นให้  interrupt ทำงาน ถูกกำหนดในตารางข้างล่างนี้ ค่าบนขา INT1 จะถูกสุ่มตรวจจับก่อนที่จะตรวจพบขอบขา(ขึ้น-ลง) ถ้าขอบขา(ขึ้น-ลง) หรือการสลับ(ทั้งขึ้นทั้งลง) interrupt ถูกเลือก สัญญาน pulses ที่นานกว่า 1 clock period จะเกิดการ interrupt  สัญญาน pulses ที่สั้นกว่า (1 clock period) ไม่การันตีว่าจะเกิดการ interrupt ถ้าระดับสัญญานเป็น "0" ถูกเลือก ระดับสัญญานเป็น "0"ต้องถูกทำให้ยืนนาน
จนกระทั่งเสร็จการปฏิบัติคำสั่งปัจจุบันถึงจะเกิดการ interrupt

(https://i.imgur.com/D6gNHoU.png)

Bits 1:0 – ISC0n: Interrupt Sense Control 0 [n = 1:0]
The External Interrupt 0 ถูกกระตุ้นให้ทำงาน(activate) โดยขา external pin INT0 ถ้า the SREG I-flag(Global Interrupt) และ the corresponding(ที่ตรงกัน) interrupt mask ถูกเซท ระดับสัญญานเป็น "0" และขอบขา(ขึ้น-ลง)บนขา external INT0 pin ที่กระตุ้นให้  interrupt ทำงาน ถูกกำหนดในตารางข้างล่างนี้ ค่าบนขา INT0 จะถูกสุ่มตรวจจับก่อนที่จะตรวจพบขอบขา(ขึ้น-ลง) ถ้าขอบขา(ขึ้น-ลง) หรือการสลับ(ทั้งขึ้นทั้งลง) interrupt ถูกเลือก สัญญาน pulses ที่นานกว่า 1 clock period จะเกิดการ interrupt  สัญญาน pulses ที่สั้นกว่า (1 clock period) ไม่การันตีว่าจะเกิดการ interrupt ถ้าระดับสัญญานเป็น "0" ถูกเลือก ระดับสัญญานเป็น "0"ต้องถูกทำให้ยืนนาน
จนกระทั่งเสร็จการปฏิบัติคำสั่งปัจจุบันถึงจะเกิดการ interrupt

(https://i.imgur.com/hXtRy7e.png)

ปล.   00 = ระดับสัญญานเป็น "0"
        01 = ทั้งขอบขาขึ้นขอบขาลง
        10 = ขอบขาลง
        11 = ขอบขาขึ้น
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 10, 2019, 02:48:51 PM
17.2.2. External Interrupt Mask Register
เมื่อระบุตำแหน่ง I/O Registers เป็น data space โดยใช้คำสั่ง LD(load) และ ST(store) instructions, the provided offset(ค่าจากจุดเริ่มต้น) จะต้องถูกใช้. เมื่อใช้คำสั่ง the I/O specific commands IN and OUT, the offset จะถูลดลงไป 0x20, ผลคือ I/O address offset จะอยู่ในระหว่าง 0x00 - 0x3F.(ดู 12.3 SRAM Data Memory ประกอบด้วย)

(https://i.imgur.com/IPCjku9.png)

Bit 1 – INT1: External Interrupt Request 1 Enable
เมื่อบิท INT1 ถูกเซทและบิท I-bit(global interrupt) ใน Status Register (SREG) ถูกเซทด้วย, the external pin interrupt จะถูก enable. The Interrupt Sense Control1 bits 1/0 (ISC11 and ISC10) ใน the External Interrupt Control Register A (EICRA) จะเป็นตัวกำหนดว่า external interrupt จะถูกกระตุ้นให้ทำงานที่ขอบขาขึ้นและหรือขอบขาลงของขา INT1 หรือระดับสัญญานเป็น "0" การกระตุ้นให้ทำงานบนขานี้จะเป็นเหตุให้เกิด interrupt request ถึงแม้ว่า INT1 ถูกกำหนดให้เป็น output ก็ตาม

Bit 0 – INT0: External Interrupt Request 0 Enable
เมื่อบิท INT0 ถูกเซทและบิท I-bit(global interrupt) ใน Status Register (SREG) ถูกเซทด้วย, the external pin interrupt จะถูก enable. The Interrupt Sense Control0 bits 1/0 (ISC01 and ISC00) ใน the External Interrupt Control Register A (EICRA) จะเป็นตัวกำหนดว่า external interrupt จะถูกกระตุ้นให้ทำงานที่ขอบขาขึ้นและหรือขอบขาลงของขา INT1 หรือระดับสัญญานเป็น "0" การกระตุ้นให้ทำงานบนขานี้จะเป็นเหตุให้เกิด interrupt request ถึงแม้ว่า INT0 ถูกกำหนดให้เป็น output ก็ตาม
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 10, 2019, 02:51:50 PM
17.2.3. External Interrupt Flag Register
เมื่อระบุตำแหน่ง I/O Registers เป็น data space โดยใช้คำสั่ง LD(load) และ ST(store) instructions, the provided offset(ค่าจากจุดเริ่มต้น) จะต้องถูกใช้. เมื่อใช้คำสั่ง the I/O specific commands IN and OUT, the offset จะถูลดลงไป 0x20, ผลคือ I/O address offset จะอยู่ในระหว่าง 0x00 - 0x3F.(ดู 12.3 SRAM Data Memory ประกอบด้วย)

(https://i.imgur.com/pAXJN6Z.png)

Bit 1 – INTF1: External Interrupt Flag 1
เมื่อขอบขา(ขึ้น-ลง)หรือขอบขา(ทั้งขึ้นทั้งลง)เปลี่ยนบนขา INT1 จะทริก interrupt request, INTF1 ก็จะถูกเซท ถ้า I-bit ใน SREG และบิท INT1 ใน EIMSK ถูกเซท MCU ก็จะกระโดดไปยัง corresponding(ที่ตรงกัน) Interrupt Vector, flag นี้จะถูกเคลียร์เมื่อโปรแกรมย่อยบริการอินเตอร์รัพท์ถูกปฏิบัติ อีกทางเลือกหนึ่ง flag นี้สามารถถูกเคลียร์โดยการเขียน "1" ไปยังบิทนี้ flag นี้จะถูกเคลียร์อย่างถาวรเมื่อ INT1 ถูกกำหนดให้เป็น level interrupt (ระดับสัญญานเป็น "0")

Bit 0 – INTF0: External Interrupt Flag 0
เมื่อขอบขา(ขึ้น-ลง)หรือขอบขา(ทั้งขึ้นทั้งลง)เปลี่ยนบนขา INT0 จะทริก interrupt request, INTF0 ก็จะถูกเซท ถ้า I-bit ใน SREG และบิท INT0 ใน EIMSK ถูกเซท MCU ก็จะกระโดดไปยัง corresponding(ที่ตรงกัน) Interrupt Vector, flag นี้จะถูกเคลียร์เมื่อโปรแกรมย่อยบริการอินเตอร์รัพท์ถูกปฏิบัติ อีกทางเลือกหนึ่ง flag นี้สามารถถูกเคลียร์โดยการเขียน "1" ไปยังบิทนี้ flag นี้จะถูกเคลียร์อย่างถาวรเมื่อ INT0 ถูกกำหนดให้เป็น level interrupt (ระดับสัญญานเป็น "0")
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 10, 2019, 03:09:38 PM
ดู 12.3. SRAM Data Memory ที่นี่ ว่ารีจีสเตอร์ที่เราดูอยู่แอสเดรสไหนกันบ้าง
http://www.electoday.com/index.php/topic,15827.msg38057.html#msg38057 (http://www.electoday.com/index.php/topic,15827.msg38057.html#msg38057)

เป็นยังไงบ้าง แปลดีไหม ก็จะพยายามแปลให้เข้าใจนะ อ่านไปอ่านมา คนแปลก็มีงงเหมือนกัน อาจจะเบลอนะ ต้องพักสักครู่ก่อน เวลาดีๆแล้วค่อยกลับมาอ่านดีกว่า ก็จะเข้าใจมากขึ้น หรืออ่านทำความเข้าใจสักสองสามรอบก็จะเข้าใจมากขึ้น ลองเปรียบเทียบกับภาษาอังกฤษดูเอานะ

พรุ่งนี้ก็จะยกตัวอย่าง มะรืนวันแม่ก็จะหยุดกันสักวัน
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 13, 2019, 01:20:55 PM
http://www.mediafire.com/file/hgrxcd3ijntxslb/INT_1.rar/file (http://www.mediafire.com/file/hgrxcd3ijntxslb/INT_1.rar/file)

อันนี้ตัวอย่าง INT1 interrupt เวลาอินเตอร์รัพท์แล้วเซท flag a เอา แต่เวลา build ในแบบบีบอัด(Optimization = -Os) จะไม่ทำงาน(ไม่เซท flag a) แต่เวลาไม่บีบอัด(Optimization = -O0) ก็จะทำงานได้ แต่ code size จะใหญ่ ก็ลอง build ดูได้ทั้ง winavr และ avr8 gnu toolchain เลย ก็จะเหมือนกันกับนี่แหละ http://www.electoday.com/index.php?topic=16901.8 (http://www.electoday.com/index.php?topic=16901.8)
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 13, 2019, 02:01:31 PM
http://www.mediafire.com/file/ukm4zb51sldrdhe/INT.rar/file (http://www.mediafire.com/file/ukm4zb51sldrdhe/INT.rar/file)

อันนี้ INT1 Interrupt แล้วจะปลุกขึ้นจาก sleep mode ก็จะตั้ง INT1 Interrupt ตรวจจับแบบ low level(ระดับสัญญานเป็น "0") ที่ไม่ต้องใช้สัญญานนาฬิกา IO clock (มีเพียง Idle Mode ใช่ไหมที่ไม่หยุด IO clock ก็จะตั้งเป็นขอบขาขึ้น ขอบขาลงและทั้งสองขอบขาได้อีก)

อันนี้ลองมาทั้ง 5 sleep mode เลย ก็สามารถทำงานปลุกให้ตื่นจาก sleep mode ได้

Quote
   //set_sleep_mode(SLEEP_MODE_IDLE);           // see detail in sleep.h
   //set_sleep_mode(SLEEP_MODE_PWR_DOWN);
   //set_sleep_mode(SLEEP_MODE_PWR_SAVE);
   //set_sleep_mode(SLEEP_MODE_STANDBY);
   set_sleep_mode(SLEEP_MODE_EXT_STANDBY);

เอา sleep mode ไว้ใช้ในตอน เราใช้ถ่านกับบอร์ด ตอนที่เราไม่ต้องการให้บอร์ดทำงาน เราก็ให้บอร์ดเข้า sleep mode พอเราอยากให้บอร์ดกลับมาทำงาน เราก็กดสวิทช์ INT1 interrupt ปลุกให้บอร์ดตื่น ทำอย่างนี้เพื่อประหยัดพลังงานถ่านไฟ

ปล. พอดีเน็ตล่มเลยหยุดไปสองวัน ตกลงให้ไปช้าๆใช่ไหม ก็ดีเหมือนกันนะ คนที่กำลังตามจะได้ตามทัน คนที่ตามทันแล้วจะได้แน่นๆ คนที่เก่งแล้วจะได้นำหน้าไปก่อน

ว่าไปวัตถุเทคโนโลยี่ก็เป็นดาบสองคมเหมือนกัน ดูอย่างมือถือสิ
หนังโป้กามราคะก็มีให้ดูกันอย่างง่ายๆ ทำเด็กสาวมีลูกก่อนวัยอันควร
ดูข่าวการเมืองก็กระตุ้นโทสะกันได้บ่อยๆ
ความอยากได้อยากมีอยากเป็นก็ถูกกระตุ้นกันอยู่บ่อยๆ ก็เพราะเราเห็นสิ่งของอะไรต่างๆที่อยากได้ ได้ง่ายๆในมือถือนี่แหละ
อย่างข่าวลูกจ้างคนฆ่าแม่ตัวเองหวังฮุบสมบัตินี่ สมัยก่อนไม่มีหรอก มีในสมัยนี้นี่แหละ
จิตใจคนไม่ดีเลย มือถือทำคนกิเลสหนาตัณหาจัด ใช่ป่าว

ได้อ่านหนังสือ "เมฆเหิน น้ำไหล" ที่พระเทพทรงแปล ก็ว่าการเร่งทำให้วัตถุเทคโนโลยี่เจริญอย่างรวดเร็ว ทำให้คนจิตใจไม่ดีเลย ทำให้คนรุ่นใหม่มีนิสัยเห็นแก่ตัวจัด หลอกลวงคตโกง แก่งแย่งแข่งขัน ทำอะไรก็ได้ ขอให้ได้ ขอให้ชนะ

ตกลงไปช้าๆเอานะพวกเรา ช้าไปเร็วไปก็บอกกันได้นะ
แต่อย่างไรประเทศเราเป็นเมืองร้อน พอร้อนก็อ่านหนังสือไม่ได้แล้ว
ถึงอย่างไรเราก็ตามเขาอยู่ไกล ได้สัก 10% ของจีนของอเมริกาได้หรือเปล่าครับ
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 14, 2019, 08:34:57 AM
17.2.4. Pin Change Interrupt Control Register

(https://i.imgur.com/bSgLFm5.png)

Bit 2 – PCIE2: Pin Change Interrupt Enable 2
เมื่อบิท PCIE2 ถูกเซทและบิท I-bit ใน Status Register (SREG) ถูกเซท, pin change interrupt 2 จะถูกเปิดการใช้งาน การเปลี่ยน(ทั้งขึ้นทั้งลง)บนขาใดขาหนึ่งของ PCINT[23:16] pin ที่ enable ไว้ จะเป็นเหตุให้เกิดการ interrupt. The corresponding(ที่ตรงกัน) interrupt ของ Pin Change Interrupt Request จะถูกปฏิบัติจาก PCI2 Interrupt Vector. PCINT[23:16] pins ถูก enabled เป็นรายขาโดย PCMSK2 Register

Bit 1 – PCIE1: Pin Change Interrupt Enable 1
เมื่อบิท PCIE1 ถูกเซทและบิท I-bit ใน Status Register (SREG) ถูกเซท, pin change interrupt 1 จะถูกเปิดการใช้งาน การเปลี่ยน(ทั้งขึ้นทั้งลง)บนขาใดขาหนึ่งของ PCINT[14:8] pin ที่ enable ไว้ จะเป็นเหตุให้เกิดการ interrupt. The corresponding(ที่ตรงกัน) interrupt ของ Pin Change Interrupt Request จะถูกปฏิบัติจาก PCI1 Interrupt Vector. PCINT[14:8] pins ถูก enabled เป็นรายขาโดย PCMSK1 Register
.
Bit 0 – PCIE0: Pin Change Interrupt Enable 0
เมื่อบิท PCIE0 ถูกเซทและบิท I-bit ใน Status Register (SREG) ถูกเซท, pin change interrupt 0 จะถูกเปิดการใช้งาน การเปลี่ยน(ทั้งขึ้นทั้งลง)บนขาใดขาหนึ่งของ PCINT[7:0] pin ที่ enable ไว้ จะเป็นเหตุให้เกิดการ interrupt. The corresponding(ที่ตรงกัน) interrupt ของ Pin Change Interrupt Request จะถูกปฏิบัติจาก PCI0 Interrupt Vector. PCINT[7:0] pins ถูก enabled เป็นรายขาโดย PCMSK0 Register

ปล. สงสัยในตอนต้นของบทนี้ผมจะเข้าใจผิด(บอกมาผิดด้วย ต้องกลับไปแก้ไหม) อันนี้ไม่ใช่ระดับสัญญญานเป็น "0" แต่จะเป็น any change (เปลี่ยนไป ก็คือทั้งขึ้นทั้งลง) แต่จะตรวจจับแบบไมประสานเวลา(asynchronously) คือ ไม่ต้องใช้สัญญานนาฬิกา IO clock (CLKio) ก็ได้ ก็จะมีการ sense ได้อย่างเดียว ก็เลยไม่มีบิทเลือกขอบขาให้ตั้ง
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 14, 2019, 12:22:27 PM
17.2.5. Pin Change Interrupt Flag Register
เมื่อระบุตำแหน่ง I/O Registers เป็น data space โดยใช้คำสั่ง LD(load) และ ST(store) instructions, the provided offset(ค่าจากจุดเริ่มต้น) จะต้องถูกใช้. เมื่อใช้คำสั่ง the I/O specific commands IN and OUT, the offset จะถูลดลงไป 0x20, ผลคือ I/O address offset จะอยู่ในระหว่าง 0x00 - 0x3F.(ดู 12.3 SRAM Data Memory ประกอบด้วย)

(https://i.imgur.com/czLhPjg.png)

Bit 2 – PCIF2: Pin Change Interrupt Flag 2
เมื่อลอจิกเปลี่ยน(ทั้งขึ้นทั้งลง)บนขาใดขาหนึ่งของขา PCINT[23:16] จะทริก interrupt request, PCIF2 ก็จะถูกเซท ถ้า I-bit ใน SREG และบิท PCIE2 ใน PCICR ถูกเซท, MCU ก็จะกระโดดไปยัง corresponding Interrupt Vector. flag นี้จะถูกเคลียร์เมื่อโปรแกรมย่อยบริการอินเตอร์รัพท์ถูกปฏิบัติ อีกทางเลือกหนึ่ง flag นี้สามารถถูกเคลียร์โดยการเขียน '1' ไปยังบิทนี้

Bit 1 – PCIF1: Pin Change Interrupt Flag 1
เมื่อลอจิกเปลี่ยน(ทั้งขึ้นทั้งลง)บนขาใดขาหนึ่งของขา PCINT[14:8]] จะทริก interrupt request, PCIF1 ก็จะถูกเซท ถ้า I-bit ใน SREG และบิท PCIE1 ใน PCICR ถูกเซท, MCU ก็จะกระโดดไปยัง corresponding Interrupt Vector. flag นี้จะถูกเคลียร์เมื่อโปรแกรมย่อยบริการอินเตอร์รัพท์ถูกปฏิบัติ อีกทางเลือกหนึ่ง flag นี้สามารถถูกเคลียร์โดยการเขียน '1' ไปยังบิทนี้

Bit 0 – PCIF0: Pin Change Interrupt Flag 0
เมื่อลอจิกเปลี่ยน(ทั้งขึ้นทั้งลง)บนขาใดขาหนึ่งของขา PCINT[7:0] จะทริก interrupt request, PCIF0 ก็จะถูกเซท ถ้า I-bit ใน SREG และบิท PCIE0 ใน PCICR ถูกเซท, MCU ก็จะกระโดดไปยัง corresponding Interrupt Vector. flag นี้จะถูกเคลียร์เมื่อโปรแกรมย่อยบริการอินเตอร์รัพท์ถูกปฏิบัติ อีกทางเลือกหนึ่ง flag นี้สามารถถูกเคลียร์โดยการเขียน '1' ไปยังบิทนี้
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 14, 2019, 12:51:18 PM
17.2.6. Pin Change Mask Register 2

(https://i.imgur.com/MbuD2nj.png)

Bits 0, 1, 2, 3, 4, 5, 6, 7 – PCINT16, PCINT17, PCINT18, PCINT19, PCINT20, PCINT21, PCINT22, PCINT23: Pin Change Enable Mask
แต่ละบิท PCINT[23:16]-bit เลือกได้ว่า pin change interrupt ใดถูก enable บนขา the corresponding I/O pin. ถ้าบิท PCINT[23:16] ใดถูกเซทและบิท PCIE2 ใน PCICR ถูกเซท, pin change interrupt ก็จะถูก enable บนขา corresponding I/O pin. ถ้าบิท PCINT[23:16] ใดถูกเคลียร์ pin change interrupt บนขา corresponding I/O pin ก็จะถูกปิดการใช้งาน

17.2.7. Pin Change Mask Register 1

(https://i.imgur.com/TVagg6z.png)

Bits 0, 1, 2, 3, 4, 5, 6 – PCINT8, PCINT9, PCINT10, PCINT11, PCINT12, PCINT13, PCINT14: Pin Change Enable Mask
แต่ละบิท PCINT[15:8]-bit เลือกได้ว่า pin change interrupt ใดถูก enable บนขา the corresponding I/O pin. ถ้าบิท PCINT[15:8] ใดถูกเซทและบิท PCIE1 ใน PCICR ถูกเซท, pin change interrupt ก็จะถูก enable บนขา corresponding I/O pin. ถ้าบิท PCINT[15:8] ใดถูกเคลียร์ pin change interrupt บนขา corresponding I/O pin ก็จะถูกปิดการใช้งาน

17.2.8. Pin Change Mask Register 0

(https://i.imgur.com/f2kMOCB.png)

Bits 7:0 – PCINTn: Pin Change Enable Mask [n = 7:0]
แต่ละบิท PCINT[7:0]-bit เลือกได้ว่า pin change interrupt ใดถูก enable บนขา the corresponding I/O pin. ถ้าบิท PCINT[7:0] ใดถูกเซทและบิท PCIE0 ใน PCICR ถูกเซท, pin change interrupt ก็จะถูก enable บนขา corresponding I/O pin. ถ้าบิท PCINT[7:0] ใดถูกเคลียร์ pin change interrupt บนขา corresponding I/O pin ก็จะถูกปิดการใช้งาน

ปล. เดี๋ยวจะทำตัวอย่างดูนะ เปลี่ยนลอจิกทั้งขึ้นทั้งลงเลยใช่ไหม จะใช้สวิทช์ปุ่มกดไม่ได้แล้ว ต้องใช้สวิทช์ปิดเปิดแทน
วันนี้ครึ้มฟ้าครึ้มฝนนะ ช่วงบ่ายเลยได้ ถ้าวันไหนแดดออก ไม่ได้เลยนะ สู้ไม่ไหวหรอก ร้อน ทำอะไรไม่ได้เลย
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 14, 2019, 01:54:46 PM
http://www.mediafire.com/file/f0o8928aysf7hmf/PCINT.rar/file (http://www.mediafire.com/file/f0o8928aysf7hmf/PCINT.rar/file)

อันนี้ต้องไม่ optimize code นะ (optimization = -O0) เพราะเดี๋ยวจะไม่เห็น flag a

ก็เอาสวิทช์ปิดเปิดมาต่อคร่อมสวิทช์ปุ่มกดเลย(เฉพาะบอร์ดผมนะ) คราวนี้ปิดก็ interrupt เปิดก็ interrupt (interrupt ทั้งขึ้นทั้งลง)ได้ทั้งสองสวิทช์เลย แต่ interrupt เดียวกัน อย่างนี้ก็จะใช้ทั้ง ๘ สวิทช์ก็ได้นะ ใน interrupt เดียวกัน

(https://i.imgur.com/DDc90Z9.jpg)

ปล. จะเอาตัวอย่างอีกไหม sleep mode ก็คงจะเหมือนกัน
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 14, 2019, 02:31:28 PM
http://www.mediafire.com/file/k6zisr0vtvwdmdv/PCINT_1.rar/file (http://www.mediafire.com/file/k6zisr0vtvwdmdv/PCINT_1.rar/file)

อันนี้ pin change interrupt ใช้ปลุก (wake-up) จาก sleep mode ของทุกๆโหมด ก็ได้เหมือนกัน
อะไรเป็นอะไร ก็ลองไล่ดูในไฟล์ iom328p.h ดูเอานะ อยู่ตรงไหนก็ดูได้ในโปรแกรม คอมเม้นต์บอกที่อยู่เอาไว้ให้แล้วครับ

ปล. เคยยกลูกเหล็กได้เป็นพันชั่ง(stm32 32บิท)มาแล้ว ทำใมจะยกปุยนุ่น(ATmega328p)ไม่ได้หล่ะ  ;D
ทำเก่งไป เดี๋ยวเจอวันที่แดดออก มีสิทธิ์เดี้ยง ต่อให้เก่งแค่ไหนอีก  :'(
ย่อมาซะวันเดียวเสร็จเลย ตามกันทันมั๊ยหล่ะท่าน แล้วพรุ่งนี้จะทำอะไรดีหล่ะ อ่าน IO-Port ก่อนนะ เดี๋ยวจะเริ่มใหม่หมดเลยนะเรื่อง IO Port ลืมไปแล้วเหมือนกัน
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 15, 2019, 10:06:51 AM
http://www.mediafire.com/file/940561uujf4wava/PCINT_2.rar/file (http://www.mediafire.com/file/940561uujf4wava/PCINT_2.rar/file)

ลอง PCIE1: Pin Change Interrupt Enable 1 ดูบ้าง ใช้สวิทช์ 2 ตัวต่อเข้า PC0(PCINT8), PC1(PCINT9) เปิดปิดหลอด LED (PD6) ตัวเดียวกัน ของผมบางทีก็เปิดได้ปิดได้ บางทีก็เปิดไม่ได้ปิดไม่ได้ ไม่แน่นอนเอาเสียเลย คิดว่าน่าจะเป็นที่สวิทช์ปิดเปิด พวกคุณลองดูที ว่าเป็นที่อะไร
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 16, 2019, 09:33:25 AM
เปลี่ยนมาใช้แบบนี้ ก็มีความแน่นอนขึ้น แต่ก็ไม่ร้อยเปอร์เซ็น น่าจะมาจากสวิทช์มีการบร๊าวท์(เรียกไม่ถูกแล้วลืม) แล้วให้มัน toggle อย่างในโปรแกรม PCINT2 นั้นคงจะไม่สมบรูณ์

(https://i.imgur.com/bDHUzp9.jpg)

แต่ถ้าเราแยกโปรแกรมปิดก็อยู่ส่วน เปิดก็อยู่ส่วน อย่างนี้ก็จะแน่นอนครับ

http://www.mediafire.com/file/t7gxpqbjdir5irx/PCINT_3.rar/file (http://www.mediafire.com/file/t7gxpqbjdir5irx/PCINT_3.rar/file)

ปล. จะให้ยกตัวอย่างอีกไหม เดี๋ยวจะอ่าน IO-Port อีกสักสองสามวัน คงจะได้ขึ้นนะ
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 16, 2019, 03:14:34 PM
ว่างๆก็มาทำสรุปรวมทั้ง 5 interrupt เลยนะ มีอะไรบ้าง INT0, INT1, PCINT0, PCINT1, PCINT2
INT0, INT1 ก็ใช้สวิทช์ปุ่มกดเอา ให้อินเตอร์รัพท์ที่ขอบขาลง(falling edge)
ส่วน PCINT0, PCINT1, PCINT2 ก็ใช้สวิทช์ปิด-เปิด ถ้าใครมีสวิทช์มากๆก็เพิ่มสวิทช์เอาได้ คงจะเข้าใจการเขียนโปรแกรมแล้วนะ อธิบายมากเดี๋ยวจะสับสน

http://www.mediafire.com/file/m34f7nmfki0kd32/Interrupt.rar/file (http://www.mediafire.com/file/m34f7nmfki0kd32/Interrupt.rar/file)

(https://i.imgur.com/wkF6VaG.jpg)

Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 21, 2019, 08:17:28 AM
มีพรายกระซิบบอก การทำ pin change interrupt PCINT ด้วยสวิทช์ สวิทช์มันมีบร๊าวน์(คือจะเป็น "0" เป็น "1" หลายครั้ง ตอนปิดเปิด) ก็เลยเอา ATmega328p อีกบอร์ด มาทำ output ให้เป็น ON-OFF และมีการดีเลย์ คราวนี้ไม่เกิดบร๊าวน์แน่ เลยมาลอง ก็สามารถทำงานได้ครับ

นี่มีตัวอย่างโปรแกรม:
http://www.mediafire.com/file/f2p15qsoitj4iht/Test_PCINT_Board1.rar/file (http://www.mediafire.com/file/f2p15qsoitj4iht/Test_PCINT_Board1.rar/file)

http://www.mediafire.com/file/19pvvi4icot7dat/Test_PCINT_Board2.rar/file (http://www.mediafire.com/file/19pvvi4icot7dat/Test_PCINT_Board2.rar/file)

(https://i.imgur.com/ZZ432yr.jpg)

ได้แบตสำรองมือถือมาจากที่ไปเที่ยวตัวเมืองกำแพงเพชรมา ก็เลยมาทำเป็น power supply 5V (เอามิเตอร์วัดได้ 5.09V) ให้กับบอร์ดเลย ตัวนี้ขนาด 20000mAh แต่เป็นของเก่า

(https://i.imgur.com/nrLUFSN.png)

ตอนนี้ fuse bits ก็ตั้งประมาณนี้ ลองไล่บิทเอาดูนะ ผมก็ลืมแล้ว ได้หน้าลืมหลังไปเรื่อย สมองคนเราก็ประมาณนี้แหละ  ;D
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 21, 2019, 09:56:21 AM
คราวนี้เอาบอร์ดที่ 1 มาทำเป็น 6 output เลย(เป็นสวิทช์ 6 ตัวเลย) แล้วมาเข้า pin change interrupt ทั้ง 3 interrupt เลย คือเอา 2 output ของบอร์ดที่ 1 มาเข้าต่อ 1 interrupt ของบอร์ดที่ 2 (จะโมลองทำให้หลาย output มากกว่านี้ก็ได้ ดูที่ขา ATmega328p ว่าได้
PCINT interrupt ละกี่ขา) ก็ไม่ยากแล้วใช่ไหม

ก็ต่อขาดังนี้
                        บอร์ดที่ 1                                      บอร์ดที่ 2
          ขา             PB0                 ต่อกับ                 PCINT0(PB0)          PCINT0 Interrupt
          ขา             PB1                 ต่อกับ                 PCINT1(PB1)                    "
          ขา             PB2                 ต่อกับ                 PCINT8(PC0)          PCINT1 Interrupt
          ขา             PB3                 ต่อกับ                 PCINT9(PC1)                    "
          ขา             PB4                 ต่อกับ                 PCINT19(PD3)        PCINT2 Interrupt
          ขา             PB1                 ต่อกับ                 PCINT20(PD4)                  "

อย่างนี้หลอด LED จะกระพริบหลอดละ 2 ครั้งใช่ไหม เพราะมี 2 output ต่อ 1 interrupt

มีโปรแกรมตัวอย่าง
บอร์ดที่ 1 http://www.mediafire.com/file/sriyd6zquk8ttkg/Test_PCINT_Board1_1.rar/file (http://www.mediafire.com/file/sriyd6zquk8ttkg/Test_PCINT_Board1_1.rar/file)
บอร์ดที่ 2 http://www.mediafire.com/file/1tf7z4je0e41bix/Test_PCINT_Board2_1.rar/file (http://www.mediafire.com/file/1tf7z4je0e41bix/Test_PCINT_Board2_1.rar/file)

มีแท๊บเล็ตแล้วก็ถ่ายรูปให้ดูด้วย

(https://i.imgur.com/RXMLUvy.jpg)

เดี๋ยวลองแช่ทิ้งไว้นานๆ จะดูว่าแบตสำรองนี้ จ่ายไฟได้นานเท่าไร
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 21, 2019, 01:57:41 PM
คราวนี้มาลองทำเป็นไฟวิ่งดู ใช้ pin change interrupt 0 ตัวเดียว แต่เซท pin change mask register 0 ไว้ 4 บิท 
// Pin Change Enable Mask select PCINT0(PB0), PCINT1(PB1), PCINT2(PB2), PCINT3(PB3)
ก็เสียบสาย PB0-3 ของทั้งสองบอร์ดถึงกัน เสียบสาย PD0-7 ของบอร์ดที่ 2 เข้าหลอด LED คราวนี้ไฟก็จะวิ่งจาก LED0-LED7

นี่ตัวอย่างโปรแกรม
บอร์ดที่ 1 http://www.mediafire.com/file/qmnzsaap7vgr0da/Test_PCINT_Board1_2.rar/file (http://www.mediafire.com/file/qmnzsaap7vgr0da/Test_PCINT_Board1_2.rar/file)
บอร์ดที่ 2 http://www.mediafire.com/file/33ob2h53baidvn5/Test_PCINT_Board2_2.rar/file (http://www.mediafire.com/file/33ob2h53baidvn5/Test_PCINT_Board2_2.rar/file)

(https://i.imgur.com/FGTYHL9.jpg)

เข้าใจกันมั๊ยหล่ะ ลองไล่เช็คดูใน register ที่แปลมา กับเช็คขา ATmega328p ว่าขาไหนเป็นขาไหนนะ

ปล. ผมจบ ปวส.ไฟฟ้ามาก็เป็นแต่ตีกิ๊บนะ มาสู้ชีวิตที่กรุงเทพ ก็มาตีกิ๊บตามบ้านจัดสรรนะ คราวนี้มาสอบเข้าโรงปูนตรานก สอบข้อเขียนก็ไม่ได้สอบสัมภาษณ์ก็ไม่ได้ พอดีเขาจะเอาคนมากันพวกรุ่นพี่ในโรงปูนประท้วง เขาเลยรับมาเป็นพนักงานชั่วคราว ไอ้เราก็ไม่รู้ว่าเขาจะปลดเมื่อไหร่ พอเข้าโรงปูนมาแล้ว ก็เลยรีบเร่งศึกษาหาความรู้ ถูๆไถๆมาเรื่อย จบปวส.มาถึงห้าปีถึงไปสอบปริญญาตรีได้ ปริญญาตรีก็เรียนกันแต่ทฤษฎี ลืมไปหมดแล้ว ดีอยู่อย่างเดียวคือมันทำให้เราติดการอ่านหนังสือมากๆเท่านั้นเอง
เข้าใจอยู่นะว่าบางคนอาจไม่เข้าใจ ก็ถามกันได้ครับ
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 21, 2019, 02:19:27 PM
ประกาศตัวแปร b ไว้ ถ้า a เท่ากับ b อยู่ ก็จะติดอยู่กับลูป while นี้อยู่ พออินเตอร์รัพย์ a เพิ่มค่าถึงจะหลุดมาจากลูป while นี้ไป

Quote
   while(a==b);

คราวนี้ a เพิ่มค่าแล้ว เราก็มาให้ b = a อีก ก็วนไปติดที่ลูป while ก่อน รอการอินเตอร์รัพต่อไปอีก ไม่ให้มันวนทำงานซ้ำๆตลอดเวลาโดยไม่จำเป็น
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 21, 2019, 02:49:14 PM
ลองอัฟโหลดยูทูปตามคำเรียกร้องนะ เคยอัฟโหลดมาวีดีโอเดียวนานหลายปีแล้ว คราวนี้อัฟโหลดอีก พอจะเป็นแล้ว
มาดูกัน pin change interrupt PCINT0 มาทำเป็นไฟวิ่งคัรบ

https://www.youtube.com/v/U7J5K175SMQ
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 21, 2019, 03:04:40 PM
น่าเสียดายที่มันอินเตอร์รัพท์ทั้งขึ้นทั้งลงเลย แล้วสวิทช์มันมีบร๊าวน์(เป็น "0" เป็น "1" หลายครั้งตอนปิดเปิดสวิทช์) มันจะเซ้นส์ไวมากด้วย อย่างเราใช้ clock 16Mhz คำสั่งหนึ่งก็ไซเคิลเดียว ก็ใช้เวลาเพียง 1/16Mhz = 1/16 us เอง

มีวิธีอื่นไหมที่ไม่ต้องใช้บอร์ดมาทำเป็นสัญญาน ON-OFF อย่างนี้ แล้วไม่เกิดบร๊าวด้วย

ถ้าสวิทช์ไม่มีบร๊าวน์ เราก็สามารถใช้สวิทช์ได้ถึงมากสุด 8 ตัว on-off หลอดไฟดวงเดียวได้เลย
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 24, 2019, 07:29:55 AM
พรายกระซิบบอก ให้ลองทำ ON ไปก่อนทั้ง 4 สวิทช์ แล้วค่อย OFF ทั้ง 4 สวิทช์ ก็จะได้ผลเหมือนกัน เมื่อสวิทช์ใดเปลี่ยนก็จะเกิด interrupt เหมือนกันหมด

มีตัวอย่างของบอร์ดที่ 1 ส่วนบอร์ดที่ 2 ยังคงเดิม
http://www.mediafire.com/file/rdhtq7vuapw8hld/Test_PCINT_Board1_2%25282%2529.rar/file (http://www.mediafire.com/file/rdhtq7vuapw8hld/Test_PCINT_Board1_2%25282%2529.rar/file)

ส่วนฟังชั่น delay ms เราก็มาเขียนแบบนี้ ให้เป็นฟังชั่นย่อย ถ้าเขียนแบบเดิม code size จะใหญ่มาก เพราะโปรแกรมเราไม่ได้บีบอัดแล้ว optimization = -O0 (ดูใน configuration options) เขียนเป็นฟังชั่นย่อยอย่างนี้ก็จะลด code size ลง
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 24, 2019, 08:17:37 AM
พรายกระซิบบอกมาอีกแล้ว ให้ไปดูที่ ไฟล์ delay.h ใน C:\avr8-gnu-toolchain\avr\include\util ดูแล้วปรากฎว่า ฟังชั่น _delay_ms(); ประกาศตัวแปรเป็น double เลย เท่าไหร่นะ 32 บิทเลยใช่ไหม ส่วนโปรแกรมย่อยของผม ประกาศตัวแปรแค่ unsigned int 16 บิท ซึ่งน้อยกว่า แต่ว่าไม่เกินนี่ก็น่าจะใช้ได้นะใช่ไหม

Quote
void
_delay_ms(double __ms)
{
   double __tmp ;
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
  !defined(__DELAY_BACKWARD_COMPATIBLE__) &&      \
  __STDC_HOSTED__
   uint32_t __ticks_dc;
   extern void __builtin_avr_delay_cycles(unsigned long);
   __tmp = ((F_CPU) / 1e3) * __ms;

   #if defined(__DELAY_ROUND_DOWN__)
      __ticks_dc = (uint32_t)fabs(__tmp);

   #elif defined(__DELAY_ROUND_CLOSEST__)
      __ticks_dc = (uint32_t)(fabs(__tmp)+0.5);

   #else
      //round up by default
      __ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
   #endif

   __builtin_avr_delay_cycles(__ticks_dc);

#else
   uint16_t __ticks;
   __tmp = ((F_CPU) / 4e3) * __ms;
   if (__tmp < 1.0)
      __ticks = 1;
   else if (__tmp > 65535)
   {
      //   __ticks = requested delay in 1/10 ms
      __ticks = (uint16_t) (__ms * 10.0);
      while(__ticks)
      {
         // wait 1/10 ms
         _delay_loop_2(((F_CPU) / 4e3) / 10);
         __ticks --;
      }
      return;
   }
   else
      __ticks = (uint16_t)__tmp;
   _delay_loop_2(__ticks);
#endif
}

ของ winavr ก็จะเหมือนกัน ที่เรา include file มาที่หัวโปรแกรม ไฟล์ก็จะอยู่แถวนี้ ในโปรแกรมของผม ผมก็จะบอกไว้นะว่าไฟล์เหล่านี้อยู่ที่ไหน ลองไล่เช็คทำความเข้าใจดูนะ ดูบ่อยๆสักวันคงจะเข้าใจ ก็จะเก่งการเขียนโปรแกรมครับ
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 24, 2019, 08:27:27 AM
พรายกระซิบบอกมาให้ประกาศตัวแปรให้เป็น double เหมือนกันไว้ พอ build ปรากฎว่า code size ลดจาก 1646 bytes เหลือ 1582 bytes
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 24, 2019, 09:41:26 AM
ถ้าเราไม่ optimize code (ตั้ง project->configuration options->optimization = -O0) เวลา build ก็จะขึ้น warning เหลืองเตือนว่า  # warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed"
ผมเลยเช็คโดยการตั้งให้เวลาเยอะๆ อย่าง 5000ms แล้วใช้แท๊บเล็ตจับเวลาดู เวลาหลอด LED ติดก็ใกล้เคียงกับ 5 วินะ คงจะใช้ได้ใช่ไหม ลองเช็ตดูกัน

แต่พอเราบีบอัด optimize code (ตั้ง project->configuration options->optimization = -Os) เวลา build ก็จะขึ้น error เลย build ไม่ผ่านที่โปรแกรมย่อย delay_ms อย่างนี้หมายถึงว่า ถ้าเรา optimization = -Os เราก็ใช้ฟังชั่น   _delay_ms(500); ในส่วนต่างๆของโปรแกรมได้เลย เวลา build มันก็จะ potimize code ให้เราเอง

Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 24, 2019, 10:31:24 AM
แต่ต่อไปโปรแกรมเราจะตั้งไม่ให้ optimize (ไม่ตั้ง optimization = -Os) นะ จะตั้ง optimization = -O0 นะ ถ้าตั้งบีบอัด flag ที่เราตั้งจะถูกบีบอัดเช็ค flag ไม่ได้เลย (มั่วเหมือนกัน GCC) ตกลงตามนี้นะ เจอปัญหาก็แก้ไปเรื่อยๆครับ
Title: Re: Atmega328P Datasheet 17. External Interrupt
Post by: tha on August 28, 2019, 01:49:59 PM
ตัวอย่างที่ให้ไปมันผิดอยู่นะ ให้ประกาศตัวแปร global variable ประกาศเป็น volatile ขึ้นหน้านะครับ
อย่างเช่นโปรแกรม Test_PCINT_Board2_2 ก็ประกาศอย่างนี้
Quote
volatile uint8_t a = 0;
volatile uint8_t b = 0;
เพื่อให้มันไม่ optimize ตัวแปร a, b เวลาตอนเราบีบอัด code นะ
   คราวนี้เราก็มาตั้งให้ optimize (บีบอัดโค๊ด) อย่างนี้ได้ (project->configuration options->optimization = -Os) ขนาดของ code size ก็จะลดลงมาเยอะเลย

ส่วนฟังชั่นการดีเลย์ก็ให้กลับมาใช้ฟังชั่น _delay_ms(100); ได้ตามปกติครับ

ส่วนตัว compiler ก็กลับมาใช้ winavr ก็ได้ครับ

ปล. ไม่ได้ทำมานานชักจะลืมเลยผิดพลาด ต้องขออภัยด้วย
      ขอโฆษณาหน่อย ก็เคยบวชเรียนมา ก็ว่านั่งสมาธิ พุท-โธๆ นี้ดี ทำให้ลมหายใจนี้ยาวลึกละเอียด เป็นผลดีต่อสุขภาพไม่ค่อยเป็นหวัดเป็นไอ
      อ่านหนังสือก็มีสมาธิดี เพราะนิวรณ์มันลดลง เราก็จะมีสุขมากขึ้น สุขที่ใจสงบ ชีวิตเราก็จะดีขึ้น ก็ทำง่ายๆเราหัดทำเองก็ได้ วันละนิดวันละ
      หน่อย เดี๋ยวเราก็จะรู้เองว่าควรทำอย่างไร มันก็จะดีขึ้นเรื่อยๆเองครับ
       http://www.84000.org/tipitaka/dic/d_item.php?i=225 (http://www.84000.org/tipitaka/dic/d_item.php?i=225)