議詳解:從時序原理到調(diào)試實戰(zhàn))
1. 項目概述1.1 為什么嵌入式開發(fā)繞不開I2S如果你做過音頻相關(guān)的嵌入式開發(fā)不管是用單片機驅(qū)動一個簡單的語音播放模塊還是在應(yīng)用處理器上接一顆高性能音頻Codec遲早會碰上I2S這個名字。第一次接觸的人容易被它和I2C搞混——就差一個字母但完全是兩回事。I2C是低速控制總線用來讀寫寄存器、掛傳感器I2S是音頻數(shù)據(jù)總線專門用來傳輸數(shù)字音頻流。我最早做音頻項目時就在I2S的時序配對上卡了整整一個下午那個印象太深了所以決定把這篇文章寫出來把I2S協(xié)議的家底一次性講清楚。簡單來說I2S全稱是Inter-IC Sound Bus也叫Integrated Interchip Sound是飛利浦在1986年提出的一種數(shù)字音頻設(shè)備之間的總線標(biāo)準(zhǔn)。它解決的問題非常純粹讓兩個芯片之間能穩(wěn)定、同步地傳輸連續(xù)的PCM音頻數(shù)據(jù)。幾乎所有你能想到的音頻芯片都支持I2S接口——Codec、DAC、ADC、DSP、藍牙音頻模塊、HDMI音頻提取板甚至高檔CD轉(zhuǎn)盤內(nèi)部也都是I2S在跑。這篇博文寫給誰剛接觸音頻協(xié)議的嵌入式新手被MCLK、BCLK、WS、DATA四根線繞暈的工程師以及想自己動手改裝或調(diào)試I2S信號硬件的發(fā)燒友。1.2 I2S在整條音頻鏈路里的位置要理解I2S的作用你得先看清楚它在音頻系統(tǒng)里扮演的角色。一個完整的數(shù)字音頻鏈路通常分三段源頭是音頻數(shù)據(jù)中間是傳輸/處理末端是回放或采集。I2S干的是中間那段。舉個例子你手機里存著一首44.1kHz、16bit的WAV文件CPU從存儲讀出數(shù)據(jù)后需要把這些數(shù)字信號送到DAC芯片去轉(zhuǎn)成模擬電壓DAC才能推動耳機發(fā)聲。CPU和DAC之間傳遞PCM數(shù)據(jù)走的就是I2S。如果源頭不是CPU而是藍牙模塊或數(shù)字麥克風(fēng)情況也類似。藍牙模塊解出音頻數(shù)據(jù)后通過I2S把數(shù)據(jù)喂給后級的DAC或功放數(shù)字麥克風(fēng)則直接把采集到的PCM數(shù)據(jù)按幀輸出到I2S總線上。總之I2S負責(zé)在“產(chǎn)生PCM數(shù)據(jù)的一端”和“消費PCM數(shù)據(jù)的一端”之間建立一座同步的橋梁。沒有它音頻芯片之間就只能靠并行的低速接口慢慢挪效率和實時性都跟不上。注意I2S傳的是純粹的PCM數(shù)字音頻數(shù)據(jù)不負責(zé)音量調(diào)節(jié)、音效處理也不帶任何控制信息。想要控制Codec的寄存器比如AGC、EQ、增益通常還得搭配I2C或SPI接口。這兩者在硬件設(shè)計上經(jīng)常是“控制面”和“數(shù)據(jù)面”的分工關(guān)系。2. 核心細節(jié)解析與實操要點2.1 三根線與第四根線——SCK、WS、SD和MCLKI2S最基本的形態(tài)只有三根線這也是飛利浦原始標(biāo)準(zhǔn)的核心。第一根叫位時鐘有的叫BCLK有的叫SCKSerial Clock還有的寫成BITCLK都是一個東西。它每來一個脈沖就對應(yīng)傳輸一位音頻數(shù)據(jù)。位時鐘的頻率很好算采樣率乘以位深再乘以聲道數(shù)。常見的組合44.1kHz采樣率、16bit、雙聲道立體聲BCLK就是44.1k × 16 × 2 1.4112MHz如果是24bit、192kHz、雙聲道那就是192k × 24 × 2 9.216MHz。這個公式很關(guān)鍵后面配置主控的I2S外設(shè)時全靠它來推算分頻系數(shù)。第二根叫幀時鐘又叫WSWord Select、LRCLK它是整個I2S的“指揮棒”。WS拉高表示當(dāng)前在傳右聲道的數(shù)據(jù)拉低表示在傳左聲道的數(shù)據(jù)WS翻轉(zhuǎn)一次就代表完成了一個采樣點。所以在常見的雙聲道配置下WS的頻率就等于采樣率本身44.1kHz的音頻WS就是44.1kHz的方波。這也意味著WS從低到高再回到低完成一個周期的時間內(nèi)總共傳了64個BCLK周期在16bit雙聲道配置下而實際有用的數(shù)據(jù)位只有32個剩下的一半是BCLK“閑置”的。這是初學(xué)I2S最容易忽略的地方——BCLK可以比“數(shù)據(jù)位寬×聲道數(shù)”跑得更快幀的邊界由WS決定而不是由BCLK個數(shù)決定。第三根是數(shù)據(jù)線叫SDSerial Data有的芯片叫DOUT、DIN、SDA方向取決于你是發(fā)送方還是接收方。發(fā)送端在BCLK的上升沿把數(shù)據(jù)一位一位擺到SD上接收端在BCLK的下降沿去采樣這樣雙端都在同一個邊沿動作就不會產(chǎn)生競爭。這是I2S有別于很多同步串行協(xié)議的地方——它不是用上升沿發(fā)、上升沿收而是發(fā)送和接收錯開了半個周期。這個小細節(jié)決定了信號能在較長的PCB走線上保持穩(wěn)定。第四根線MCLK也叫主時鐘是很多人最容易忽略、偏偏也是最容易讓人栽跟頭的一根線。MCLK的用途是給Codec內(nèi)部的Δ-Σ調(diào)制器和數(shù)字濾波器提供一個高頻參考時鐘一般是采樣率的整數(shù)倍常見的是256×fs或512×fs。比如44.1kHz采樣率配256倍MCLK就是11.2896MHz。如果你的主控I2S外設(shè)沒有獨立的MCLK輸出引腳那接Codec時就得想辦法從外部晶振或主控的定時器/PWM借一個主時鐘過去。很多入門級MCU只有三根I2S線這會導(dǎo)致某些Codec芯片尤其是中高端的比如CS4398、ES9038這類沒法正常工作——它們對MCLK有硬性要求。提醒MCLK不便宜很多低端方案為了省成本會直接用BCLK給Codec當(dāng)MCLK用或者用BCLK的兩倍頻。這種做法在低采樣率、低位數(shù)場景可能能跑通但在高采樣率、高保真場景下效果會很差失真大、底噪高。如果你要追求音質(zhì)MCLK該給就給別省。2.2 四種信號格式除了標(biāo)準(zhǔn)I2S還有左對齊、右對齊和DSP純粹的飛利浦I2S幀格式是WS變化沿先來緊接著延遲一個BCLK周期后數(shù)據(jù)最高位MSB才出現(xiàn)在SD上。也就是說數(shù)據(jù)位相對于WS翻轉(zhuǎn)沿存在一個BCLK的“偏移”。這個特性非常關(guān)鍵決定了主控和Codec能不能正確對齊數(shù)據(jù)。但實際應(yīng)用中你會發(fā)現(xiàn)滿世界不止這原始的一種格式。最常見的有四種標(biāo)準(zhǔn)I2SPhilips格式數(shù)據(jù)在WS翻轉(zhuǎn)后的下一個BCLK上升沿開始輸出MSB先行。左對齊Left Justified數(shù)據(jù)在WS翻轉(zhuǎn)的同時立刻輸出MSB沒有那一個BCLK的延遲。因為MSB對齊到幀起點所以叫“左對齊”。右對齊/日立格式Right Justified數(shù)據(jù)的LSB貼住幀的結(jié)尾也就是說數(shù)據(jù)在幀內(nèi)是“靠右”的。這種格式常見于一些日本廠商的老Codec芯片它要求接收端知道數(shù)據(jù)位寬是多少、才能算準(zhǔn)MSB從哪個時鐘開始。DSP/PCM格式連續(xù)發(fā)送的多通道數(shù)據(jù)流早期用于DSP之間互傳多聲道數(shù)據(jù)現(xiàn)在在一些TDM多通道Codec上也常見。這里面最坑的就是“標(biāo)準(zhǔn)I2S的1-BCLK延遲”和“右對齊格式對位寬的強依賴”。我遇到過一塊Codec它的主控默認(rèn)配置成了左對齊結(jié)果放出來的聲音像是機器人在說話全是高頻毛刺。最后把數(shù)據(jù)手冊逐行看了一遍才發(fā)現(xiàn)這顆芯片在I2S模式之外還分了一個Left-Justified模式數(shù)據(jù)時序差一個時鐘就全亂了。再看接收端的采樣點。以16bit數(shù)據(jù)、24BCLK幀長度為例標(biāo)準(zhǔn)I2S模式下發(fā)送端在BCLK上升沿移出數(shù)據(jù)接收端在BCLK下降沿采樣。由于數(shù)據(jù)比WS晚了一個時鐘接收端如果想在下降沿采樣等效于它在數(shù)據(jù)穩(wěn)定后的后半段去讀取剛好躲開了數(shù)據(jù)的跳變區(qū)。這樣的時序設(shè)計非常適合長距離板內(nèi)走線。2.3 位深與數(shù)據(jù)長度的坑——16bit、24bit、32bit容器I2S本身不關(guān)心數(shù)據(jù)位深它只負責(zé)按BCLK一個個地搬移比特。但你的Codec和主控總得商量好“每幀里到底有多少位有效數(shù)據(jù)”。這就是一個巨大的坑BCLK的周期數(shù)可以大于實際的數(shù)據(jù)位寬。舉個例子某Codec支持32bit的BCLK/WS幀但實際有效數(shù)據(jù)只有24bit剩下的8bit是什么可能是補零也可能是填充狀態(tài)信息。如果你做主控時把“幀長度”配置成16bit而Codec按32bit來解析幀那數(shù)據(jù)就會錯位——你可能聽到的是完全無法分辨的噪聲。配置I2S外設(shè)時有幾個參數(shù)是必須明確的幀長度每幀多少個BCLK、數(shù)據(jù)位寬有效音頻數(shù)據(jù)多少位、以及數(shù)據(jù)在幀內(nèi)的對齊位置MSB先還是LSB先、延遲幾個時鐘。這些參數(shù)錯一個輕則音量小或噪聲重則完全無聲。很多現(xiàn)代Codec支持“自動檢測”主控給出的幀長但那是建立在主控給出的BCLK必須和幀長匹配的前提下。如果BCLK的數(shù)量和Codec預(yù)期的不一致檢測機制也會失效。成熟的驅(qū)動工程師會把主控側(cè)和Codec側(cè)兩側(cè)的寄存器配置放在同一張表里核對逐項比對幀長、位寬、是否帶MCLK、分頻系數(shù)。3. 實操過程與核心環(huán)節(jié)實現(xiàn)3.1 主從模式理解與接線實戰(zhàn)I2S系統(tǒng)和I2C一樣分主從但音頻總線的“主”通常指的是產(chǎn)生BCLK和WS的一方。常見的有兩種典型架構(gòu)。第一種是主控做主機Codec做從機。主控產(chǎn)生BCLK、WS、MCLKCodec被動接收時鐘、輸出/接收數(shù)據(jù)。這種模式最簡單適合MCU和Codec之間直接通信。接線也直觀主控的I2S_TX接Codec的DINCodec的DOUT接主控的I2S_RXBCLK、WS、MCLK并接。第二種是Codec做主機主控做從機。典型的應(yīng)用是音頻子卡、或者帶獨立晶振的高精度DAC。Codec自己掛一顆高精度晶振自己產(chǎn)生所有時鐘主控只負責(zé)在WS的邊沿上同步收發(fā)數(shù)據(jù)。這種方案的優(yōu)勢是時鐘抖動更低音質(zhì)更好因為Codec的時鐘源離DAC核心更近缺點是主控的I2S外設(shè)必須支持從機模式而且WS和BCLK都來自外部調(diào)試時必須讓主控側(cè)先鎖定外部時鐘稍有不對就會失步。接線時有個高頻易錯點MCLK的走線盡量短、盡量粗別跟BCLK走得太近避免串?dāng)_。在雙面板上我習(xí)慣給I2S的幾根線都加地孔圍籠尤其MCLK和BCLK之間至少隔一個地走線。別覺得這是玄學(xué)音頻Codec對時鐘質(zhì)量極其敏感板子上BCLK的過沖會直接反映在DAC輸出的底噪上。3.2 時鐘配置的計算方法配置I2S時鐘是唯一繞不開的數(shù)學(xué)環(huán)節(jié)。以STM32F4系列為例它的I2S外設(shè)通常掛在I2S2/I2S3上時鐘源可以選PLLI2S或者系統(tǒng)時鐘直出。PLLI2S的輸出頻率設(shè)計成256×fs的整數(shù)倍后再經(jīng)過I2S外設(shè)的分頻器得到BCLK和WS。實際算一下目標(biāo)采樣率fs48kHzCodec要求MCLK256×fs。那么MCLK頻率48k × 256 12.288MHzBCLK頻率48k × 32 × 2 3.072MHz按每幀32bit、雙聲道算I2S外設(shè)分頻比12.288MHz / 3.072MHz 4也就是BCLK MCLK/4如果你的主控PLL輸出正好是12.288MHz那就完美直接掛上。如果不能整出12.288MHz選一個接近的頻率但要注意Codec對MCLK頻率的容忍范圍一般高端Codec要求MCLK的誤差在±50ppm低端一些的在±200ppm。超過范圍DAC內(nèi)部的數(shù)字濾波器會表現(xiàn)出嚴(yán)重的時鐘抖動反映在聽感上就是聲音發(fā)飄、高頻毛糙。ES9038Q2M這顆DAC在I2S模式下MCLK必須是BCLK的整數(shù)倍我試過給它配64×fs3.072MHz也能出聲音但失真明顯高于256×fs。所以我的建議是如果你不確定優(yōu)先選256×fs如果Codec手冊里寫了128/384/512等模式再根據(jù)主控PLL的能力靈活調(diào)整追求音質(zhì)就上512×fs但前提是主控能干凈地輸出高頻時鐘。3.3 一套可復(fù)用的I2S配置流程配置I2S外設(shè)我一般按下面的順序來少走很多彎路先查Codec數(shù)據(jù)手冊確認(rèn)目標(biāo)采樣率、位深、MCLK倍頻、I2S格式標(biāo)準(zhǔn)還是左對齊。算BCLK fs × 位深 × 聲道數(shù)再用推薦的MCLK倍頻算出MCLK目標(biāo)頻率。配置主控PLL讓MCLK盡量精確誤差在可接受范圍內(nèi)。配置I2S外設(shè)數(shù)據(jù)位寬、幀長、主從模式、極性一般標(biāo)準(zhǔn)I2S是上升沿發(fā)送下降沿接收。先把MCLK和BCLK用示波器量出來確認(rèn)頻率正確、波形干凈再接上Codec。使能DMA或中斷收發(fā)先傳一段已知的靜音數(shù)據(jù)用邏輯分析儀抓SD線看幀邊界是否和數(shù)據(jù)手冊一致。最后才接Codec的I2C控制口配置Codec的內(nèi)部寄存器如輸入選擇、音量、DAC使能然后播測試音頻。這套流程里第5步和第6步是最容易省、但最不該省的。很多人直接燒錄程序聽聲音聽到噪聲就開始懷疑Codec芯片壞了其實多半是I2S時序參數(shù)沒對齊。先把波形量出來再用邏輯分析儀看幀結(jié)構(gòu)基本能定位九成問題。我實際測試時用邏輯分析儀抓過一塊損壞的Codec——SD線上有數(shù)據(jù)但WS頻率完全亂了最后發(fā)現(xiàn)是主控在從機模式下沒鎖定外部BCLK導(dǎo)致內(nèi)部FIFO溢出。這種問題聽是聽不出來的只有抓波形才看得到。3.4 從零配置一個I2S播放器的關(guān)鍵代碼片段下面給一個STM32 WM8960 Codec的例子。WM8960是顆很常見的低功耗Codec支持I2S和左對齊模式MCLK可以用256×fs。假設(shè)fs44.1kHz位深16bit雙聲道MCLK 256 × 44100 11.2896MHzBCLK 16 × 2 × 44100 1.4112MHz分頻比11.2896 / 1.4112 8STM32F407的PLLI2S配置目標(biāo)是11.2896MHz。I2S2外設(shè)開啟配置為主機、標(biāo)準(zhǔn)I2S、16bit數(shù)據(jù)幀長使用DMA發(fā)送。// 1. 配置PLLI2S輸出 11.2896MHz RCC_PLLI2SConfig(258, 0, 43); // 經(jīng)過計算得到分頻系數(shù) // 2. 使能I2S外設(shè)時鐘 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2S2, ENABLE); // 3. 設(shè)置I2S2為主機、標(biāo)準(zhǔn)模式、16bit I2S_InitTypeDef I2S_InitStructure; I2S_InitStructure.I2S_Mode I2S_Mode_MasterTx; I2S_InitStructure.I2S_Standard I2S_Standard_Phillips; I2S_InitStructure.I2S_DataFormat I2S_DataFormat_16b; I2S_InitStructure.I2S_MCLKOutput I2S_MCLKOutput_Enable; I2S_InitStructure.I2S_AudioFreq I2S_AudioFreq_44k; I2S_InitStructure.I2S_CPOL I2S_CPOL_Low; I2S_Init(I2S2, I2S_InitStructure); // 4. 配置DMA發(fā)送 DMA_InitTypeDef DMA_InitStructure; DMA_InitStructure.DMA_Channel DMA_Channel_0; DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)I2S2-DR; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)audio_buffer; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralDST; DMA_InitStructure.DMA_BufferSize BUFFER_SIZE; DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_HalfWord; DMA_Init(DMA1_Stream4, DMA_InitStructure); // 5. 使能I2S和DMA I2S_Cmd(I2S2, ENABLE); DMA_Cmd(DMA1_Stream4, ENABLE);這段代碼里I2S_CPOL_Low是標(biāo)準(zhǔn)I2S的時鐘極性選擇I2S外設(shè)在這里約定在BCLK的低電平期間發(fā)送數(shù)據(jù)在BCLK的邊沿采樣。如果你換成Left-Justified模式記得改I2S_Standard同時把數(shù)據(jù)幀對齊方式一并確認(rèn)STM32的HAL庫在這些細節(jié)上封裝得比較隱性一定要對照參考手冊。3.5 不同芯片的I2S接口異同不是所有芯片的I2S都長得一模一樣到了實際項目里你會見到各種變體全雙工I2S有獨立的TX和RX數(shù)據(jù)線可以同時收發(fā)典型是STM32的I2S外設(shè)。半雙工I2S只有一根SD線時分復(fù)用做收發(fā)。有些低功耗藍牙芯片為了省引腳用半雙工。TDM多通道模式BCLK和WS不變但一個WS周期里塞進了4路、8路甚至16路數(shù)據(jù)常見于多聲道Codec如TAS5754、陣列麥克風(fēng)如AC108。I2S over HDMIHDMI音頻提取板上用I2S把多通道LPCM音頻導(dǎo)出來本質(zhì)還是I2S只是數(shù)據(jù)流的組織方式和普通立體聲略有不同。PCM接口很多人把它和I2S混為一談其實PCM接口如Qualcomm的PCM接口通常以短幀同步信號SYNC代替WS幀長可以是16bit或32bit數(shù)據(jù)位可以在128fs、256fs等時鐘下跑本質(zhì)上也是一種音頻串行總線但時序和I2S有細節(jié)差異。做兼容性設(shè)計時我的經(jīng)驗是把I2S外設(shè)的極性、幀長、數(shù)據(jù)位寬都做成可配置項不要寫死任何一個參數(shù)。你永遠不知道下一塊Codec喜歡什么格式。比如某國產(chǎn)Codec默認(rèn)就是24bit/32bit幀不改參數(shù)根本不出聲。4. 常見問題與排查技巧實錄4.1 問題速查表現(xiàn)象可能原因排查方法完全無聲MCLK沒配置或頻率錯誤示波器量MCLK確認(rèn)是否等于Codec要求的fs倍數(shù)完全無聲I2S數(shù)據(jù)方向接反核對TX/RX方向主控TX接Codec DIN主控RX接Codec DOUT有噪聲/爆音BCLK和WS極性不對檢查I2S外設(shè)的CPOL極性設(shè)置調(diào)反試試聲音變調(diào)采樣率配置錯誤示波器量WS頻率確認(rèn)等于目標(biāo)fs音量異常低位深錯位高bit被當(dāng)成低bit用邏輯分析儀抓幀核對MSB對齊位置左右聲道互換WS極性可能與預(yù)期相反嘗試把WS的級性取反或檢查左右聲道映射寄存器間歇性雜音DMA緩沖下溢/溢出調(diào)整DMA緩沖區(qū)大小或中斷優(yōu)先級聲音高頻失真MCLK不是fs的整數(shù)倍重新計算PLL分頻確保MCLK fs × 整數(shù)4.2 調(diào)試手法與工具體會I2S調(diào)試示波器和邏輯分析儀是兩件法寶。示波器用于量頻域和波形質(zhì)量MCLK的抖動、BCLK的過沖、WS的上升沿是否干凈。邏輯分析儀則用于看時序邏輯數(shù)一下一個WS周期內(nèi)有多少個BCLK、MSB是否在預(yù)期位置、數(shù)據(jù)是否連續(xù)。我踩過的最深的坑是I2S外設(shè)的DMA配置看起來全對程序也沒報錯但就是不出聲。后來用邏輯分析儀抓了SD線發(fā)現(xiàn)SD線上根本沒有任何翻轉(zhuǎn)DMA沒把數(shù)據(jù)送到外設(shè)。最后定位到問題是DMA和外設(shè)的時鐘使能順序?qū)懛戳讼乳_了I2S再開DMA外設(shè)的FIFO沒有準(zhǔn)備好。這類問題在參考手冊上根本不會寫只能靠經(jīng)驗。另一個高頻問題GPIO復(fù)用功能沒配置。很多MCU的I2S引腳是復(fù)用功能引腳如果你只開了外設(shè)時鐘、忘了配置引腳的AFAlternate Function那BCLK和WS永遠輸不出來。我建議大家寫好配置后第一件事就是量主控引腳的BCLK和MCLK有波形再繼續(xù)往下調(diào)。4.3 發(fā)燒友改裝場景天籟CD機I2S飛線熱詞里出現(xiàn)了“天籟CD機I2S飛線改裝”這屬于發(fā)燒友圈子里比較經(jīng)典的玩法。老款CD機/DVD機里通常有一顆DSP或伺服芯片內(nèi)部有I2S信號但PCB上不一定預(yù)留出測試點。愛好者會找到芯片手冊確認(rèn)I2S引腳位置然后用漆包線直接把I2S信號引到外置DAC的I2S輸入跳過機內(nèi)劣質(zhì)的模擬輸出電路達到提升音質(zhì)的目的。這個玩法技術(shù)上可行但風(fēng)險也不小一根飛線動輒幾厘米I2S的BCLK動輒幾MHz長線會引入串?dāng)_和反射飛線焊點松了會導(dǎo)致雜音甚至短路。我的建議是如果你真想玩飛線優(yōu)先找3.3V邏輯的芯片、最短路徑引出每根I2S線外面套上屏蔽地線而且最好直接從主控芯片引腳引不要從過孔或焊盤上擠。改裝前先抓一下原始I2S信號確認(rèn)有信號再動手。很多DIY失敗不是DAC不行而是I2S信號在飛線上已經(jīng)爛得沒法看了。4.4 I2S與AHB、AXI總線的關(guān)系澄清熱詞里還有AHB總線協(xié)議和AXI4總線協(xié)議這里順便澄清一下避免初學(xué)者混淆。AHB、AXI是芯片內(nèi)部的片上總線協(xié)議是SoC內(nèi)部的“高速公路”負責(zé)連接CPU、內(nèi)存、外設(shè)控制器。I2S是芯片對外的串行音頻接口協(xié)議屬于“外設(shè)功能”。兩者之間關(guān)系是I2S外設(shè)控制器掛在AHB/AXI總線上CPU通過AHB/AXI訪問I2S的寄存器、讀寫FIFO但I2S接口信號本身毫不知曉AXI的存在。你只需要知道配置I2S外設(shè)時總線時鐘的開關(guān)和復(fù)位控制通常是由總線管理器來做的調(diào)試時如果I2S外設(shè)時鐘沒開量到的引腳全是低電平十有八九就是總線側(cè)時鐘沒使能。5. 實操經(jīng)驗補充與深入思考5.1 從波形讀懂I2S時序初學(xué)I2S時最需要訓(xùn)練的能力就是看波形。你可以把一根探針夾在BCLK上另一根夾在WS上用示波器的余暉模式觀察。一個正常的44.1kHz/16bit音頻流BCLK是1.4112MHz的方波WS是44.1kHz的方波兩者頻率比值剛好是3216bit × 2聲道。如果比值不是整數(shù)幀結(jié)構(gòu)一定有問題。再看SD線和WS的相位關(guān)系標(biāo)準(zhǔn)I2S模式下WS翻轉(zhuǎn)后SD要等下一個BCLK上升沿才出現(xiàn)MSB。你用示波器同時看這三根線時會發(fā)現(xiàn)SD的第一個數(shù)據(jù)位落后WS一個時鐘。如果能清楚地看到這個“延遲一位”的現(xiàn)象說明I2S時序大概率是對的。如果SD和WS同時翻轉(zhuǎn)那是Left-Justified模式不是標(biāo)準(zhǔn)I2S。5.2 I2S線上的信號完整性與PCB布局建議I2S不是高速差分信號但它在音頻場景里對時鐘質(zhì)量的要求接近“玄學(xué)”級別。PCB布局時建議遵循幾個原則所有I2S線盡量短而直最好不要跨島走線跨過不同的地平面。BCKL和WS之間留出間距至少2-3倍線寬如果空間允許用GND包地。MCLK單獨走別和I2S數(shù)據(jù)線平行長距離走。MCLK是最高頻的信號11.2896MHz以上對串?dāng)_最敏感。電阻匹配很多方案會在MCLK和BCLK串33Ω或47Ω的電阻既能限流又能抑制振鈴實測能降低一些EMI。如果你在Codec端看到BCLK有過沖超過VCC0.3V的波形大概率是阻抗失配串個小電阻往往立竿見影。音頻系統(tǒng)里“聲道分離度差”這種問題很多就是I2S線之間的串?dāng)_造成的適當(dāng)拉開距離或包地就能改善。5.3 從I2S到系統(tǒng)——音頻時鐘樹設(shè)計I2S配置說到底是在一個時鐘樹里做“頻率搬運工”。完整的音頻時鐘樹一般包含系統(tǒng)時鐘、PLL、I2S外設(shè)分頻器、Codec內(nèi)部的PLL/分頻器。任何一個環(huán)節(jié)的“臟時鐘”最終都會反映在音頻質(zhì)量上。我的一個經(jīng)驗是如果系統(tǒng)里有獨立的音頻晶振常見的有24.576MHz和22.5792MHz兩種分別對應(yīng)48k和44.1k系列采樣率一定要優(yōu)先用它作為MCLK的源頭而不是復(fù)用系統(tǒng)MCU的PLL輸出。這顆晶振是整個音頻鏈路的“心跳”它干凈后面的數(shù)據(jù)才干凈。很多高保真DAC開發(fā)板會設(shè)計兩顆晶振一顆管44.1kHz家族22.5792MHz一顆管48kHz家族24.576MHz然后根據(jù)播放的采樣率自動切換。這種設(shè)計不是為了炫技而是確保任何采樣率下MCLK都是fs的精確整數(shù)倍。用PLL硬分頻雖然方便但相位噪聲很難和專用晶振比。5.4 I2S之外的選擇PDM、TDM、USB Audio最后聊兩句I2S之外的“隔壁鄰居”。PDM接口在數(shù)字麥克風(fēng)上很常見它的數(shù)據(jù)線只有一根時鐘頻率通常在1MHz到4.8MHz之間通過過采樣噪聲整形輸出1bit數(shù)據(jù)流和I2S的多bit并行完全不同。TDM則是I2S的多通道擴展版本適合做多聲道音頻傳輸。USB Audio則是把音頻數(shù)據(jù)打包成USB packet走USB線纜完全不需要I2S但在主控內(nèi)部從USB controller解出來的PCM數(shù)據(jù)大概率還是要經(jīng)過I2S或I2S-like的接口送到Codec。做系統(tǒng)選型時不要盲目追求I2S有些場景用PDM比如很多麥克風(fēng)陣列更合適有些場景用TDM多聲道音響更省引腳。但在絕大多數(shù)立體聲Codec連接場景中I2S依然是那個最通用、最不容易出錯的選擇。實操心得如果你正在學(xué)習(xí)I2S我強烈建議你準(zhǔn)備一個30塊錢的邏輯分析儀先把主控發(fā)出的I2S波形抓下來對著數(shù)據(jù)手冊數(shù)一遍BCLK、WS、SD的對應(yīng)關(guān)系。看過一次波形、理解了幀結(jié)構(gòu)之后I2S對你來說就不再是抽象協(xié)議了。后面換任何芯片、改任何參數(shù)基于這套對幀結(jié)構(gòu)的直覺都能快速定位問題。這段功夫花得值別省。