การใช้งาน EXTI (External Interrupt) ใน CH32V003

EXTI คือโมดูลที่ใช้ตรวจจับ การเปลี่ยนแปลงขา GPIO เช่น

  • กดปุ่ม → ส่งสัญญาณ Interrupt
  • เซ็นเซอร์สั่งสัญญาณ Digital → เรียก Interrupt

โดย EXTI สามารถจับได้ทั้ง

  • Rising Edge (ขาขึ้น)
  • Falling Edge (ขาลง)
  • หรือ ทั้งสองขอบ (Rising + Falling)

ขั้นตอนการใช้งาน EXTI ที่ถูกต้อง

1. Enable Clock Peripheral

เปิดนาฬิกา GPIO และ AFIO (Alternate Function IO)

2. ตั้งค่า GPIO เป็น Input

โดยไม่เปิด Pull-up หรือ Pull-down ถ้าไม่จำเป็น

3. ตั้งค่า AFIO สำหรับ Mapping GPIO Pin ไปยัง EXTI Line

EXTI0 ถึง EXTI7 สามารถเลือกขาได้ (PA, PC, PD)

4. ตั้งค่า EXTI Line

กำหนดว่าให้ Trigger ด้วย Rising, Falling หรือ Both Edge

5. Enable Interrupt ใน NVIC (PFIC ใน CH32V003)

ตั้ง Priority และเปิด Interrupt


ตัวอย่างโค้ด: ตั้งค่า EXTI ตรวจจับปุ่มกดบนขา PC0 (เมื่อกดลง)

#include "ch32v00x.h" // รวมไลบรารีทั้งหมดที่ต้องใช้

// ฟังก์ชันตั้งค่า EXTI
void EXTI0_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    EXTI_InitTypeDef EXTI_InitStructure = {0};

    // 1. เปิดนาฬิกา GPIOC และ AFIO
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);

    // 2. ตั้งค่า PC0 เป็นขาอินพุต
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; // เลือก Pin 0
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // อินพุตแบบไม่มี Pull-up/Pull-down
    GPIO_Init(GPIOC, &GPIO_InitStructure); // ประยุกต์ใช้กับพอร์ต C

    // 3. เชื่อมโยง PC0 เข้ากับ EXTI Line 0
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource0);

    // 4. ตั้งค่า EXTI Line
    EXTI_InitStructure.EXTI_Line = EXTI_Line0; // เลือก Line 0
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; // ทำงานแบบ Interrupt
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // ตรวจจับ Falling Edge (กดปุ่มลง)
    EXTI_InitStructure.EXTI_LineCmd = ENABLE; // เปิดใช้งาน
    EXTI_Init(&EXTI_InitStructure); // ลงทะเบียนค่า

    // 5. เปิด Interrupt ใน PFIC
    PFIC_EnableIRQ(EXTI0_IRQn); // เปิดใช้งาน IRQ ของ EXTI0
}

// ฟังก์ชันจัดการ Interrupt EXTI0
void EXTI0_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_Line0) != RESET) // ตรวจสอบว่ามี Interrupt มาจริงหรือไม่
    {
        // *** เขียนโค้ดที่ต้องการทำเมื่อปุ่มถูกกดลงที่นี่ เช่น กระพริบไฟ LED ***

        // เคลียร์สถานะ Interrupt เพื่อป้องกันซ้ำ
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

หมายเหตุเพิ่มเติม:

  • PFIC_EnableIRQ() คือฟังก์ชันใน SDK ใช้เปิด NVIC ของ QingKeV2
  • ฟังก์ชัน EXTI0_IRQHandler() ต้องตั้งชื่อตรงกับชื่อใน Startup.s (Vector Table)
  • ควรเช็ก Debounce ปุ่มด้วย (เช่นหน่วงเวลาเล็กน้อย) เพื่อป้องกันสัญญาณซ้ำ

Flow การทำงานสรุป

  1. ไฟฟ้าเปลี่ยนที่ขา PC0 →
  2. EXTI Line0 ตรวจจับขอบ Falling →
  3. ส่งสัญญาณไปยัง PFIC (Interrupt Controller) →
  4. กระโดดไปทำงานใน EXTI0_IRQHandler()
  5. ทำงานที่เขียนไว้ เช่น เปิด/ปิดไฟ LED →
  6. เคลียร์สถานะ EXTI Line เพื่อรับเหตุการณ์ใหม่