75
« on: March 05, 2016, 12:56:16 pm »
ผมสาย Standard Peripheral Lib (SPL) เลยไม่แน่ใจว่าจะช่วยอะไรได้มั้ย
ADC_RegularChannelConfig อันนี้เป็นคำสั่งที่ใช้บน SPL ครับ Cube จะไม่มีให้ใช้
พอดีตอนนี้ผมมีแค่บอร์ด Nucleo L053 อยู่กับตัว ผมเลยลองทำบน L053 ดู ผมลองโหลด Cube F0 มาดูแล้ว ผมแนะนำให้ดูตัวอย่าง STM32F072B-Discovery\Examples\ADC\ADC_DMA_Transfer ครับ ตัวอย่างนี้จะใช้ DMA อ่าน ADC มาเก็บไว้ในตัวแปร DMA จะอ่านมาตลอด แล้วเราก็ไปอ่านค่ามาจากตัวแปรอีกที ผมจะอ้างอิงจาก โปรเจ็คนี้ละกันครับ ผมจะบอกว่าผมแก้อะไรบ้าง
Init pin ADC อื่นๆ ใน stm32f0xx_hal_msp.c เพิ่มครับ ผม Init PA1 เพิ่ม
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
จากนั้นในไฟล์ main.c ผมก็เปลี่ยนตัวแปรที่ DMA ที่รับค่า ADC เป็น Array ตามจำนวน Channel ที่จะใช้ ในที่นี้ผมใช้ 2 Channel
uint32_t aResultDMA[2];
ลงมาตรง Initialize ADC peripheral ต้องแน่ใจว่าเปิดใช้งาน ScanMode ไว้ โดยหลักการแล้ว ADC มันก็ไม่ได้อ่านพร้อมกันทีเดียวครับ มันก็ต้องไล่ Scan อ่านทีละ Channel ให้เราเหมือนกัน แล้วก็ DMAContinuousRequests เป้น ENABLE
AdcHandle.Init.ScanConvMode = ADC_SCAN_ENABLE;
...
AdcHandle.Init.DMAContinuousRequests = ENABLE;
ลงมาตรง 3 - Channel configuration ตรงนี้เราจะใช้ Channel ไหนเพิ่มเราก็ไป Init เพิ่มครับ ผมเพิ่ม PA1 ก็คือ Init ADC Channel 1 เพิ่ม
ในส่วนของ L053 นั้น sConfig.Rank มัน Fix ครับ คือปรับไปมันก็ไม่สนใจค่านี้ แต่ผมไม่รู้ว่า F072 เราต้องกำหนดมั้ย มันคือให้เราเลือกว่าเราจะให้มันเริ่มแปลง Channel ไหนก่อนให้ระบุ Rank 0,1,2,3,... ไป
sConfig.Channel = ADC_CHANNEL_1;
sConfig.Rank = ADC_RANK_CHANNEL_NUMBER + 1;
sConfig.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
if (HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK)
{
Error_Handler();
}
ลงมาตรง Start conversion in DMA mode ก็เปลี่ยนขนาด buffer ให้เท่ากับจำนวนค่า ADC ที่เราจะอ่าน
/* ### - 4 - Start conversion in DMA mode ################################# */
if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)aResultDMA, 2) != HAL_OK)
{
Error_Handler();
}
กรณีจะอ่านหลายๆ ค่า และ หลายๆ channel ในเวลาเดียวกันก็ให้ประกาศ Array ที่ใช้รับค่า ADC จาก DMA เป็น 2D Array ได้ครับ แบบนี้
uint32_t aResultDMA[100][2];
/* ### - 4 - Start conversion in DMA mode ################################# */
if (HAL_ADC_Start_DMA(&AdcHandle, (uint32_t *)aResultDMA, 100*2) != HAL_OK)
{
Error_Handler();
}
เท่านี้ครับ ลองทดสอบดูนะครับ