การใช้งานของ ADC ใน CH32V003 นั้นมีการทำงานหลายแบบมาก บทความนี้จะมาสรุปเกี่ยวกับ วิธีการใช้งาน ADC และ ประเภทของ ADC สำหรับการใช้งาน เรามาดูภาพรวม และ แนวทางการใช้งานกันเลย
1. โหมดการทำงานของ ADC ใน CH32V003
CH32V003 มี ADC แบบ 10-bit ความละเอียด รองรับการทำงานได้ 3 แบบหลัก ๆ:
โหมด | การทำงาน | การใช้งาน |
---|---|---|
Single Conversion Mode | แปลงสัญญาณแค่ครั้งเดียว เมื่อถูกสั่ง (Software Trigger) หรือ Hardware Trigger | อ่านค่า ADC ทีละตัว |
Continuous Conversion Mode | ทำการแปลง ADC ต่อเนื่องไม่หยุดจนกว่าจะสั่งหยุด | ใช้วัดค่า real-time ต่อเนื่อง เช่น เซ็นเซอร์อุณหภูมิ |
Scan Mode (Multiple Channel) | อ่านหลายช่องสัญญาณตามลำดับอัตโนมัติ | วัดหลาย input เช่น sensor หลายตัว |
หมายเหตุ:
- ช่อง ADC Input (Analog Inputs) มีทั้งหมด 8 ช่อง คือ AIN0-AIN7
- รองรับทั้ง Trigger ภายนอก (จาก Timer เป็นต้น) และ Trigger ภายใน (Software)
2. ขั้นตอนการทำงานของ ADC ใน MCU
ลำดับการทำงานของ ADC โดยทั่วไป เป็นดังนี้:
- เปิด Clock ของ ADC
เปิดใช้งาน Clock ผ่าน RCC ก่อน (RCC_APB2PeriphClockCmd
) - Configure ADC Parameters
ตั้งค่า ADC ด้วยโครงสร้างADC_InitTypeDef
- โหมด (Single, Continuous, Scan)
- Alignment (Right/Left)
- External Trigger
- จำนวน Channels ที่ต้องแปลง
- Configure ADC Channels
เลือก Channel ที่ต้องการอ่าน และกำหนดลำดับ - Enable ADC
เปิดการทำงาน ADC (ADC_Cmd(ADCx, ENABLE)
) - Calibration (เฉพาะบางกรณี)
รีเซ็ต และเริ่มการปรับเทียบค่าภายใน ADC - Start Conversion
สั่งเริ่มต้นการแปลง ADC (ADC_SoftwareStartConvCmd
) - Wait Until Conversion Complete
เช็คสถานะEOC
(End of Conversion) Flag - Read Data
อ่านค่าผลลัพธ์จาก Register (ADC_GetConversionValue
)
3. โค้ดตัวอย่างการเขียนโปรแกรมใช้งาน ADC
#include "ch32v00x_adc.h" #include "ch32v00x_rcc.h" void ADC1_Init(void) { ADC_InitTypeDef ADC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // เปิด clock ADC1 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // ทำงานแบบอิสระ ADC_InitStructure.ADC_ScanConvMode = DISABLE; // ไม่ scan หลาย channel ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // เปิดการทำงานต่อเนื่อง ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // ไม่มี trigger ภายนอก ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // ชิดขวา ADC_InitStructure.ADC_NbrOfChannel = 1; // ใช้แค่ 1 channel ADC_Init(ADC1, &ADC_InitStructure); // ตั้งค่า ADC1 ADC_Cmd(ADC1, ENABLE); // เปิดใช้งาน ADC1 ADC_ResetCalibration(ADC1); // รีเซ็ตการ calibrate while(ADC_GetResetCalibrationStatus(ADC1)); // รอ reset calibration เสร็จ ADC_StartCalibration(ADC1); // เริ่ม calibration while(ADC_GetCalibrationStatus(ADC1)); // รอ calibration เสร็จ ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // ตั้ง channel 0 เป็นตัววัด ADC_SoftwareStartConvCmd(ADC1, ENABLE); // เริ่มสั่งแปลง } uint16_t ADC1_Read(void) { while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // รอแปลงเสร็จ return ADC_GetConversionValue(ADC1); // อ่านค่า }
4. คำอธิบายฟังก์ชัน (Line-by-Line Explanation)
void ADC1_Init(void) { ADC_InitTypeDef ADC_InitStructure; // สร้างโครงสร้างเก็บค่าตั้งค่า ADC RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // เปิด clock ของ ADC1 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // เลือกโหมดอิสระ ADC_InitStructure.ADC_ScanConvMode = DISABLE; // ไม่ต้อง scan หลาย channel ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // เปิด continuous mode ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // ไม่มี external trigger ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; // ชิดขวา (ค่าที่อ่านได้เหมือนเป็น unsigned) ADC_InitStructure.ADC_NbrOfChannel = 1; // ใช้แค่ 1 channel ADC_Init(ADC1, &ADC_InitStructure); // ส่งข้อมูลเข้าไปยัง ADC1 ADC_Cmd(ADC1, ENABLE); // เปิดใช้งาน ADC1 ADC_ResetCalibration(ADC1); // รีเซ็ตการตั้งค่า calibration while(ADC_GetResetCalibrationStatus(ADC1)); // รอจนกว่าการรีเซ็ต calibration จะเสร็จสิ้น ADC_StartCalibration(ADC1); // เริ่มต้นกระบวนการ calibration ใหม่ while(ADC_GetCalibrationStatus(ADC1)); // รอ calibration เสร็จ ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5); // ตั้งให้ใช้ช่อง 0 ADC_SoftwareStartConvCmd(ADC1, ENABLE); // เริ่มแปลงข้อมูล ADC แบบ software trigger }
uint16_t ADC1_Read(void) { while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)); // รอ flag End of Conversion return ADC_GetConversionValue(ADC1); // อ่านค่า ADC }
5. ประเภทการอ่านค่า ADC
- Single Read: สั่งแปลงทุกครั้งที่ต้องการค่าใหม่
- Auto Continuous: เริ่มแค่ครั้งเดียว จากนั้นอ่านค่าใหม่ได้ตลอดเวลา
- Trigger-based: เริ่มแปลงเมื่อตรงกับสัญญาณ Trigger ภายนอก เช่น Timer Event
6. การใช้ DMA ร่วมกับ ADC
- CH32V003 รองรับ การใช้ DMA อ่านค่าจาก ADC อัตโนมัติ
- ไม่ต้องรอค่าสำเร็จจาก EOC flag
- ใช้
ADC_DMACmd(ADCx, ENABLE);
เพื่อเปิดโหมด DMA
สรุปสั้น ๆ แบบภาพรวม
หมวด | รายละเอียด |
---|---|
จำนวน Channel | 8 ช่อง (AIN0-AIN7) |
ความละเอียด | 10-bit |
แหล่ง Trigger | Software / Timer |
รองรับ DMA | มี |
ความเร็ว Sampling | ขึ้นอยู่กับ Clock (สูงสุด 24MHz สำหรับ ADC Clock) |
ฟังก์ชันสำคัญ | ADC_Init , ADC_Cmd , ADC_SoftwareStartConvCmd , ADC_GetConversionValue , ADC_DMACmd |