戰(zhàn):從直流輸出到DMA波形生成全解析)
1. 項(xiàng)目概述為什么HAL庫的DAC值得深挖在STM32的實(shí)戰(zhàn)開發(fā)中模擬信號輸出是一個繞不開的話題。無論是驅(qū)動一個老式的VU表頭、生成特定波形的信號源還是為音頻設(shè)備提供基準(zhǔn)電壓數(shù)模轉(zhuǎn)換器DAC都扮演著關(guān)鍵角色。很多開發(fā)者尤其是從標(biāo)準(zhǔn)庫或LL庫轉(zhuǎn)過來的朋友初次接觸HAL庫的DAC時可能會覺得它“封裝得太厚”配置項(xiàng)繁多遠(yuǎn)不如直接操作寄存器來得“痛快”。我最初也有同感但經(jīng)過多個項(xiàng)目的磨合我發(fā)現(xiàn)HAL庫的DAC模塊其實(shí)設(shè)計得非常周全它把很多容易出錯的細(xì)節(jié)和高級功能都封裝好了用熟了之后開發(fā)效率反而更高。這個實(shí)戰(zhàn)總結(jié)就是想把我踩過的坑、驗(yàn)證過的穩(wěn)定配置以及那些數(shù)據(jù)手冊里不會明說的“潛規(guī)則”分享出來。我們不止步于讓DAC“響起來”更要探討如何讓它“跑得穩(wěn)”、“輸出準(zhǔn)”。從最基礎(chǔ)的直流電壓輸出到利用DMA實(shí)現(xiàn)高速、低抖動的波形合成再到結(jié)合定時器觸發(fā)實(shí)現(xiàn)精確定時我們會把HAL庫DAC的里里外外都捋一遍。無論你是正在評估一個需要精密模擬輸出的新項(xiàng)目還是對現(xiàn)有DAC代碼的穩(wěn)定性不滿意希望找到優(yōu)化方向這篇總結(jié)里的內(nèi)容應(yīng)該都能給你提供直接的參考。2. DAC核心機(jī)制與HAL庫設(shè)計思想解析2.1 STM32 DAC的工作原理與核心配置項(xiàng)STM32的DAC模塊本質(zhì)上是一個數(shù)字值到模擬電壓的線性轉(zhuǎn)換器。以常見的12位分辨率DAC為例它將一個0到4095之間的數(shù)字值線性地映射到參考電壓所定義的一個電壓范圍上。這個“參考電壓”通常是VDDA模擬電源電壓它是DAC輸出精度的基石。如果你的VDDA是3.3V且穩(wěn)定那么數(shù)字值4095對應(yīng)的理論輸出電壓就是3.3V。這里就引出了第一個實(shí)戰(zhàn)要點(diǎn)DAC的精度和穩(wěn)定性首先取決于你的電源質(zhì)量。一個紋波大的VDDA會直接導(dǎo)致DAC輸出帶有噪聲。HAL庫將DAC的配置抽象為幾個關(guān)鍵結(jié)構(gòu)體最主要的是DAC_ChannelConfTypeDef。這個結(jié)構(gòu)體里的每一個成員都對應(yīng)著硬件寄存器中的一個或一組控制位。理解它們就理解了DAC的工作模式DAC_Trigger這是決定DAC何時更新輸出的“扳機(jī)”。選擇DAC_TRIGGER_NONE意味著你通過軟件直接寫數(shù)據(jù)寄存器來更新輸出這是最簡單的模式。但如果你需要周期性地、精確地更新輸出比如生成波形就需要選擇硬件觸發(fā)源如DAC_TRIGGER_T2_TRGO定時器2的觸發(fā)輸出。硬件觸發(fā)可以實(shí)現(xiàn)與系統(tǒng)其他部分嚴(yán)格同步是高質(zhì)量波形生成的關(guān)鍵。DAC_OutputBuffer輸出緩沖器。這是一個非常容易讓人糾結(jié)的選項(xiàng)。開啟緩沖器DAC_OUTPUTBUFFER_ENABLE可以降低輸出阻抗提高帶負(fù)載能力直接驅(qū)動一些高阻負(fù)載沒問題。但是開啟緩沖器會引入額外的偏移誤差和非線性并且輸出電壓范圍無法達(dá)到軌到軌即無法非常接近0V和VDDA。如果你的應(yīng)用需要最高的直流精度或盡可能寬的輸出擺幅比如需要輸出接近0V的電壓那么必須禁用輸出緩沖器DAC_OUTPUTBUFFER_DISABLE。代價就是驅(qū)動能力變?nèi)跬ǔP枰蠹壐S一個運(yùn)算放大器。DAC_Align數(shù)據(jù)對齊方式。12位數(shù)據(jù)寫入32位寄存器有左對齊、右對齊之分。HAL庫通常使用DAC_ALIGN_12B_R即12位右對齊。這一點(diǎn)務(wù)必和你的數(shù)據(jù)生成邏輯匹配寫錯了數(shù)值輸出電壓會完全不對。2.2 HAL庫的封裝哲學(xué)與利弊權(quán)衡HAL庫對DAC的封裝體現(xiàn)了其“以安全性和功能性為首要目標(biāo)”的設(shè)計哲學(xué)。它通過一系列HAL_DAC_*函數(shù)將寄存器操作、狀態(tài)標(biāo)志管理、錯誤處理都包裹起來。例如HAL_DAC_SetValue函數(shù)內(nèi)部會檢查DAC是否已初始化、通道是否使能然后才寫入數(shù)據(jù)。這避免了開發(fā)者直接操作寄存器時可能出現(xiàn)的順序錯誤。這種封裝的“利”很明顯代碼更易讀移植性更好減少了低級錯誤。但“弊”在于開銷和靈活性。每一個HAL函數(shù)調(diào)用都有一定的執(zhí)行時間對于需要極高更新率的應(yīng)用比如音頻采樣率48kHz頻繁調(diào)用HAL_DAC_SetValue可能成為瓶頸。此時直接操作DAC-DHR12R1這樣的數(shù)據(jù)保持寄存器在確保使能后或者使用DMA就成了必要手段。注意HAL庫的DAC驅(qū)動中狀態(tài)機(jī)管理比較嚴(yán)格。例如在啟動DMA傳輸前必須確保DAC處于HAL_DAC_STATE_READY狀態(tài)。如果流程不對很容易卡在HAL_BUSY。我的經(jīng)驗(yàn)是嚴(yán)格按照HAL_DAC_Init-HAL_DAC_ConfigChannel-HAL_DAC_Start的順序初始化并在啟動DMA傳輸前調(diào)用HAL_DAC_Start_DMA而不是自己手動配置DMA。3. 四大實(shí)戰(zhàn)場景配置詳解與避坑指南3.1 場景一基礎(chǔ)直流電壓輸出這是最簡單的應(yīng)用。目標(biāo)是讓DAC輸出一個固定的電壓值例如1.65V。配置步驟引腳與時鐘初始化通過CubeMX或代碼使能DAC時鐘__HAL_RCC_DAC1_CLK_ENABLE()并將對應(yīng)引腳如PA4對應(yīng)DAC1通道1配置為模擬模式。切記DAC引腳必須配置為“Analog”而不是普通的GPIO輸出。初始化DAC調(diào)用HAL_DAC_Init(hdac1)。這個函數(shù)主要處理DAC的公共部分。配置通道填充DAC_ChannelConfTypeDef結(jié)構(gòu)體。對于直流輸出觸發(fā)源選擇DAC_TRIGGER_NONE輸出緩沖器根據(jù)需求選擇如需高精度、寬幅輸出則禁用對齊方式選DAC_ALIGN_12B_R。然后調(diào)用HAL_DAC_ConfigChannel(hdac1, sConfig, DAC_CHANNEL_1)。使能通道與輸出電壓調(diào)用HAL_DAC_Start(hdac1, DAC_CHANNEL_1)使能通道。此時輸出可能是0V。然后計算對應(yīng)電壓的數(shù)字值。公式為Value (Vout / Vdda) * 4095。例如Vdda3.3V需要輸出1.65V則Value (1.65 / 3.3) * 4095 2047.5取整為2048。最后調(diào)用HAL_DAC_SetValue(hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048)。避坑指南輸出電壓不準(zhǔn)首先用萬用表測量VDDA的實(shí)際電壓用它來計算而不是理論值3.3V。其次檢查輸出緩沖器設(shè)置。禁用緩沖器后輸出在低電壓區(qū)接近0V和高電壓區(qū)接近VDDA的非線性會改善但中間段可能因芯片而異可以嘗試做一次簡單的兩點(diǎn)校準(zhǔn)。輸出有噪聲或波動確保模擬電源VDDA、VSSA的濾波電容已正確焊接并且遠(yuǎn)離數(shù)字電源的噪聲源??梢栽贒AC輸出引腳到地之間加一個幾十到幾百皮法的小電容濾除高頻噪聲但容值太大會影響響應(yīng)速度。3.2 場景二DMA驅(qū)動波形生成以正弦波為例這是DAC的進(jìn)階應(yīng)用用于生成連續(xù)變化的波形如正弦波、三角波。核心思想是預(yù)先把一個周期的波形數(shù)據(jù)數(shù)組存儲在內(nèi)存中然后由DMA自動、循環(huán)地將這些數(shù)據(jù)搬運(yùn)到DAC的數(shù)據(jù)寄存器。配置步驟生成波形數(shù)據(jù)表在代碼中定義一個數(shù)組例如uint16_t SineWave12bit[128]。用數(shù)學(xué)計算或工具預(yù)生成一個周期正弦波的12位右對齊數(shù)據(jù)。數(shù)組長度決定了波形的“粒度”越長則波形越光滑但消耗內(nèi)存越多DMA循環(huán)周期也受影響。配置DAC與場景一類似但關(guān)鍵區(qū)別在于觸發(fā)源。此時需要選擇一個硬件觸發(fā)源來驅(qū)動DAC更新例如DAC_TRIGGER_T6_TRGO使用定時器6。DAC會在每次定時器觸發(fā)事件到來時自動將DMA輸送來的下一個數(shù)據(jù)加載到輸出寄存器。配置定時器配置一個定時器如TIM6作為觸發(fā)源。定時器的更新頻率就是DAC的輸出采樣率。采樣率 定時器時鐘 / (PSC 1) / (ARR 1)。例如定時器時鐘72MHz要生成1kHz正弦波且波形表有100個點(diǎn)則DAC需要每秒更新100k次100點(diǎn) * 1k波形。那么定時器ARR應(yīng)配置為 (72MHz / 100kHz) - 1 719。配置DMA在CubeMX中為DAC通道的DHR寄存器配置DMA流如DAC1, Channel1對應(yīng)DMA1 Stream5。方向?yàn)閮?nèi)存到外設(shè)數(shù)據(jù)寬度為半字16位對應(yīng)12位數(shù)據(jù)對齊模式為循環(huán)模式。在代碼中調(diào)用HAL_DAC_Start_DMA(hdac1, DAC_CHANNEL_1, (uint32_t*)SineWave12bit, 128, DAC_ALIGN_12B_R)。避坑指南波形畸變或卡頓檢查DMA緩沖區(qū)是否夠大以及DMA傳輸完成中斷是否影響了定時器觸發(fā)。確保定時器中斷優(yōu)先級低于或等于DMA傳輸完成中斷避免定時器中斷被延遲。更優(yōu)的做法是不使用DMA傳輸完成中斷僅用循環(huán)模式靜默運(yùn)行。采樣率計算錯誤這是最常見的問題。務(wù)必分清“波形頻率”和“DAC更新頻率”。DAC更新頻率采樣率必須遠(yuǎn)高于你生成的波形頻率通常需要10倍以上奈奎斯特定理實(shí)際中為了波形質(zhì)量常取20-100倍。上面例子中1kHz波形100點(diǎn)/周期采樣率就是100kHz。內(nèi)存對齊確保你的波形數(shù)據(jù)數(shù)組在內(nèi)存中的地址是對齊的通常是2字節(jié)對齊否則可能引發(fā)DMA硬件錯誤。使用__ALIGNED(2)修飾數(shù)組定義可以避免此問題。3.3 場景三定時器觸發(fā)與同步輸出當(dāng)你的系統(tǒng)中有多個需要同步的模擬輸出或者DAC輸出需要與其他外設(shè)如ADC采樣、另一個定時器嚴(yán)格同步時就必須使用定時器觸發(fā)。配置核心關(guān)鍵在于定時器的“主/從模式”和“觸發(fā)輸出TRGO”功能。例如你可以將TIM2配置為主模式使其更新事件產(chǎn)生TRGO信號。這個TRGO信號可以同時觸發(fā)DAC1和DAC2如果存在甚至可以觸發(fā)ADC開始一次轉(zhuǎn)換。實(shí)現(xiàn)步驟配置一個定時器主定時器開啟“主模式”選擇“更新事件”作為觸發(fā)輸出TRGO源。配置DAC的觸發(fā)源為該定時器的TRGO如DAC_TRIGGER_T2_TRGO。如果使用DMA則DAC會在每次收到TRGO信號時自動加載DMA提供的新數(shù)據(jù)。如果需要DAC輸出一個單次或特定序列的電壓可以在定時器觸發(fā)中斷中用軟件更改DAC輸出值這樣可以實(shí)現(xiàn)與定時器中斷嚴(yán)格同步的復(fù)雜序列。避坑指南觸發(fā)無反應(yīng)檢查主定時器是否確實(shí)使能并開始計數(shù)。檢查DAC的觸發(fā)源配置是否正確HAL庫中對應(yīng)的觸發(fā)選擇枚舉值必須準(zhǔn)確。同步精度硬件觸發(fā)同步的精度遠(yuǎn)高于軟件定時。但要留意從觸發(fā)信號發(fā)出到DAC輸出電壓穩(wěn)定有一個微小的建立時間Tsetting在數(shù)據(jù)手冊中可以查到。在要求極高的場合這個延遲需要考慮。3.4 場景四雙DAC通道的協(xié)同工作部分STM32型號包含兩個DAC通道如DAC1_CH1, DAC1_CH2。它們可以獨(dú)立工作也可以在某些模式下協(xié)同。獨(dú)立模式最常見的用法。每個通道有自己的數(shù)據(jù)寄存器、觸發(fā)源和輸出引腳。配置方法完全等同于兩個獨(dú)立的DAC。同步模式兩個通道使用同一個觸發(fā)源。這可以確保兩個通道的輸出更新嚴(yán)格同步對于需要生成差分信號或XY坐標(biāo)信號的應(yīng)用至關(guān)重要。配置時只需將兩個通道的DAC_Trigger設(shè)置為同一個定時器TRGO即可。合并模式Dual Mode這是一種特殊模式允許通過一次32位數(shù)據(jù)寫入同時更新兩個通道的12位輸出值。HAL庫提供了HAL_DACEx_DualSetValue函數(shù)。這可以減少軟件開銷并確保兩個通道更新的時間差極小。注意使用此模式時數(shù)據(jù)對齊方式有特殊要求需要仔細(xì)閱讀參考手冊和HAL庫函數(shù)注釋。避坑指南功耗與干擾同時使能兩個DAC通道會增加功耗。如果兩個通道輸出頻率相差很大高頻通道可能會通過電源耦合干擾低頻通道。在PCB布局時兩個DAC輸出引腳應(yīng)適當(dāng)隔離并確保模擬電源濾波良好。同步模式下的數(shù)據(jù)管理如果兩個通道都使用DMA你需要為每個通道配置獨(dú)立的DMA流但它們可以被同一個定時器觸發(fā)。要確保兩個波形數(shù)據(jù)數(shù)組在內(nèi)存中的訪問不會沖突。4. 性能優(yōu)化與高級技巧4.1 提升輸出精度與穩(wěn)定性的硬件考量DAC的性能天花板很大程度上由硬件決定。以下是在設(shè)計階段就必須考慮的事項(xiàng)參考電壓源VDDA這是最重要的因素。理想情況下應(yīng)使用獨(dú)立的低壓差線性穩(wěn)壓器LDO為VDDA供電并與數(shù)字電源VDD隔離。在VDDA和VSSA引腳附近必須放置一個10uF的鉭電容或電解電容進(jìn)行低頻去耦再并聯(lián)一個100nF和1nF的陶瓷電容進(jìn)行高頻去耦且布局應(yīng)盡可能靠近芯片引腳。PCB布局布線DAC的模擬輸出走線應(yīng)遠(yuǎn)離任何數(shù)字信號線特別是高頻的時鐘線和PWM線。如果空間允許用地線將模擬走線包圍起來進(jìn)行隔離。避免在DAC輸出走線下方或相鄰層走數(shù)字信號線。輸出緩沖與濾波如前所述禁用片內(nèi)緩沖器可以提高線性度。但此時輸出阻抗很高典型值幾十kΩ必須連接一個高輸入阻抗的負(fù)載如運(yùn)放電壓跟隨器。在輸出端串聯(lián)一個小的電阻如50-100Ω再對地接一個電容可以形成一個簡單的RC低通濾波器有效濾除從DAC內(nèi)部或PCB耦合進(jìn)來的高頻噪聲。濾波器的截止頻率f1/(2πRC)應(yīng)高于你需要的信號頻率以免造成信號衰減。4.2 軟件層面的優(yōu)化策略在硬件確定的基礎(chǔ)上軟件優(yōu)化能進(jìn)一步提升性能減少中斷延遲在DMA傳輸波形數(shù)據(jù)的應(yīng)用中避免在DMA傳輸完成中斷或定時器觸發(fā)中斷中執(zhí)行冗長的操作。保持中斷服務(wù)函數(shù)盡可能短小。如果需要在每個采樣點(diǎn)進(jìn)行計算可以考慮使用定時器中斷但需評估CPU負(fù)載是否可接受。使用內(nèi)存到DAC的直接傳輸對于極高速率的需求可以探索使用DMA的“雙緩沖”模式或“內(nèi)存到內(nèi)存”模式預(yù)先處理數(shù)據(jù)然后以最高優(yōu)先級觸發(fā)一次到DAC的傳輸。但這屬于高級技巧需要對DMA控制器有深入理解。校準(zhǔn)STM32的DAC出廠時有一定誤差。如果項(xiàng)目對絕對精度要求很高例如優(yōu)于1%可以進(jìn)行簡單的兩點(diǎn)校準(zhǔn)。測量DAC輸出為某個低值如對應(yīng)0.5V和某個高值如對應(yīng)2.5V時的實(shí)際電壓通過線性擬合計算出增益和偏移誤差在軟件中進(jìn)行補(bǔ)償。公式為Corrected_Code (Original_Code * Gain_Factor) Offset。4.3 低功耗應(yīng)用下的DAC配置在電池供電設(shè)備中需要關(guān)注DAC的功耗。動態(tài)關(guān)閉當(dāng)不需要DAC輸出時及時調(diào)用HAL_DAC_Stop()或HAL_DAC_Stop_DMA()來關(guān)閉DAC通道和可能關(guān)聯(lián)的DMA。在停止?fàn)顟B(tài)下DAC的功耗可以降到極低。輸出緩沖器功耗片內(nèi)輸出緩沖器本身會消耗一定的靜態(tài)電流。如果禁用緩沖器能滿足驅(qū)動要求這將直接降低功耗。觸發(fā)頻率與功耗DAC在每次被觸發(fā)無論是軟件還是硬件進(jìn)行數(shù)據(jù)更新時都會有一個動態(tài)功耗。在滿足性能要求的前提下降低觸發(fā)頻率即輸出更新率有助于節(jié)省電能。5. 調(diào)試技巧與常見問題排查實(shí)錄調(diào)試DAC光看代碼是不夠的必須借助工具觀察實(shí)際輸出。5.1 必備工具與觀測方法數(shù)字萬用表用于測量靜態(tài)直流電壓驗(yàn)證基礎(chǔ)輸出是否正確檢查VDDA電壓。示波器這是調(diào)試動態(tài)波形最重要的工具。用它可以看到輸出的實(shí)際波形、噪聲、建立時間、毛刺等。觀察噪聲將示波器探頭打到交流耦合AC coupling垂直刻度調(diào)到最小如1mV/div可以清晰地看到輸出上的噪聲幅度和頻率成分。測量建立時間輸出一個階躍信號如從0V跳變到滿量程使用示波器的上升時間測量功能看輸出電壓達(dá)到最終值特定誤差帶如0.1%所需的時間是否與數(shù)據(jù)手冊相符。邏輯分析儀可以同步抓取觸發(fā)DAC的定時器信號、DMA請求信號等幫助分析時序問題。5.2 常見問題速查表現(xiàn)象可能原因排查步驟與解決方案無輸出或輸出為01. DAC或GPIO時鐘未使能。2. 引腳未配置為模擬模式。3. DAC通道未使能HAL_DAC_Start未調(diào)用。4. 輸出緩沖器禁用且負(fù)載阻抗太低。1. 檢查__HAL_RCC_DAC1_CLK_ENABLE()和GPIO時鐘。2. 檢查CubeMX或代碼中引腳配置是否為“Analog”。3. 確保初始化后調(diào)用了啟動函數(shù)。4. 測量輸出引腳對地電阻確認(rèn)負(fù)載是否為高阻抗100kΩ或增加電壓跟隨器。輸出電壓值不正確1. VDDA實(shí)際電壓與計算值不符。2. 數(shù)據(jù)對齊方式錯誤。3. 輸出緩沖器使能導(dǎo)致接近0V/VDDA時輸出不準(zhǔn)。4. 寫入的數(shù)據(jù)值計算錯誤。1. 用萬用表實(shí)測VDDA引腳電壓。2. 檢查HAL_DAC_SetValue或DMA配置中的對齊參數(shù)。3. 嘗試禁用輸出緩沖器或避免使用極限電壓值。4. 重新核對電壓-數(shù)字值轉(zhuǎn)換公式。輸出波形有臺階、不光滑1. 波形數(shù)據(jù)表點(diǎn)數(shù)太少。2. DAC更新率采樣率不夠高低于奈奎斯特頻率。3. 后級電路帶寬不足無法響應(yīng)高頻變化。1. 增加波形數(shù)組的長度如從64點(diǎn)增加到256點(diǎn)。2. 提高定時器觸發(fā)頻率確保采樣率 2倍 * 波形最高頻率建議10倍以上。3. 在輸出端增加RC低通濾波器但截止頻率要高于信號頻率。波形中有周期性毛刺或抖動1. 定時器觸發(fā)中斷被更高優(yōu)先級中斷打斷。2. DMA傳輸過程中被其他總線主設(shè)備如另一個DMA或CPU搶占導(dǎo)致數(shù)據(jù)供應(yīng)不及時。3. 電源噪聲耦合。1. 調(diào)整中斷優(yōu)先級確保DAC相關(guān)中斷定時器、DMA有足夠高的優(yōu)先級。2. 檢查DMA流優(yōu)先級或優(yōu)化內(nèi)存訪問使用TCM內(nèi)存避免緩存。3. 用示波器AC耦合觀察電源引腳加強(qiáng)電源濾波。DMA傳輸一次后停止1. DMA未配置為循環(huán)模式Circular。2. DMA傳輸完成中斷中錯誤地停止了DMA或DAC。1. 在CubeMX或初始化代碼中將DMA模式設(shè)置為“Circular”。2. 檢查中斷服務(wù)函數(shù)確保沒有調(diào)用HAL_DAC_Stop_DMA。使用雙通道不同步1. 兩個通道使用了不同的觸發(fā)源。2. 兩個通道的DMA或軟件更新時間有差異。1. 將兩個通道的觸發(fā)源配置為同一個硬件觸發(fā)源如同一個定時器的TRGO。2. 對于軟件更新確保在同一個高優(yōu)先級中斷或任務(wù)中更新兩個通道的值。考慮使用“合并模式”一次寫入。5.3 一個真實(shí)的調(diào)試案例音頻輸出中的“咔嗒”聲我曾在一個使用DACDMA播放WAV音頻的項(xiàng)目中遇到每次開始播放和停止播放時揚(yáng)聲器都會發(fā)出“咔嗒”聲的問題。排查過程觀察現(xiàn)象用示波器觀察DAC輸出發(fā)現(xiàn)播放開始時輸出會瞬間跳變到一個非零電壓可能是DAC數(shù)據(jù)寄存器的殘留值或默認(rèn)值然后才開始正常的波形數(shù)據(jù)。停止時輸出會瞬間跳變到0V。分析原因DAC在啟動DMA前其輸出寄存器DOR可能處于不確定狀態(tài)。HAL_DAC_Start_DMA函數(shù)啟動DMA傳輸需要一點(diǎn)時間在這期間DAC可能已經(jīng)使能并輸出了某個舊值。同樣停止時DAC在DMA停止后立即關(guān)閉輸出歸零這個跳變被后級放大電路放大產(chǎn)生了沖擊噪聲。解決方案啟動消隱在啟動DMA傳輸之前先調(diào)用HAL_DAC_SetValue將DAC輸出設(shè)置為一個中間值如0V對應(yīng)的數(shù)字值。然后啟動DAC通道HAL_DAC_Start此時輸出為中間值。最后再啟動DMAHAL_DAC_Start_DMADMA會立即用波形數(shù)組的第一個值更新輸出這個變化是平滑的。停止淡出在停止播放時不要立刻調(diào)用HAL_DAC_Stop_DMA和HAL_DAC_Stop。可以先將DMA傳輸?shù)臄?shù)據(jù)源切換到一個內(nèi)容全為中間值0V的小數(shù)組讓DMA再循環(huán)幾次將輸出“拉回”到零點(diǎn)然后再停止DAC。更復(fù)雜的實(shí)現(xiàn)是做一個軟件的音量淡出逐漸減小DMA傳輸?shù)臄?shù)據(jù)值最后再停止硬件。這個案例說明HAL庫提供了正確的硬件操作順序但為了實(shí)現(xiàn)更好的用戶體驗(yàn)我們需要在它的基礎(chǔ)上根據(jù)具體的應(yīng)用場景增加一些“軟”性的控制邏輯。