TI TMS320F28004x - ADC 採樣及設定
Publish Date : 2024-02-15 09:29
當今韌體可被視為較為簡易的軟體
以軟體的角度可以這麼說不為過
但如果是越靠近硬體的韌體
這樣的說法可能要改變
我的背景為軟體
幾乎都沒有碰過硬體相關
高中的電學單元也幾乎忘光了
現在則成為一個數位電源的韌體工程師
進入這領域的韌體
不是大學時的專題
也不像是前文說到的–簡易的軟體
接觸到更多電路知識
程式執行過程,生命週期
記憶體的使用及CPU使用率的分配等等
很多的智識是在高階程式語言當中
不會注意到的
此章是進入韌體(以數位電源來說)重要的一節
以軟體工程師進入的視角來說
如何將外面的環境資訊與訊號,讓在MCU運作的程式碼知道?
像是外面的溫度,電壓,壓力等等
讓MCU知道後交由程式處理?
靠的就是ADC
ADC(Analog-to-digital converter, ADC, A/D 或 A to D)是類比數位轉換器, 用於將類比形式的連續訊號轉換為數位形式的離散訊號的一類設備。
將 外界的訊號(自然界的訊號為類比)
轉換為 數位的訊號
依照MCU不同的位元數轉並編碼為不同的等級訊號
比如
8位元的ADC可以將訊號分成256個等級($2^8$)
最強訊號在數位當中表示為256,最弱訊號為0
或是
12位元的ADC可以將訊號分成4096個等級($2^{12}$)
最強訊號在數位當中表示為4096,最弱訊號為0
假設最大訊號是3.3伏特的電壓
以12位元編碼就是
4096為3.3伏特
4095為3.29919伏特
4094為3.29838伏特
以此往下算
差值就可看出解析度
越多位元的ADC能力就會越精細
但是MCU的價格也就越貴
ADC處理訊號的過程
採樣(Sampling): 對輸入的訊號進行採樣。採樣頻率取樣多少次。越高的採樣頻率可以提供越更精確的訊號
量化(Quantization): 採樣訊號被量化為一系列離散的數值。這個過程將連續的訊號分成有限的數量級,這些級別代表不同的數值
編寫(Encoding): 採樣和量化的數位值通常以二進制形式進行編寫,以便 MCU 處理
輸出(Output): 最終的數值供 MCU 使用
ADC MCU設定
以下說明以TI晶片TMS320F28004x為範例,具體操作請參考各晶片官方文件
ADC單一模組如下:

TMS320F28004x是12位元的ADC,數位的結果計算方式如圖:

ADC的輸入如果在
VREFHI($V_{reference}$ High)
VREFLO($V_{reference}$ Low)
超出範圍的不是1就是0了
$V_{reference}$ High/Low 的設定是在MCU的外部接腳上

要以ADC的結果換算為實際值:

MCU會先經由前文提到的取樣頻率來取樣,並進行sample and hold(S+H)的方式來取樣
TMS320F28004x sample rate由ADC的預分頻器藉由系統的時鐘來設定
The ADC sample and hold circuits (S+H) are clocked by SYSCLK while the ADC conversion process is clocked by ADCCLK. ADCCLK is generated by dividing down SYSCLK based on the PRESCALE field in the ADCCTL2 register
ADC_setPrescaler(myADC0_BASE, ADC_CLK_DIV_2_0);
MCU中,需要有個trigger的訊號讓S+H啟動,也就是訊號轉換的時機
在adc_ex2_soc_epwm範例,就是ePWM訊號來trigger的
//
// Start ePWM1, enabling SOCA and putting the counter in up-count mode
//
EPWM_enableADCTrigger(EPWM1_BASE, EPWM_SOC_A);
EPWM_setTimeBaseCounterMode(EPWM1_BASE, EPWM_COUNTER_MODE_UP);
ADC的轉換是由單個SOC單元來轉換
TMS320F280049C有三個ADC模組
每一個模組又各有15個SOC單元
一個SOC單元可以各別配置ADC輸入pin,要trigger的來源以及S+H的時間
// Configures a start-of-conversion (SOC) in the ADC and its interrupt SOC trigger.
// SOC number : 0
// Trigger : ADC_TRIGGER_EPWM1_SOCA
// Channel : ADC_CH_ADCIN0
// Sample Window : 8 SYSCLK cycles
// Interrupt Trigger: ADC_INT_SOC_TRIGGER_NONE
ADC_setupSOC(myADC0_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM1_SOCA, ADC_CH_ADCIN0, 8U);
ADC_setInterruptSOCTrigger(myADC0_BASE, ADC_SOC_NUMBER0, ADC_INT_SOC_TRIGGER_NONE);
或是更深入的可以設定每個SOC轉換的順序
// Sets the priority mode of the SOCs.
ADC_setSOCPriority(myADC0_BASE, ADC_PRI_ALL_ROUND_ROBIN);
轉換順序的排程方法於技術文件有寫到,這裡不作討論
ADC可設定中斷,adc_ex2_soc_epwm範例設定如下:
ADC_SOC_NUMBER0轉換結束時觸發中斷
// ADC Interrupt 1 Configuration
// SOC/EOC number : 0
// Interrupt Source: enabled
// Continuous Mode : disabled
ADC_setInterruptSource(myADC0_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);
ADC_enableInterrupt(myADC0_BASE, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(myADC0_BASE, ADC_INT_NUMBER1);
ADC_disableContinuousMode(myADC0_BASE, ADC_INT_NUMBER1);
// Interrupt Setings for INT_myADC0_1
Interrupt_register(INT_myADC0_1, &adcA1ISR);
Interrupt_enable(INT_myADC0_1);
取的轉換結果時,直接存取ADC result register就可以
myADC0Results[index++] = ADC_readResult(ADCARESULT_BASE, ADC_SOC_NUMBER0);
ADC在MCU控制中,是除了通訊之外,能夠取得外界資訊的重要方式
軟體(韌體)上的設定會影響到
- CPU的計算時間 – 一直去取得ADC result及計算回真實數據的時間
- 硬體的配合 – 於線路上的S+H的delay時間
- 準確度 – 假設用於控制系統,ADC的回饋的即時性及正確性會影響整個系統的穩定度
因此在設計ADC的時候
會依照技術文件上的說明進行
因為配合到硬體的部份
訊號從外部到MCU,中間的過程中都需要進行考慮
也是新手剛進來時,可以體會到硬體影響到韌體上設計