บทนำ
General Purpose Input/Output (GPIO) เป็นพินบนไมโครคอนโทรลเลอร์ CH32V003 ที่สามารถกำหนดค่าให้ทำงานเป็นอินพุตหรือเอาต์พุตดิจิทัล รวมถึงฟังก์ชันพิเศษอื่นๆ ได้ พอร์ต GPIO หลักๆ บน CH32V003 ได้แก่ Port A, Port C และ Port D
การใช้งาน GPIO จำเป็นต้องมีการกำหนดค่า (Configure) ให้กับพินที่ต้องการก่อน โดยใช้ไลบรารีมาตรฐาน (Standard Peripheral Library) หรือ HAL (Hardware Abstraction Layer) ที่ WCH จัดเตรียมให้
ขั้นตอนหลักในการกำหนดค่า GPIO
1. เปิดสัญญาณนาฬิกา (Enable Clock):
จำเป็นต้องเปิดสัญญาณนาฬิกาให้กับ GPIO Port ที่ต้องการใช้งานก่อนเสมอ ผ่าน RCC (Reset and Clock Control) มิฉะนั้น Port จะไม่ทำงาน
// ตัวอย่าง: เปิด Clock ให้ Port C และ Port D RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE); // สำหรับ Port A: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2. กำหนดค่าพิน (Configure Pin):
ใช้ Structure GPIO_InitTypeDef
เพื่อกำหนดโหมด, ความเร็ว (ถ้าจำเป็น), และพินที่ต้องการ จากนั้นเรียกฟังก์ชัน GPIO_Init()
GPIO_InitTypeDef GPIO_InitStruct = {0}; // ประกาศและเคลียร์ค่า Structure GPIO_InitStruct.GPIO_Pin = GPIO_Pin_x; // เลือกพิน เช่น GPIO_Pin_0, GPIO_Pin_1, ... // สามารถใช้ | รวมหลายพินได้ เช่น GPIO_Pin_0 | GPIO_Pin_1 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_xxx; // เลือกโหมดการทำงาน (ดูรายละเอียดด้านล่าง) GPIO_InitStruct.GPIO_Speed = GPIO_Speed_yyy; // เลือกความเร็ว (สำหรับ Output/AF) // เช่น GPIO_Speed_50MHz, GPIO_Speed_10MHz, GPIO_Speed_2MHz // เรียกใช้ฟังก์ชัน Init สำหรับ Port ที่ต้องการ (ตัวอย่างคือ Port C) GPIO_Init(GPIOC, &GPIO_InitStruct);
โหมด GPIO แต่ละแบบและการใช้งาน (GPIO_Mode_xxx
)
CH32V003 รองรับโหมดการทำงานของ GPIO ดังนี้:
1. GPIO_Mode_IN_FLOATING
(Input Floating – อินพุตแบบลอย)
- ลักษณะ: โหมดอินพุตพื้นฐาน ไม่ต่อ Pull-up/Pull-down ภายใน สถานะพินขึ้นกับสัญญาณภายนอก (หากไม่ต่ออะไร สถานะจะไม่แน่นอน).
- การกำหนดค่า:
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOC, &GPIO_InitStruct); // หรือ Port อื่น
- การใช้งาน: อ่านค่าดิจิทัล (0 หรือ 1) จากพิน.
uint8_t pin_state = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_x);
2. GPIO_Mode_IPU
(Input Pull-up – อินพุตแบบมีพูลอัป)
- ลักษณะ: โหมดอินพุตที่มีตัวต้านทาน Pull-up ภายในต่อกับ VCC หากไม่มีสัญญาณภายนอก จะอ่านได้ค่า High (1) เหมาะกับสวิตช์ที่ต่อลง Ground.
- การกำหนดค่า:
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOC, &GPIO_InitStruct);
- การใช้งาน: อ่านค่าดิจิทัล (ไม่กด = 1, กดลง GND = 0).
uint8_t pin_state = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_x);
3. GPIO_Mode_IPD
(Input Pull-down – อินพุตแบบมีพูลดาวน์)
- ลักษณะ: โหมดอินพุตที่มีตัวต้านทาน Pull-down ภายในต่อกับ GND หากไม่มีสัญญาณภายนอก จะอ่านได้ค่า Low (0) เหมาะกับสวิตช์ที่ต่อกับ VCC.
- การกำหนดค่า:
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(GPIOC, &GPIO_InitStruct);
- การใช้งาน: อ่านค่าดิจิทัล (ไม่กด = 0, กดต่อ VCC = 1).
uint8_t pin_state = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_x);
- หมายเหตุ: การเลือก Pull-up/Pull-down บางครั้งอาจต้องกำหนดผ่าน Register
OUTDR
เพิ่มเติมใน CH32V003 แต่ไลบรารีมักจัดการส่วนนี้ให้เมื่อเลือกโหมดIPU
หรือIPD
.
4. GPIO_Mode_AIN
(Analog Input – อินพุตอะนาล็อก)
- ลักษณะ: ใช้สำหรับรับสัญญาณแรงดันไฟฟ้าแบบต่อเนื่อง เพื่อป้อนเข้าสู่โมดูล ADC (Analog-to-Digital Converter) Digital Buffer ของพินจะถูกปิด.
- การกำหนดค่า:
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN; // ไม่ต้องกำหนด Speed สำหรับโหมดนี้ GPIO_Init(GPIOC, &GPIO_InitStruct);
- การใช้งาน: ต้องกำหนดค่าและอ่านค่าผ่านโมดูล ADC โดยตรง.
5. GPIO_Mode_Out_PP
(Output Push-Pull – เอาต์พุตแบบพุชพูล)
- ลักษณะ: โหมดเอาต์พุตมาตรฐาน ขับสัญญาณ High (VCC) และ Low (GND) ได้โดยตรง เหมาะสำหรับขับ LED, ส่งสัญญาณดิจิทัล.
- การกำหนดค่า:
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // เลือกความเร็วที่เหมาะสม GPIO_Init(GPIOC, &GPIO_InitStruct);
- การใช้งาน: เขียนค่าดิจิทัล (0 หรือ 1) ไปยังพิน.
GPIO_WriteBit(GPIOC, GPIO_Pin_x, Bit_SET); // ทำให้พินเป็น High (1) GPIO_WriteBit(GPIOC, GPIO_Pin_x, Bit_RESET); // ทำให้พินเป็น Low (0) // หรือใช้ฟังก์ชัน Set/Reset โดยตรง // GPIO_SetBits(GPIOC, GPIO_Pin_x); // High // GPIO_ResetBits(GPIOC, GPIO_Pin_x); // Low
6. GPIO_Mode_Out_OD
(Output Open-Drain – เอาต์พุตแบบโอเพนเดรน)
- ลักษณะ: โหมดเอาต์พุตที่ขับได้เฉพาะ Low (GND) เมื่อต้องการให้เป็น High จะปล่อยพินเป็นสถานะ High-Impedance (Hi-Z) ต้องใช้ตัวต้านทาน Pull-up ภายนอกต่อกับ VCC เหมาะสำหรับบัสแบบหลายอุปกรณ์ เช่น I2C.
- การกำหนดค่า:
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // เลือกความเร็ว GPIO_Init(GPIOC, &GPIO_InitStruct);
- การใช้งาน: เขียนค่าดิจิทัล (ต้องมี Pull-up ภายนอก).
GPIO_WriteBit(GPIOC, GPIO_Pin_x, Bit_RESET); // ขับ Low (GND) GPIO_WriteBit(GPIOC, GPIO_Pin_x, Bit_SET); // ปล่อย Hi-Z (จะเป็น High ถ้ามี Pull-up) // หรือใช้ // GPIO_ResetBits(GPIOC, GPIO_Pin_x); // ขับ Low // GPIO_SetBits(GPIOC, GPIO_Pin_x); // ปล่อย Hi-Z
7. GPIO_Mode_AF_PP
(Alternate Function Push-Pull – ฟังก์ชันทางเลือกแบบพุชพูล)
- ลักษณะ: มอบหมายการควบคุมพินให้กับ Peripheral ภายใน (เช่น UART TX, SPI MOSI/SCK, Timer PWM) โดย Peripheral นั้นจะขับสัญญาณแบบ Push-Pull.
- การกำหนดค่า:
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // เลือกความเร็ว GPIO_Init(GPIOC, &GPIO_InitStruct); // ต้องมีการกำหนดค่า Peripheral ที่เกี่ยวข้อง และอาจต้องตั้งค่า Pin Remapping เพิ่มเติม
- การใช้งาน: ควบคุมผ่าน Peripheral ที่กำหนด (เช่น สั่ง UART ให้ส่งข้อมูล).
8. GPIO_Mode_AF_OD
(Alternate Function Open-Drain – ฟังก์ชันทางเลือกแบบโอเพนเดรน)
- ลักษณะ: มอบหมายการควบคุมพินให้กับ Peripheral ภายใน (เช่น I2C SDA/SCL) โดย Peripheral นั้นจะขับสัญญาณแบบ Open-Drain (ต้องใช้ Pull-up ภายนอก).
- การกำหนดค่า:
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; // เลือกความเร็ว GPIO_Init(GPIOC, &GPIO_InitStruct); // ต้องมีการกำหนดค่า Peripheral (เช่น I2C) และอาจต้องตั้งค่า Pin Remapping
- การใช้งาน: ควบคุมผ่าน Peripheral ที่กำหนด (เช่น การทำงานของ I2C).
ข้อควรจำเพิ่มเติม
- การเลือกพิน (
GPIO_Pin_x
): ใช้ค่าคงที่ที่กำหนดไว้ เช่นGPIO_Pin_0
,GPIO_Pin_1
, … ตรวจสอบ Datasheet สำหรับพินสูงสุดของแต่ละพอร์ต. - ความเร็ว (
GPIO_Speed_yyy
): สำคัญสำหรับโหมด Output/AF มีผลต่อ Slew Rate และการใช้พลังงาน เลือกให้เหมาะสมกับความเร็วสัญญาณที่ต้องการ. - Alternate Function (AF) และ Remapping: การใช้ AF ต้องตรวจสอบจาก Datasheet ว่าพินใดรองรับฟังก์ชันใด และอาจต้องกำหนดค่า Pin Remapping ใน Register
AFIO_PCFR1
เพื่อให้ Peripheral เชื่อมต่อกับพินที่ถูกต้อง. - Datasheet/Reference Manual: คือเอกสารอ้างอิงที่สำคัญที่สุด ควรศึกษาประกอบเสมอเพื่อความถูกต้องและรายละเอียดเชิงลึก.