版本 8d2b282d5d8a2b014f7f250fa68f7142343ceefb
ADC
Introduction
數位類比轉換器(Analog-to-digital coverter),用於將類比形式的連續訊號轉換為數位形式的離散訊號的一類設備。
.. image:: /embedded/ADC/圖片2.png 取樣率(Sampling rate) ———————- - 類比訊號在時域上是連續的,因此可以將它轉換為時間上連續的一系列數位訊號。這樣就要求定義一個參數來表示新的數位訊號取樣自類比訊號速率。 - 這個速率稱為轉換器的取樣率(sampling rate)或取樣頻率(sampling frequency)。
解析度(Resolution)
- 對於允許範圍內的類比訊號,它能輸出離散數位訊號值的個數。
- 這些訊號值通常用二進制數來存儲,因此解析度經常用位元作為單位,且這些離散值的個數是2的冪指數。
- 例如,一個具有8位解析度的類比數位轉換器可以將類比訊號編碼成256個不同的離散值(因為2^8 = 256)。
.. image:: /embedded/ADC/adc_convert.png
ADC on STM32F4
- 共有3個12-bit ADC 在開發板上,且可量測16個外部訊號源及2個內部訊號源。
- 有12-bit, 10-bit, 8-bit or 6-bit共4種可選擇的解析度。
- 每個通道的A/D轉換可以使用單次、連續、掃描或間斷模式執行。
- ADC的結果可以左對齊或右對齊的方式儲存於16-bit暫存器中。
.. image:: /embedded/ADC/ADC on STM32F4
Independent Mode
Single-channel, single conversion mode ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 此模式只會針對單一通道執行單次轉換,且完成轉換後則停止。 - 可用來檢查電壓來決定系統是否可以啟動。
.. image:: /embedded/ADC/SSM.png
Multichannel (scan), single conversion mode ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 此模式可使用多個通道依序執行單次轉換,最多可以達到16個通道且可使用不同的取樣時間及不同的通道順序。 - 可用來檢查多種訊號(如電壓、壓力、溫度等)來確保系統可以啟動。
.. image:: /embedded/ADC/MSM.png
- 下圖是個例子:
.. image:: /embedded/ADC/MSMex.png
Single-channel continuous conversion mode ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 此模式以單一通道連續執行轉換。 - 可讓ADC在背景連續執行,且CPU不會干預。 - 另外可利用DMA的circular mode降低CPU的負擔。 - 可用來監控電池電壓或是量測溫度。
.. image:: /embedded/ADC/SCM.png
Multichannel (scan) continuous conversion mode ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 此模式與Multichannel (scan), single conversion mode類似,但執行至最後一個通道後不會停止,而是會回到第一個通道執行轉換。 - 可用來量測多組電壓及溫度,像是電池充電器,可監控每個電池的電壓及溫度,當電壓或溫度到達最達最大值時必須能將電池斷路。
.. image:: /embedded/ADC/MCM.png
ADC Voltage Measurement
::
ConvertedVoltage = ConvertedValue*VDD/4095;
ADC Temperature Measurement
.. image:: /embedded/ADC/formula.png ::
ConverTemp= ((((ConverValue*VDD)/4095)-V25)/Slope + 25;
Demo
- Video
- 溫度 : http://youtu.be/93aU9fYuZaQ
- ADC Voltage Convertion(with Power Supply)
.. image:: /embedded/ADC/ADC_PowerSupply.jpg
.. image:: /embedded/ADC/ADC_Convert.jpg
- ADC Voltage Convertion(with Battery)
.. image:: /embedded/ADC/ADC_battery.jpg
.. image:: /embedded/ADC/ADC_pin.jpg
Questions
- ADC的轉換時間有多快? 不一定隨著條件而變,Sample Time跟温度以及内部電路的rc有關
::
Tconv = Sample Time + 12 cycles ( 12-bit resolution ) Sample Time = [3 - 480] cycles Total conversion time = [0.50 - 16.40] µs,with ADCCLK = 30MHz. So, Sample Time must > 16.4µs 。
.. image:: /embedded/ADC/table7.jpg
Refer from: STM32F407xx Datasheet P125
- Bandwidth大小為多少?
- 頻率響應為多少,可容忍的最大頻率呢? 在Datasheet中,因為我們參考電壓VDD為2.97V,故Frequency為[0.6-36]MHz。
.. image:: /embedded/ADC/table6.jpg
Refer from: STM32F407xx Datasheet P124
- ADC在Stm32的flow中,會經過的,會用到的電路和元件有哪些? 有External Event Trigger(e.g. timer capture,EXTI),GPIO ports,External/Internal Reference Voltage,Analog to Digital convert core, Temperature Sensor,Analog Multiplexer,Injected/Regular data register,Analog watchdog,Address/date bus,ADC Clock…。
.. image:: /embedded/ADC/22.JPG
STM32F407xx Reference Manual<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/DM00031020.pdf>
_ 參照P264 ADC block diagram
- 測試的接法? 請參考Demo.
- ADC的公式在哪裡找到?
STM32F407xx Reference Manual<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/DM00031020.pdf>
_ 在 11.10 Temperature sensor 中溫度轉換公式為
- ADC的公式在哪裡找到?
::
Temperature (in °C) = {(VSENSE – V25) / Avg_Slope} + 25
Where: V25 = VSENSE value for 25° C、 Avg_Slope = average slope of the temperature vs. VSENSE curve (given in mV/°C or μV/°C)
- 溫度的範圍?
STM32F407xx Reference Manual<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/DM00031020.pdf>
_ 在 11.10 Temperature sensor 中提到 Supported temperature range: –40 to 125 °C, Precision: ±1.5 °C。
- 溫度的範圍?
- 當在測量輸出電壓時,三用電表在pin腳上量到的電壓大小與gdb上所取得到的值得誤差有多少?
- 如何先做溫度上的校準? 利用內建溫度感測計在做實驗時,由於無法獨立出一個sensor出來測,所以實驗的環境下是在室溫的環境下,並利用溫度計來量測室溫為多少,來比對板子上所抓到的溫度與溫度計上的溫度.
補:
STM32F407xx Reference Manual<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/DM00031020.pdf>
_ 在 11.10 Temperature sensor 中一張中的Note提到,此開發版的內部溫度感測器適合來偵測溫度的變化,依據溫度感測公式來看,是基於25°C下與offset得到的溫度值,也就是適合觀察溫度變化,並不適合來取得室溫上的絕對溫度. 所以若要測量精確的絕對溫度的話,Manual上建議外接溫度感測器較為合適.- 整個程式上的架構為如何? 一開始程式先初始化ADC會用到的硬體資源,其中包含Interrupt、ADC、DMA的初始,之後將ADC的TASK註冊到freertos裡面,Task中是做了DMA所註冊的通道與NVIC的channel設定,而當中我們註冊了 DMA_Stream0_IRQHandler(void),此Interrupt handler會在每次資料由peripheral到memory傳完之後,產生DMA的interrupt,去更新溫度值或電壓值.
詳細的設定請參考下方的Sample code
- Structure
.. code-block:: prettyprint
int main()
{
prvSetupHardware();
xTaskCreate(vADC_DMATask, .., .., .., ..);
vTaskStartScheduler();
}
- 如何選擇mode? Scan or Continuous? Two groups => a.Regular group。(16 channels) b.Injected group。(2 channels)
::
1.Single conversion mode => ADC dose one conversions。
2.Continuous conversion mode => ADC stars a new conversion as soon as is finishes one。
3.Scan mode => This mode is used to scan a groupof analog channels。
4.Discontinuous mode => Regular group。( n conversions,n<=8 )
- 若想要取得其他外部Sensor的Anolog值,要如何取得? 利用GPIO,設定要接出的Pin腳,並連接至外部訊號上。
- 頻率除以4要幹嘛?不除頻又會怎樣? 頻率目的是方便操作與計算,因為我們設定Sample/Convert Time,單位是cycle,
而 ADCCLK generates from APB2,fPCLK = 84MHz,1 cycle = 0.0119 µs,溫度感測時間需要17 µs。
若設定1個cycle=0.0119 µs,則需要1428個cycles,但是ADC_Sample_Time 支援上限為480 Cycles。
- ExternalTrigConvEdge和ExternalTrigConv是甚麼?觸發又是在幹嘛? 分別為以下︰
- 1.ExternalTrigConvEdge
.. image:: /embedded/ADC/table9.jpg
- 2.ExternalTrigConv
.. image:: /embedded/ADC/table10.jpg
- DMA跟ADC之間是在幹嘛的? 規則通道轉換後的數值儲存在一個唯一的暫存器中,所以當轉換多個規則通道時需要使用DMA,用來避免遺失已經儲存在ADC_DR暫存器的數據。
只有在規則通道轉換結束後才能產生DMA的請求,並且將轉換後的數據從ADC_DR的暫存器傳輸到用戶指定的目的地位址。
- 為什麼要設定DMA,照我們我的作法是跑迴圈的方式去polling溫度的值?要做DMA的話會花幾個cycle?
- DMA_Mode_Circulur這mode在做甚麼用? 主要用來處理circular buffers和連續的data flow(像是ADC的scan mode)。
當此模式啟動時,會將要傳送的資料載入在stream config所設定的初始值,且DMA request會持續服務。
- DMA2_Stream0是甚麼?為什麼是以Stream的方式? DMA Stream 提供了一個source to destination的單方向傳輸的連結,像是周邊到記憶體或是記憶體到周邊。
- 用while loop可能會取得錯誤的值,也可能會浪費資源?
- 溫度的sampling rate設成20MHz會不會太高,或許1KHz會差不多,開發程式中要call api時,config中值是否可參數化? 溫度的Sample Time是經由公式計算出,無法設定,Datasheet有提供公式,需要設定是Sample Time必須大於取樣時間的MAX值,
您的問題應該是Sampling Rate(取樣頻率),就根據使用者需求來設定轉換模式,並算出轉換頻率。
.. image:: /embedded/ADC/table8.jpg Sample Code =========== - main
.. code-block:: prettyprint
int main()
{
...
/* Start the tasks defined within this file/specific to this demo. */
xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED3", configMINIMAL_STACK_SIZE, (void *)LEDS[0], tskIDLE_PRIORITY, &xLED_Tasks[0] );
xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED4", configMINIMAL_STACK_SIZE, (void *)LEDS[1], tskIDLE_PRIORITY, &xLED_Tasks[1] );
xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED5", configMINIMAL_STACK_SIZE, (void *)LEDS[2], tskIDLE_PRIORITY, &xLED_Tasks[2] );
xTaskCreate( vLEDTask, ( signed portCHAR * ) "LED6", configMINIMAL_STACK_SIZE, (void *)LEDS[3], tskIDLE_PRIORITY, &xLED_Tasks[3] );
xTaskCreate( vADC_DMATask, ( signed portCHAR * ) "ADC", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
xTaskCreate( vSWITCHTask, ( signed portCHAR * ) "SWITCH", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
xTaskCreate( vMEMSTask, ( signed portCHAR * ) "MEMS", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xMEMS_Task );
xTaskCreate( vBALANCETask, ( signed portCHAR * ) "BALANCE", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, &xBALANCE_Task );
...
}
- vADC_DMATask
.. code-block:: prettyprint
void vADC_DMATask( void *pvParameters )
{
NVIC_InitTypeDef NVIC_InitStructure;
/**/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/**/
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
for(;;);
}
- DMA2_Stream0_IRQHandler
.. code-block:: prettyprint
void DMA2_Stream0_IRQHandler(void)
{
if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET) {
DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
ADC1ConverTemp = ( ( ( ( ADC1ConverValue * 2960 ) / 4096 ) - 760 ) / ( 25 / 10 ) ) + 25;
}
}
Reference
Analog-to-digital converter - Wikipedia, the free encyclopedia<http://en.wikipedia.org/wiki/Analog-to-digital_converter>
_稀里糊塗學 STM32 - 第四講:白駒過隙</embedded/learn-stm32-part-4.pdf>
_STM32F407xx Datasheet<http://www.st.com/web/en/resource/technical/document/datasheet/DM00037051.pdf >
_STM32F407xx Reference Manual<http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/REFERENCE_MANUAL/DM00031020.pdf>
_STM32™’s ADC modes and their applications<http://www.st.com/st-web-ui/static/active/cn/resource/technical/document/application_note/CD00258017.pdf>
_