STM32F1 ADC HAL

Started by tha, September 17, 2020, 09:42:20 AM

Previous topic - Next topic

tha

พอดีไปเจอขุมทรัพย์อยู่ตรงนี้  https://github.com/yohanes-erwin/stm32f103-sw4stm32

เดี๋ยวจะแปล ADC ตามใน reference manaul ไปเลย ก็ดูภาษาอังกฤษเปรียบเทียบไปเลย ลืมไปแล้วเหมือนกัน ก็ต้องเริ่มต้นกันใหม่

11.1 ADC introduction
The 12-bit ADC เป็น successive approximation analog-to-digital converter. มันจะมีถึง 18 multiplexed(เชิงซ้อน) channels ทำให้มันวัดสัญญานจากภายนอกได้ 16 แหล่งและภายใน 2 แหล่ง. การแปลงสัญญาน A/D ของ channels ต่างๆสามารถทำได้ใน single, continuous, scan หรือ discontinuous mode. ผลของการแปลง ADC จะถูกเก็บในแนว left-aligned(ชิดซ้าย) หรือ right-aligned(ชิดขวา)ของ 16-bit data register.

The analog watchdog feature ทำให้ใช้งานเกี่ยวกับการตรวจจับ ถ้า input voltage ออกนอกกรอบขอบเขต high หรือ low ที่ผู้ใช้กำหนด

The ADC input clock ถูสร้างขึ้นจาก the PCLK2 clock ถูกหารโดย prescaler และมันต้องไม่เกิน 14 MHz, อ้างอิงถึงรูป Figure 8 สำหรับ low-, medium-, high- and XL-density devices, และรูป Figure 11 สำหรับ connectivity line devices.

tha

11.2 ADC main features
•  ความละเอียด 12-bit
• อินเตอรัพท์ถูกสร้างขึ้นที่การจบการแปลง(Conversion), การจบของการแปลงแบบอินเจ็คท์(Injected conversion) และเกิด Analog
watchdog event
• โหมดการแปลงครั้งเดียวและโหมดการแปลงต่อเนื่องกัน
• Scan mode สำหรับการแปลงแบบอัตโนมัติของ channel 0 to channel 'n'
• Self-calibration(การปรับแต่งด้วยตัวมันเอง)
• Data alignment(การจัดวางแนวข้อมูล) ด้วย in-built data coherency(ติดต่อกัน)
• Channel ต่อ channel programmable sampling time
• External trigger option(ตัวเลือก) สำหรับทั้ง regular และ injected conversion
• Discontinuous mode
• Dual mode (บน mcu ด้วย 2 ADCs หรือมากกว่า)
• ADC conversion time:
   – STM32F103xx performance line devices: 1 μs at 56 MHz (1.17 μs at 72 MHz)
   – STM32F101xx access line devices: 1 μs at 28 MHz (1.55 μs at 36 MHz)
   – STM32F102xx USB access line devices: 1.2 μs at 48 MHz
   – STM32F105xx and STM32F107xx devices: 1 μs at 56 MHz (1.17 μs at 72 MHz)
• ADC supply requirement:(แหล่งจ่ายไฟที่ต้องการ) 2.4 V to 3.6 V
• ADC input range: VREF- ≤ VIN ≤ VREF+
• DMA request generation ในระหว่าง regular channel conversion
The block diagram ของ the ADC ถูกแสดงในรูป Figure 22.
บันทึก: VREF-,ถ้ามีให้ใช้ (ขึ้นอยู่กับ package), ต้องถูกต่อถึง VSSA.

tha

11.3 ADC functional description (การอธิบายถึงฟังชั่นของ ADC)
รูปที่ 22 แสดง single ADC block diagram และตารางที่ 65 ให้คำอธิบายถึง ADC pin .



1. ADC3 มี regular และ injected conversion triggers แตกต่างไปจากของ ADC1 และ ADC2.
2. TIM8_CH4 และ TIM8_TRGO ด้วย corresponding remap bits ของมันมีอยู่เพียงใน High-density และ XL-density products.

ปล. วันนี้บ่ายมาแดดมันร่ม มันเลยไม่ร้อน ปกติบ่ายมาร้อน จะอ่านอะไรไม่ได้เลย สาเหตุที่ไทยไม่เจริญทางด้านวัตถุเทคโนโลยี ใครมาเป็นนายกก็เข็ญไม่ขึ้น ไม่เหมือนจีนๆเขาหนาวเย็น เลยเจริญเอาๆจะแซงอเมริกาแล้ว มันไม่เกี่ยวกับประชาธิปไตย ไม่ประชาธิปไตยหรอกใช่ไหมครับ


tha



1. VDDA และ VSSA จะถูกต่อเข้ากับ VDD และ VSS, ตามลำดับ
2. สำหรับรายละเอียดเกี่ยวกับ ADC I/O pins, ถูกกล่าวถึงใน the "Pinouts and pin descriptions" section ของ the corresponding device datasheet.

tha

11.3.1 ADC on-off control
The ADC สามารถถูก powered-on โดยการเซ็ตบิต ADON bit ใน the ADC_CR2 register. เมื่อบิต ADON bit ถูกเซ็ตในครั้งแรก, มันจะ wakes up the ADC จาก Power Down mode. การแปลงจะเริ่มเมื่อบิต ADON bit ถูกเซ็ตเป็นครั้งที่สองโดย software หลังจาก ADC power-up time (tSTAB).
การแปลงสามารถถูกหยุด, และ ADC ถูกทำให้อยู่ใน power down mode โดยการรีเซ็ตบิต(ทำให้เป็น '0') ADON bit. ในโหมดนี้ ADC เกือบ
จะไม่กินพลังงาน (กินเพียงหน่วยเป็น μA เล็กน้อยเท่านั้น).

tha

11.3.2 ADC clock
The ADCCLK clock ถูกจัดให้มีโดย the Clock Controller คือจะ synchronous ด้วย the PCLK2 (APB2clock). The RCC controller มี a dedicated programmable prescaler สำหรับ the ADC clock,
อ้างอิงถึง Low-, medium-, high- and XL-density reset and clock control (RCC) สำหรับรายละเอียดที่มากขึ้น.

tha

ดูที่บิต Bit 0 ADON: A/D converter ON / OFF ในรีจีสเตอร์ ADC control register 2 (ADC_CR2) ใน reference manaul นะ
ให้บิต Bit 0 ADON ค้างเป็น '1' power on ก่อน แล้วเขียนเป็น '1' ไปอีกทีเพื่อสตาร์ทการแปลงอีกทีครับ



ในฟังชั่นย่อย void ADC_setup(void) เราให้ บิต 0 ADON เป็น '1' ไปก่อน ADC_Cmd(ADC1, ENABLE);  // Enable ADC1
Quote
void ADC_setup(void)
{
   ADC_InitTypeDef ADC_InitStructure;
   // Enable ADC1 clock
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);
   // ADC1 configuration
   ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
   ADC_InitStructure.ADC_ScanConvMode = DISABLE;
   ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
   ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
   ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
   ADC_InitStructure.ADC_NbrOfChannel = 1;
   ADC_Init(ADC1, &ADC_InitStructure);
   // ADC1 regular channel14 configuration
   //ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 1, ADC_SampleTime_13Cycles5);
   ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_13Cycles5);
   ADC_Cmd(ADC1, ENABLE);  // Enable ADC1

   ADC_ResetCalibration(ADC1);   // Enable ADC1 reset calibaration register
   while(ADC_GetResetCalibrationStatus(ADC1));

   ADC_StartCalibration(ADC1);   // Start ADC1 calibaration
   while(ADC_GetCalibrationStatus(ADC1)); // Check the end of ADC1 calibration
}


พอในลูป while(1) เราก็คอยเขียนบิต 0 ADON เป็น '1' ซ้ำ ADC_Cmd(ADC1, ENABLE);  // Enable ADC1 พอแปลงเสร็จแต่ละครั้งก็เขียนเป็น '1' ซ้ำไปเรื่อย ADC ก็จะทำการแปลงตลอดเวลา
Quote
int main(void)
{
   unsigned long adc_val=0,percentage; // Keep analog value
   char str[14];  // Keep string convert
   GPIO_setup();  // GPIO Configuration
   ADC_setup();   // ADC Configuration
   lcdString(1,1,"ADC Demo...");   // Set message on line 1
   lcdUpdate();     // Display message
   while(1)    // Infinite loop
   {
      ADC_Cmd(ADC1,ENABLE);   // Enable ADC1
      while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==RESET);   // Wait EOC flag set
      adc_val = ADC_GetConversionValue(ADC1);   // Get analog value from ADC channel 14(PC4)
      percentage = (adc_val*100)/4095; // Convert analog to percentage(0-100% reference from 0-4095)
      sprintf(str,"AIN0: %d    ",adc_val);  // Convert analog value to string
      lcdString(1,3,str);     // Set message on line 3
      lcdProgBar(0,26,83,5,percentage);   // Display progress bar at(0,26),width 83 pixel,high 5 pixel
      sprintf(str,"%d%%   ",percentage);  // Convert percentage value to string
      lcdString(6,5,str);     // Set message on line 5(position(6,5))
      lcdUpdate();      // Display message
      delay_ms(50);     // Delay a few time
   }

}

tha

ได้แล้วนะครับ เอามาใช้กับโปรแกรม Keil ก่อน เพราะ library ยังเป็นตัวเก่าอยู่ ไม่ใช่ HAL



ปล. ร้อนนะเครียด ผมไม่ได้อยู่ห้องแอร์นะครับ