簡介
本應用筆記介紹ADSP-CM408F模數轉換器控制器(ADCC)模塊的主要特性,重點討論該產品在高性能電機控制應用的電流反饋系統中的相關性與可用性。
本應用筆記的目的是為了強調模數轉換器(DAC)模塊的關鍵功能,并提供針對電機控制應用的配置指南。本文提供演示ADI ADCC驅動器的代碼示例。
有關此ADCC的所有功能、配置寄存器和應用程序接口(API)的更多詳細信息,請參閱ADSP-CM402F/ADSP-CM403F/ADSP-CM407F/ADSP-CM408F產品頁面和采用ARM Cortex-M4和16位ADC開發產品的ADSP-CM40x混合信號控制處理器的產品頁面上提供的《采用ARM Cortex-M4的ADSP-CM40x混合信號控制處理器硬件參考指南》。
雖然本應用筆記重點討論電流反饋,類似的配置和應用原理同樣適用于其他信號的反饋與測量。
同樣,雖然本應用筆記重點討論ADSP-CM408F,但原理在本質上同樣適用于ADSP-CM402F/ ADSP-CM403F/ADSP-CM407F/ADSP-CM408F系列的其他產品。
電流反饋系統概述
電機控制應用中的電流反饋示例如圖1所示。該配置常用于高性能電機驅動,并針對電機相位繞組電流采樣,而非對逆變器低端相位引腳采樣。中高電平時,電流傳感器或變壓器(CT0和CT1)必須用于電流測量路徑,因為阻性分流器尺寸過大而低效。
在圖1的配置中,處理器位于安全的隔離柵低壓側,而信號隔離通常為CT0和CT1所固有,且微處理器的脈沖寬度調制PWM輸出和柵極驅動器之間還存在數字隔離。
通常需要在電流傳感器輸出和ADC輸入之間進行一些信號調理,以便實現范圍匹配和高頻噪聲濾波。隨后將調理的電流測量信號施加于ADC輸入,用來采樣和轉換。對每個ADC輸入進行一次繞組電流測量將使能電流測量的同步采樣以獲得更高的控制環路精度,從而增強性能。另外,還可在硬件內直接配置采樣時間與PWM sync脈沖的同步。
圖1. 電機控制中ADSP-CM408F ADC的電流反饋
這些特性可使能PWM周期中相位電流測量點的精密時序。將這些測量時刻與零矢量的中間點或PWM周期的中間點對齊,確保電流采樣電平等效于忽略開關紋波的瞬時平均電流。
圖2中顯示了零矢量中點和PWM周期中點處的同步U相位和V相位采樣。
圖2. 平均電流采樣圖解
完成數據轉換后,便可將其通過直接存儲器訪問(DMA)傳輸至控制器靜態隨機存取存儲器(SRAM),完成傳輸后會生成一個中斷。在內核模式下,通過存儲器映射寄存器,還可實現直接ADC狀態和數據讀取,但這種方法需消耗更多的處理器開銷。
通常還會采樣其他模擬信號,例如直流總線電壓、隔離式柵極雙極性晶體管(IGBT)溫度和電機位置正弦與余弦輸出。雖然本應用筆記重點討論電流反饋,但很多信息也與系統中的其他測量參數有關。
ADC模塊概述
該ADC采用雙通道、16位、高速、低功耗、逐次逼近型寄存器(SAR)設計,精度高達14位。
輸入多路復用器最多支持連接兩個獨立受控ADC的26個模擬輸入源組合(每個ADC的12路模擬輸入加上1路DAC回送輸入),任意時刻都對兩個通道同步采樣。 ADC轉換時間快達380 ns。單端模擬輸入所需的電壓輸入范圍為0 V至2.5 V。
多路復用器和ADC之間提供片內緩沖器,無需使用額外的外部信號調理ADSP-CM408F。此外,每個ADC都有一個片內2.5 V基準電壓源,當優先選擇外部基準電壓源時可將其過驅(通過ADCC_CFG寄存器選擇該選項)。
ADSP-CM408F中的總模擬子系統的圖形概述如圖3所示。ADSP-CM408F采用多芯片系統級封裝(SiP),而ADC硅片制造工藝與處理器硅片工藝有所不同,如圖3所示。
ADCC負責ADC中與處理器的時序同步,并管理DMA,將采樣數據傳輸到SRAM。
圖3. ADSP-CM408F模擬子系統
電流反饋調整
若要最大限度地正確利用ADC的能力,正確調整反饋信號非常重要。信號通過反饋路徑處理,如圖5所示。雙極性相位繞組電流IW通過電流傳感器(或變壓器)和信號調理電路的組合功能轉換為ADC輸入端的單極性電壓。
電流傳感器的傳遞函數由下式表示:
其中:
為輸出電壓;是傳感器的線性增益系數;是傳感器的零電流失調電壓。
? KCT在不同傳感器類型的某些電流水平下表現出非線性,且為了獲得更佳的精度,應當與IW成函數關系,即KCT (IW)。之后,ADC輸入電壓可表示為:
? 其中,KSIG是信號調理電路的低頻增益。
? 該單極性電壓轉換為16位無符號整數,并由DMA傳輸至處理器存儲器,然后發出中斷,提醒控制程序新數據樣本可用。ADC理想化的傳遞函數如下所示:
?
? 其中:
? NIW是ADC數字輸出字。
? KADC表示ADC的線性增益,等于
? 根據輸入電壓范圍劃分的ADC分辨率,如上所示。
? ADC輸出會產生一些失調;而在軟件內進行一些失調補償(NADC_OFFSET)通常是一個好辦法,可將ADC自身的所有失調以及傳感器和信號調理電路產生的所有殘余失調從ADC輸出中去除。該值可在零電流周期(如系統啟動或禁用驅動輸出)中動態更新。
? 最后,電流傳感器零電流失調電壓NCT_OFFSET的數字表示從ADC輸出信號中去除,使帶符號值IW(與實際相位繞組電流有關)的表達式為:
? 其中:
?
? 這個帶符號的16位值可轉換為浮點值,或直接使用,具體取決于控制器實現方案。若要最大限度地利用ADC的全范圍,則系統中的正峰值受控電流必須與ADC輸入電壓2.5 V相對應,而負峰值受控電流與ADC輸入0 V相對應。
? 該情況的一個示例如圖4所示。該圖顯示了典型電流波形和相關的各種零電平、峰值電平以及標稱電平,圖4顯示的電流電平將轉換為通過信號測量系統傳播(如圖5所示)的比例量(參見表1)。
圖4. 電流反饋信號幅度
表1. 電流反饋信號幅度
本示例采用連接LEM?,的CAS 6-NP霍爾效應傳感器,其初級匝數為3,具有0 V至5 V輸出,后接增益為0.5的信號調理電路。
圖5. 電流反饋路徑的調整關系
?
ADC時序考慮因素
以PWM周期同步采樣事件對于精確電流反饋而言非常重要。ADCC采用PWM周期工作的概念時序如圖6所示。下列事件序列由PWM SYNC脈沖觸發。
1. PWM sync脈沖觸發定時器,以便啟動。
2. ADCC不斷將事件信息中的采樣時間與定時器時間比較。
3. 完成定時器匹配,ADCC計劃ADC操作。
4. ADC變為可用后,ADCC便使用事件信息選擇適當的通道。
5. ADCC觸發ADC轉換序列,ADC采樣并轉換數據。
6. 數據回流至ADCC。
7. ADCC將數據通過DMA傳輸至存儲器位置(LSB優先)。
8. 產生中斷(IRQ),提醒CPU數據樣本可用。
圖6. ADCC操作序列
ADCC事件時序
控制器管理最多24個采樣事件的配置和時序。這些事件的時序受觸發限制,該觸發會啟動兩個定時器(TMR0或TMR1)中的其中一個,并在定時器啟動后啟動一個事件時間。
如圖7所示,觸發源可從一系列外設或處理器事件中選取,如PWM SYNC脈沖、定時器或I/O引腳中斷。每次事件都與一個事件號碼(以Event x表示)、一個事件時間(以TIMEx表示)、控制信息(以CTLx表示)及其結果數據相關聯。事件控制信息(圖7中以CTLx表示)包含每個采樣事件的信息,如ADC接口和通道號、所用的ADC定時器、同步采樣選擇,以及相關事件ADC數據的存儲器失調。ADCC使用該信息對正確的ADC通道(CHx)進行多路復用處理、初始化ADC轉換(CVST0/CVST1信號)并將正確的數據傳輸至適當的事件數據寄存器中。
然后,可設置DMA傳輸,將每次事件的ADC數據移入SRAM中。完成所有事件和后續DMA傳輸之后,便產生一個中斷,通知主應用代碼新ADC數據可用。
圖7. ADCC模塊功能框圖
例如,圖8顯示與ADC定時器0有關的3個采樣事件。PWM sync脈沖觸發定時器,事件時間與每一次事件相關聯。
事件0和事件1是同步采樣事件,事件時間寄存器中的事件時間置零。事件2稍后發生,并同樣由事件2時間寄存器確定,表示為ADC時鐘周期(tACLK)的倍數。若事件2是與定時器0關聯的最終事件,則定時器將在事件處理完成后停止運行,以降低功耗。
圖8. 事件時序
ADC操作時序
ADCC控制器觸發采樣事件后,ADC操作本身具有一個轉換時間延遲。圖9顯示單次ADC事件與每個ADC接口相關聯,且使能兩次事件同步采樣的情況。
有三個獨立的轉換周期與ADC操作有關。
1. 寫入8位控制字,選擇ADC讀取通道(ADCC_EVTCTL.CTLWD)。
2. 置位轉換脈沖,使能ADC采樣和轉換。
3. 讓16位ADC數據回流至ADCC。
ADCC提供這3個事件相位的片選和選通時鐘信號。ADCC與ADC的接口為串行接口,采用雙通道位操作。因此,每個CS脈沖期間提供的最小時鐘周期數(ADCC時序控制寄存器的NCK段)為8。其他重要的設置有:ADC時鐘頻率、轉換周期片選信號之間的最小延遲(tCSCS)(ACLK周期內),以及CS邊沿和ACLK邊沿之間的最小延遲(tCSCK和tCKCS)。因此,單個同步采樣信號對的ADC轉換周期時間tCONV_ADC可表示為:
其中,fACLK表示ADCC時鐘頻率。
ADCC時鐘由處理器系統時鐘(fSYSCLK)通過ACKDIV分頻(在時序控制寄存器ADCC_TCA中)在內部產生,計算如下:
其結果是系統時鐘來源于處理器內核時鐘(fCORECLK)。當fCORECLK為fSYSCLK的整數倍時,獲得最佳系統性能。完成ADC轉換后,額外延遲是因為ADC數據通過DMA傳輸至數據存儲器,并最終由中斷請求服務將數據幀準備就緒,供主應用程序使用。因此,在應用中,從觸發(例如,PWM SYNC脈沖)到數據可用的總時間為:
tCONV_TOTAL = tCONV_ADC + tDMA + tIRQ
其中:
tDMA是DMA傳輸的平均時間。
tIRQ是中斷請求服務的平均時間。
圖9. 單次事件同步采樣的轉換時間
典型時序設置見表2。表中還列出了對時序的一些約束條件。獲得正確ADC性能的絕對約束條件是,允許的ADC采樣和轉換周期(tCONV_ADC/3)必須至少為380 ns。單個同步采樣事件的時序結果如圖10所示,該結果與電機繞組電流的采樣有關(注意,該圖為了突出示例而略為夸大)。
圖10. 采樣延遲時間
采用這些設置時,在所需的電流波形采樣點與實際采樣點之間存在450 ns失調。該值等于一個片選脈寬(200 ns + 25 ns + 0 ns)加兩次片選之間的脈寬(225 ns)。 該結果造成平均電機繞組電流和實際采樣電流之間的ΔiSAMP產生差異,在時序調度中需加以考慮,雖然在1 kHz的典型電流控制環路帶寬環境中,這表示不超過0.2°的相移。此外,對于10 kHz的典型PWM頻率,ADC數據從產生PWM SYNC脈沖(表2中的設置)起,在不足2%的可用PWM周期時間內可供應用程序使用。如果在事件發生時ADC處于空閑狀態,則4至5個SYSCLK周期的額外延遲將存在于事件激活的時刻與ADC開始工作的時刻之間。
圖11. 采樣時刻調整的實現
表2. 典型ADC設置的時序設定
??????
采樣時刻調整
可能需要進一步提高電機電流采樣時刻的精度并消除所需采樣時刻和實際采樣時刻之間的450 ns失調。精度提高后對低電感伺服電機等應用案例或者采用較高開關頻率的情況特別有益。要消除這一較小的時間偏移量,一種方法是使用通用(GP)定時器在PWM sync脈沖前一個ADCC片選脈寬處創建觸發。這可以通過從前一PWM sync脈沖觸發GP定時器來實現,如圖11所示。使用此方法時,在PWM周期結束前安排任何采樣事件時必須謹慎。所有采樣事件必須在下一周期開始前一個片選脈寬處完成(圖11中的EVT0標記)。
ADC流水線
當新事件開始與ADC正在處理的現有事件重疊時,ADCC將新事件作為待處理事件存儲在8深先進先出(FIFO)緩沖器中,該緩沖器可用于所有ADC接口。寫入激活事件的控制字后,ADCC立即開始寫入首個待處理事件的控制字,同時進入激活事件的采樣階段。同樣,第一個待處理事件的控制字階段執行完成后,便進入第二個待處理事件的控制字階段。以這種方式,ADCC可在每個ADC接口上通過流水線方式交錯處理三個并行事件。因此,事件能以緊湊高效的方式排列。
配置事件時序使事件以上述流水線方式處理,可獲得最高的ADC吞吐速率。該流水線如圖13所示。圖中,三對同步采樣事件的觸發時間間隔很短。
圖中,三對同步采樣事件的觸發時間間隔很短。ADCC開始處理事件0和事件1,同時將事件2至事件5存儲在FIFO中。然后,ADC資源變得可用時,便會對這些事件進行處理。
從圖7可知,在CS某次置位期間,ADCC會處理全部6個事件以及每個事件的多個階段,并且兩次連續采樣之間的時間間隔僅為18個ACLK周期。該時間間隔相當于表2設置中的450 ns,且可通過提高ACLK頻率進一步降低。若要在電機控制應用內最大化ADC帶寬,最好的方法是有意識地將所有與PWM周期相關的采樣事件以流水線方式處理。該方法可以確保新的ADC樣本能在PWM周期中可能的最早時刻準備就緒。要實施圖13中顯示的流水線,則需要所有事件時間均接近零,即緊跟在PWM SYNC脈沖后。
建議在兩個事件時間寄存器ADCC_EVTnn(nn表示0到24的寄存器編號)中存儲的事件時間之間允許一個最小1 ACLK周期,實現正確調度。
圖12中顯示使用流水線操作時的總轉換時間,包括起始延遲、DMA傳輸和中斷服務,可用于采用表2中所示時序設置的各種同步采樣對數目。
圖12. 不同采樣對數目的總轉換時間
圖13. ADC中的流水線事件
ADC數據訪問
目前為止,本文中的示例都假定ADC數據采用自動DMA傳輸從存儲器中訪問。從ADCC存儲器映射寄存器(MMR)的內核讀數中直接訪問數據是可行的,如圖14所示。注意,圖14中的ACK表示確認信號,而非模擬時鐘。
圖14 內核模式的ADC數據訪問
在內核模式下,CPU通過事件或幀中斷獲取有關新數據就緒的信號,這些中斷可按需獨立屏蔽或解除屏蔽。該模式下還具有額外的靈活性:在整個事件幀結束前,一旦完成獨立事件,即可對其進行讀取。內核模式的缺點是中斷服務以及MMR讀訪問所需的總延遲比DMA模式下要高。采用優化的內核和時鐘分頻比設定,則在每個中斷服務的最高延遲情況下,每次MMR讀操作將花費10至12個SYSCLK周期。
圖15顯示了DMA模式下的數據訪問。
在這種情況下,DMA傳輸僅在完成一個定時器幀后才會發生,且幀中斷信號僅在完成DMA傳輸后才發給CPU。
圖15. DMA模式下的ADC數據訪問
兩種情況下,EISTAT和FISTAT寄存器都在激活后提供事件和幀中斷的狀態指示,且必須在下一次觸發前經由CPU清零相關位確認,否則將標記一次觸發溢出條件。
ADCC數據故障檢測
ADCC提供多個故障狀態寄存器位,發生數據故障時可置位;ADCC事件時序和/或不確定事件序列設置不當時,就有可能發生數據故障。這些故障可能使ADCC過載,或造成無效的ADC數據。它們包括:
· 觸發溢出。當前幀結束前便觸發下一次事件。
· DMA帶寬。幀結束所需的時間長于用戶定義時間。
· 存儲器錯誤。ADC數據寫操作失敗。
· 事件沖突。處理現有事件時發生新事件。
· 事件錯失。事件未處理。
這些錯誤均可按需配置為內核的中斷源,并且它們都會置位ADCC_ERRSTAT寄存器。在電機控制應用中,尤其在電流反饋測量中,與事件錯失、存儲器和觸發溢出有關的錯誤對于監控核心應用非常重要,因為錯誤或錯失的電流環路數據可能會導致控制環路的不穩定。事件沖突在流水線操作中非常普遍,通常影響不大,除非FIFO已滿。
ADCC模塊、觸發路由和存儲器設置
使用ADC之前,需執行一系列步驟來設置ADCC模塊以及觸發路由單元和數據緩沖器。完成配置后,假定采用DMA數據訪問模式,則DMA引擎會自動將主ADC數據傳輸至存儲器,供主應用程序進行內部訪問。當數據就緒時,ADCC產生中斷,以便處理器執行控制算法并更新PWM調制器寄存器。
圖17顯示ADCC、CPU、SRAM、PWM和外部信號之間所需的互連,可用于在典型電機控制應用中捕捉電機電流反饋以及其他模擬監控信號。在本例中,編碼器正弦和余弦信號、散熱片溫度和直流總線電壓作為額外監控輸入示例提供。
設置ADCC以便正確處理信號反饋的三個步驟如下所示:
1. ADCC事件配置。
2. 中斷和觸發路由。
3. 數據訪問和存儲器分配。
下列子段落描述正確設置系統所需的步驟與相應的寄存器配置。
圖17. 典型電機控制應用中的系統互連
ADCC事件配置
ADCC事件的配置示例如圖17所示,該示例包括為每個事件分配定時器、ADC接口和通道、時間偏移以及同步采樣開關。這可以通過多種方法實現;圖16以及表3所示為其中的一種可能情況。該示例采用全部兩個定時器,僅供參考。
對于此示例,事件可連接至一個定時器,因為所有事件的定時都與PWM SYNC脈沖有關。
在諸如雙軸電機控制算法這類用例中,可能必須同時使用兩個定時器,因為該用例采用兩組PWM輸出以及相應的PWM sync脈沖。
圖16. 電機控制應用中的典型ADCC
表3. 示例應用的事件配置
?
相位電流iV和iW在發生PWM sync脈沖觸發后立即同步采樣,它們關聯至TMR1。定時器1幀立即通過DMA傳輸至存儲器,且新的電流樣本可供主應用程序使用。在PWM周期中的較晚時刻,新的事件幀采樣并關聯至TMR0。
編碼器正弦和余弦信號同步采樣,緊隨其后的是直流總線電壓和散熱片溫度信號。
對三個ADC0信號進行流水線處理,以最大化吞吐速率。然后,將TMR0幀通過DMA傳輸至存儲器。
這些參數的配置需設置ADCC_EVCTLnn事件控制寄存器和ADCC_EVTnn事件時間寄存器,nn表示每個事件的編號。提供本節內容涉及的驅動程序API,簡化該過程。
中斷和觸發路由
在圖17中的示例中,所有事件時間均參考PWM周期;因此,兩個定時器都由PWM SYNC脈沖觸發。PWM sync脈沖作為硬件觸發與ADCC定時器相關聯的前提是配置TRU,使PWM sync脈沖作為主觸發信號與ADCC觸發從機相關聯。隨后,ADCC定時器必須與ADCC觸發相關聯。
圖18顯示相應觸發路由的概念圖;該路由涉及觸發主機19 (PWM0 SYNC)與觸發從機24 (ADCC_TRIG0)之間的連接,本例中該連接可通過將主機編號寫入適當的從機選擇寄存器TRU_SSR24來實現。之后,通過在ADC_CTL寄存器中為TRIGSEL位設置相應的值,將ADCC_TRIG0觸發路由至兩個定時器。
圖18. 從PWM SYNC至ADCC定時器的觸發路由
此觸發路由配置可以提供硬件的直連鏈路,將PWM時序與ADC采樣相關聯,而不會在路徑上產生軟件延遲。觸發主機也可從其他源路由,如GPIO引腳中斷、定時器和計數器事件。如此配置便可提供精確同步,比如與ADSP-CM408F控制的其他轉換器進行采樣同步。
此外,完整的ADCC定時器幀能作為觸發主機與其他外設或核心從機相關聯。
由于本例中采用了DMA傳輸模式,因此所有事件中斷都應當在ADCC_EIMSK寄存器中屏蔽。同樣,提供驅動程序API,用來在寄存器中設置適當的中斷服務例程,實現DMA模式下的幀中斷。
利用觸發路由提供增強型精確采樣時序
像上文所述那樣,要從當前采樣時序中移除片選脈寬滯后,需要稍微不同的觸發路由配置。在此情況中,ADCC定時器是通過GP定時器觸發器觸發的,而該觸發器本身是通過PWM sync觸發的。此序列可參見圖11。
數據訪問和存儲器分配
如圖14和圖15所示,可通過讀取內核MMR訪問ADC數據,或通過DMA傳輸使其能在SRAM中訪問。在內核模式下,無需配置特定存儲器分配,即可實現除變量外的內核MMR讀取數據的寫操作。然而在DMA模式下,必須分配特定的存儲器區域,然后進行配置,才能實現DMA訪問,并且每個定時器都必須配置。所需的存儲器大小取決于每個定時器相關的幀尺寸,以及新的幀覆蓋之前需要在存儲器中存儲多少幀。
表19顯示SRAM映射概念,以及控制SRAM配置的相關ADCC寄存器。ADCC_BPTR寄存器必須存儲指向存儲器基址的指針,才能存儲ADC樣本。若存儲器緩沖器中需要存儲多個幀,則ADCC_FRINC寄存器中應包含指針的偏移值,使其指向下一幀的基址。在線性緩沖模式下(通過向ADCC_CBSIZ寄存器寫入零來激活),會以持續增加的線性化方式在存儲器中存儲額外的幀,中間隔開一個幀的增量值。若向ADCC_CBSIZ寫入非零值M,則會激活循環緩沖,且在幀的基址指針返回ADCC_BPTR值并開始覆蓋現有幀數據之前向存儲器寫入M幀。
圖19. ADC DMA傳輸的存儲器配置
在圖17中的電機控制應用示例中,每個PWM周期都會采集ADC樣本,并即刻用于控制和監控應用中。因此,將樣本以線性方式存儲毫無意義,因為存儲器將很快過載。在此類應用中,最好在啟用循環緩沖時將M限制為1或更小的值,或者將ADCC_FRINC值設為0并在每個PWM周期中覆蓋幀。簡化這項任務的驅動程序應用編程接口(API)可在“ADCC軟件支持”部分找到。
ADCC軟件支持
與ADSP-CM40x EZKIT一同提供的ADI Enablement Software軟件包內含一系列API函數調用命令,可簡化本應用筆記中討論的ADCC模塊設置。這些調用命令監控不同寄存器的正確配置以及需要執行的任何狀態確認。
示例代碼
本應用筆記中的示例代碼逐步說明配置并使用圖17中電機控制應用的方法。器件驅動程序會增加額外開銷,但極大地簡化ADCC模塊寄存器編程。
代碼的第一部分定義一系列參數和配置常數,用于驅動程序API調用。
第1行至第10行定義每個定時器的幀和關聯的數據緩沖器大小。分配樣本緩沖器長度時,將包含系數2作為安全措施,用于調試目的。由于ADC樣本傳輸至存儲器的操作完全通過硬件觸發(包括DMA),因此在將新的緩沖器提交給驅動程序以及復位ADC緩沖器指針之前,如果在第122行插入軟件斷點,則可能導致存儲器被覆寫。以一個額外緩沖作為裕量可防止出現此類調試相關問題。緩沖器中的幀數目定義為1,這表示每次收到新幀,API便會覆寫存儲器緩沖器,即每個定時器僅需針對1個幀進行存儲器分配。
第11行到第16行以ACLK周期數形式定義每個事件的采樣時間,如表3所示。
注意,SMP_TIME1、SMP_TIME2和SMP_TIME3僅以一個ACLK周期分隔。該設置使這些事件在ADC0內以流水線方式進行處理。
第17行至第44行定義每個ADC通道的控制字、6個采樣事件的通道映射,以及數據緩沖器中每個事件的數組索引。
?
第45行至第59行聲明ADC操作所需的變量和函數原型。ADCC存儲器緩沖器和ADCC定時器存儲器緩沖器的存儲器分配大小由API預定義,且不得進行更改。一個ADCC設置函數、一個TRU設置函數以及兩個ISR回調函數(每個ADCC定時器各一個回調函數)對寄存器進行設置。
第60行至91行包含主ADCC配置函數SetupADC()。第一步是設置事件配置表,即含有事件編號、ADC控制字、ADC定時器、同步采樣以及每個事件的存儲器偏置的struct。
正確完成ADCC事件配置后,必須開啟ADCC實例,以及與該實例相關的所有ADCC定時器。然后,必須在寄存器中設置每個定時器幀中斷的驅動程序回調函數名(第72行至73行)。隨后,使能DMA模式(第74行),配置ADCC時鐘和芯片選擇(第75行至第78行)。
第81行將第62行定義的EventCFG指令傳遞至adi_adcc_ConfigEvent驅動程序函數,隨后adi_adcc_SetEventMask驅動程序函數按需使能或屏蔽事件。本例中,使能全部事件。為了獲得最高的ADC吞吐速率,使能雙位數據接口很重要,代碼見第83行,這表示能在8個ADC時鐘周期內傳輸ADC的16位數據。(注意,如果沒有使能雙位接口,則第76行中的NCK以及第77行和第78行中的tCSCS必須分別設為16和17)。然后進行數據緩沖器的存儲器分配,數據緩沖器將提交至ADCC,以便通過adi_adcc_SubmitBuffer調用進行填充。adi_adcc_SubmitBuffer API僅在DMA模式下工作;因此使用該API之前必須先設置DMA模式。該驅動程序函數由主應用程序再次調用(第105行),以便應用程序完成數據提取后將緩沖器歸還給ADCC控制。最終,完成全部配置后,需要使能定時器實例以及ADCC自身。
第92行至第97行包含TRU的設置步驟。它包括開啟TRU實例、將觸發從PWM sync主機路由至ADCC從機,以及使能TRU。
如前文所述,在應用層處理ADC數據由ADCC定時器回調函數實現,該回調函數后跟一個中斷,此中斷在完成定時器事件以及相關的DMA傳輸后發出。
第98至第127行實現回調函數。緩沖數據在緩沖器的相應位置處提取,并保存至適當的全局變量中。本例中,更新后的相位電流數據立即用于電機控制算法中,通過第117行中的算法調用函數MotorControl()從定時器1回調函數中調用。
注意,ADCC事件定時器中斷服務是訪問ADCC數據時發生的唯一軟件調用例程。同步與時序均在硬件層面中實現。
第128行至第136行包含的附加代碼片段可插入TRU和ADCC設置函數,以使能圖11所示的增強型精確采樣時序功能。第128行至第129行中設置了從PWM SYNC至GP定時器TMR7再至ADCC定時器0觸發的硬件觸發路由路徑。第130行至第136行包含的示例代碼可插入ADC設置函數,以正確配置和使能GP定時器TMR7,從而提供正確的延遲。
無論何時,都必須在調用SetupADC函數前調用SetupTRU函數。
P15
/*************************************************
ADCC Module Setup Code Example
*************************************************/
/********************Defines*********************/
1. #define ADCC_DEVICE_NUM 0
2. #define TRU_DEV_NUM 0
3. #define ADI_TRU_REQ_MEMORY
4. #define NUM_SAMPLES0 4
5. #define NUM_SAMPLES1 2 /* Length of ADC buffers */
6. #define FRAME_INC0
2*NUM_SAMPLES0*sizeof(short)
7. #define FRAME_INC1
2*NUM_SAMPLES1*sizeof(short) /* Frame
increment in number of bytes for each buffer*/
8. #define FRAMES_IN_BUFFER 1 /*Number of frames in buffer */
9. #define NO_OF_EVENTS 6 /* Total number of events */
10. #define EVENT_MASK 0xFFFF
/*Event Times in ACLK Cycles*/
11. #define SMP_TIME0 950
12. #define SMP_TIME1 950
13. #define SMP_TIME2 951
14. #define SMP_TIME3 952
15. #define SMP_TIME4 0
16. #define SMP_TIME5 0
/* Control Words for All ADC Channels */
/*Upper Nibble = Chan No. Lower Nibble = 0xF for Sim Sampling, 0xD Otherwise*/
17. #define ADC0_VIN00_CTL 0x0F
18. #define ADC0_VIN01_CTL 0x1F
19. #define ADC0_VIN02_CTL 0x2D
20. #define ADC0_VIN03_CTL 0x3D
21. #define ADC0_VIN04_CTL 0x4D
22. #define ADC0_VIN05_CTL 0x5D
23. #define ADC0_VIN06_CTL 0x6D
24. #define ADC0_VIN07_CTL 0x7D
25. #define ADC1_VIN00_CTL 0x0F
26. #define ADC1_VIN01_CTL 0x1F
27. #define ADC1_VIN02_CTL 0x2D
28. #define ADC1_VIN03_CTL 0x3D
29. #define ADC1_VIN04_CTL 0x4D
30. #define ADC1_VIN05_CTL 0x5D
31. #define ADC1_VIN06_CTL 0x6D
32. #define ADC1_VIN07_CTL 0x7D
/*Mapping the Signals to the Appropriate ADC Channels*/
33. #define ES_CTL ADC0_VIN00_CTL
34. #define EC_CTL ADC1_VIN00_CTL
35. #define VDC_CTL ADC0_VIN02_CTL
36. #define THS_CTL ADC0_VIN03_CTL
37. #define IV_CTL ADC0_VIN01_CTL
38. #define IW_CTL ADC1_VIN01_CTL
/*Locations of ADC Signals in Data Buffer Index*/
39. #define IV_ADC 0
40. #define IW_ADC 1
41. #define ES_ADC 0
42. #define EC_ADC 1
43. #define VDC_ADC 2
44. #define THS_ADC 3
/*******************Variables********************/
45. static ADI_ADCC_HANDLE hADCC; /* ADCC Handle */
46. static ADI_ADCC_HANDLE hADCCTimer0, hADCCTimer1; /*ADCC Timer Handles*/
47. static uint8_t ADCCMemory[ADI_ADCC_MEMORY]; /* Memory buffer for the ADCC device - predefined */
48. static uint8_t ADCCTmr0Memory[ADI_ADCC_TMR_MEMORY];
49. static uint8_t ADCCTmr1Memory[ADI_ADCC_TMR_MEMORY]; /* Memory buffer for the ADCC Timers - predefined*/
50. static uint16_t SampleBuffer0[NUM_SAMPLES0];
51. static uint16_t SampleBuffer1[NUM_SAMPLES1];
/* Memory buffer for the ADC samples */
52. static uint16_t Iv_adc, Iw_adc;
53. static uint16_t Es_adc, Ec_adc, Vdc_adc, Ths_adc;
/*Variables for ADC data*/
54. static uint8_t TruDevMemory[ADI_TRU_REQ_MEMORY];
55. static ADI_TRU_HANDLE hTru;
/*TRU Device Memory and Handle*/
/*************Function Prototypes****************/
56. void SetupADC(void);
57. void SetupTRU(void);
58. static void AdccTmr0Callback(void *pCBParam, uint32_t Event, void *pArg);
59. static void AdccTmr1Callback(void *pCBParam, uint32_t Event, void *pArg);
/******Function to Configure ADCC***************/
60. void SetupADC(void) {
61. static ADI_ADCC_RESULT result;
/*Set Up Event Configuration Table*/
62. ADI_ADCC_EVENT_CFG EventCFG[NO_OF_EVENTS] = {
63. {0, ES_CTL, ADI_ADCC_ADCIF0, ADI_ADCC_TIMER0, true, 0, SMP_TIME0},
64. {1, EC_CTL, ADI_ADCC_ADCIF1, ADI_ADCC_TIMER0, true, 2, SMP_TIME1},
65. {2, VDC_CTL, ADI_ADCC_ADCIF0, ADI_ADCC_TIMER0, false, 4, SMP_TIME2 },
66. {3, THS_CTL, ADI_ADCC_ADCIF0, ADI_ADCC_TIMER0, false, 6, SMP_TIME3 },
67. {4, IV_CTL, ADI_ADCC_ADCIF0, ADI_ADCC_TIMER1, true, 8, SMP_TIME4 },
68. {5, IW_CTL, ADI_ADCC_ADCIF1, ADI_ADCC_TIMER1, true, 10, SMP_TIME5 }}; /*Event#, CTL_WORD, ADC Interface, Timer ID, sim. samp, Mem offset in frame, Event time */
P16
/*ADCC Setup API Functions*/
69. result = adi_adcc_OpenDevice(ADCC_DEVICE_NUM, ADCCMemory, &hADCC);
70. result = adi_adcc_OpenTimer(hADCC, ADI_ADCC_TIMER0, ADCCTmr0Memory, &hADCCTimer0);
71. result = adi_adcc_OpenTimer(hADCC, ADI_ADCC_TIMER1, ADCCTmr1Memory, &hADCCTimer1); /* ADCC Device handle, Timer to open, Timer memory, Pointer to the timer handle */
72. result = adi_adcc_RegisterTmrCallback (hADCCTimer0, AdccTmr0Callback, hADCCTimer0);
73. result = adi_adcc_RegisterTmrCallback (hADCCTimer1, AdccTmr1Callback, hADCCTimer1);/*Register callback functions*/
74. result = adi_adcc_EnableDMAMode(hADCC,true);
75. result = adi_adcc_ConfigADCCClock(hADCC, ADI_ADCC_ADCIF0, false,1u, 8u);
76. result = adi_adcc_ConfigADCCClock(hADCC, ADI_ADCC_ADCIF1, false,1u, 8u ); /*For each ADC interface: ADCC handle, ADC Interface number, falling edge, ACLK Clock divide, NCK*/
77. result = adi_adcc_ConfigChipSelect(hADCC, ADI_ADCC_ADCIF0, false, 1u, 0u, 9);
78. result = adi_adcc_ConfigChipSelect(hADCC, ADI_ADCC_ADCIF1, false, 1u, 0u, 9);/*For each interface: ADCC handle, ADC interface, active low, TCSCK, TCKCS, TCSCS*/
79. result = adi_adcc_ConfigTimer(hADCCTimer0, ADI_ADCC_TRIG0, true, false);
80. result = adi_adcc_ConfigTimer(hADCCTimer1, ADI_ADCC_TRIG0, true, false); /*For each timer: Timer handle, Timer trigger source, falling edge trigger, No trigger output */
81. result = adi_adcc_ConfigEvent(hADCC, &EventCFG[0], NO_OF_EVENTS); /*ADCC handle, Pointer to the event configuration table, Number of events in the table */
82. result = adi_adcc_SetEventMask(hADCC, EVENT_MASK); /* Handle to the device, Enable all events */
83. adi_adcc_EnableDualBitDataIF(hADCC, true); /*Dual bit interface allows highest throughput*/
84. memset((void *)SampleBuffer0, 0, NUM_SAMPLES0 * sizeof(short));
85. memset((void *) SampleBuffer1, 0, NUM_SAMPLES1 * sizeof(short));
86. result = adi_adcc_SubmitBuffer(hADCCTimer0, SampleBuffer0, FRAME_INC0, FRAMES_IN_BUFFER);
87. result = adi_adcc_SubmitBuffer(hADCCTimer1, SampleBuffer1, FRAME_INC1, FRAMES_IN_BUFFER);
/*For each timer: timer handle, Pointer to the buffer, Frame increment, Number of frames that fits into the given buffer */
88. result = adi_adcc_EnableTimer(hADCCTimer0, true);
89. result = adi_adcc_EnableTimer(hADCCTimer1, true);
90. result = adi_adcc_EnableDevice(hADCC, true);
/*Enable everything*/
91. }
/*******Function to Configure TRU****************/
92. void SetupTRU(void){
93. ADI_TRU_RESULT result;
94. result = adi_tru_Open (TRU_DEV_NUM, &TruDevMemory[0], ADI_TRU_REQ_MEMORY, &hTru); /* Setup TRU for ADCC. Slave is ADCC0 trig 1 and master is PWM0 SYNC pulse*/
95. result = adi_tru_TriggerRoute (hTru, TRGS_ADCC0_TRIG0, TRGM_PWM0_SYNC); /*TRU device, slave, master*/
96. result = adi_tru_Enable (hTru, true); /*Enable TRU*/
97. }
/***********ADCC Timer Callbacks*****************/
98. static void AdccTmr0Callback(void *pCBParam, uint32_t Event, void *pArg){
99. switch(Event){
100. case ADI_ADCC_EVENT_FRAME_PROCESSED:
101. Es_adc= SampleBuffer0[ES_ADC];
102. Ec_adc = SampleBuffer0[EC_ADC];
103. Vdc_adc = SampleBuffer0[VDC_ADC];
104. Ths_adc = SampleBuffer0[THS_ADC];
/*Store all of the data sampled in appropriate global variables*/
105. _adcc_SubmitBuffer(hADCCTimer0, SampleBuffer0, FRAME_INC0, FRAMES_IN_BUFFER); /*Return the buffer to the ADCC for use in the next events*/
106. break;
107. case ADI_ADCC_EVENT_BUFFER_PROCESSED:
108. break;
109. default:
110. break;
111. }
112. static void AdccTmr1Callback(void *pCBParam, uint32_t Event, void *pArg){
113. switch(Event){
114. case ADI_ADCC_EVENT_FRAME_PROCESSED:
115. Iv_adc = SampleBuffer1[IV_ADC];
116. Iw_adc = SampleBuffer1[IW_ADC];
117. MotorControl(); /*Run the current control algorithm*/
118.
119.
120. break;
121. case ADI_ADCC_EVENT_BUFFER_PROCESSED:
122. adi_adcc_SubmitBuffer(hADCCTimer1, SampleBuffer1,
FRAME_INC1, FRAMES_IN_BUFFER);
123. break;
124. default:
125. break;
126. }
127. return;
}
P17
/*************************************************
Enhanced Precision Timing Code
*************************************************/
/*Setup TRU for ADCC enhanced timing precision. Slave is ADCC0 trig 1 and master is GP timer 7
Added to SetpTRU() function in place of line 95 */
128. result = adi_tru_TriggerRoute(hTru, TRGS_ADCC0_TRIG0, TRGM_TIMER0_TMR7); // TRU device, slave, master
129. result = adi_tru_TriggerRoute(hTru, TRGS_TIMER0_TMR7, TRGM_PWM0_SYNC); // TRU device, slave, master
/*Setup GP timer 7 timer used to advance frame by one CS. Add to SetupADC() function after line 91*/
130. *pREG_TIMER0_STOP_CFG_SET = BITM_TIMER_STOP_CFG_TMR07;
131. *pREG_TIMER0_RUN_CLR = BITM_TIMER_RUN_SET_TMR07; /*Disable Timer First*/
132. *pREG_TIMER0_TMR7_CFG = ENUM_TIMER_TMR_CFG_PWMSING_MODE|ENUM_TIMER_TMR_CFG_IRQMODE1 |ENUM_TIMER_TMR_CFG_TRIGSTART | ENUM_TIMER_TMR_CFG_POS_EDGE|ENUM_TIMER_TMR_CFG_PADOUT_EN | ENUM_TIMER_TMR_CFG_EMU_CNT;
133. *pREG_TIMER0_TMR7_DLY = (uint32_t)(fsysclk / F_SW - 0.00000045 * fsysclk); /* Delay must be Tsw minus one ADC chip-select. Chip select is 18 ACLKs*/
134. *pREG_TIMER0_TMR7_WID = 16; /*Be careful here... DLY+WID must be smaller than one PWM period. In other words, WID must be smaller than one ADC chip select. If WID>CS, trigger pulse stretches into next PWM period. */
135. *pREG_TIMER0_TRG_MSK &= ~(BITM_TIMER_TRG_MSK_TMR07);
136. *pREG_TIMER0_TRG_IE |= BITM_TIMER_TRG_IE_TMR07; /*Enable TMR7*/
示例實驗結果
“示例代碼”部分提供的電流采樣代碼部分已在閉環永磁同步電機控制應用電路中進行了測試。應用電路采用通用交流線輸入以及?6.8 A至+6.8 A的受控電機電流范圍,并利用了電流傳感器;該電流傳感器參數圖4中的電流調整數據。圖20至圖23還顯示了應用電路的采樣結果。
圖20顯示了參考速度為1500 rpm且電機空載時測得的電機相位電流。電機電流水平極低,并且高度不連續。
圖21顯示采用正確同步采樣方法的平均效應,由圖中可見電機相位電流具有平滑的正弦平均波形,即便電流水平低于最大值的2%時亦是如此。圖21和圖22(即跟蹤IQ參考電流的控制環路工作曲線)均通過ADSP-CM408F產生的數據流獲得,該產品通過RS-232連接MATLAB?接口。
在圖23中,PWM sync脈沖位置以及后續的采樣觸發顯示在相位電流PWM周期的中央,該處電流等于瞬時平均值。為便于說明,該圖顯示的是較高的負載。
圖20. 測量電機相位電流
圖21. ADC采樣電機相位電流:上圖為調整至真實值;下圖為數字字輸出
圖22. Q軸參考電流和實際電流
最后,在圖22中,PWM SYNC脈沖位置以及后續的采樣觸發顯示在相位電流PWM周期的中央,該處電流等于瞬時平均值。為便于說明,該圖顯示的是較高的負載。
圖23. 與相位電流有關的采樣
注釋
I2C指最初由Philips Semiconductors(現為NXP Semiconductors)開發的一種通信協議。
?
評論
查看更多