簡介
在音頻處理領(lǐng)域,I2S是一種廣泛使用的通信協(xié)議,它專門用于芯片之間的音頻數(shù)據(jù)傳輸。ESP32 作為一款高性能的微控制器,不僅支持 I2S 通信,還提供了強大的硬件接口和靈活的軟件庫,使其成為音頻項目開發(fā)的理想選擇。本篇文章將介紹I2S的相關(guān)知識和使用ESP32驅(qū)動I2S音頻設(shè)備時比較常用的相關(guān)底層API函數(shù)。
I2S即Inter-IC Sound, 簡稱I2S,意思是芯片間音頻總線,它是由飛利浦開發(fā)的一種用于數(shù)字音頻設(shè)備的通信協(xié)議,常用于麥克風(fēng)、揚聲器、音頻處理器等設(shè)備之間的音頻數(shù)據(jù)傳輸。
為什么需要I2S?
傳統(tǒng)的音頻設(shè)備,像模擬電路,傳遞的是電壓信號,這種方式容易受到干擾,比如噪聲或者信號衰減。而數(shù)字音頻需要傳輸數(shù)據(jù),通常是二進制的“0”和“1”,直接用模擬接口傳輸會很麻煩。而 I2S就是為了解決這個問題的一種數(shù)字音頻接口,它讓音頻數(shù)據(jù)的傳輸變得簡單、高效、而且抗干擾能力強。 使用 I2S可以很方便地把數(shù)字音頻信號從一個芯片傳遞到另一個芯片,對于開發(fā)者來講只需要配置好芯片的 I2S 模塊,就可以實現(xiàn)數(shù)字音頻數(shù)據(jù)的傳輸了。
關(guān)于音頻信號
在自然界中音頻信號是以模擬量的形式存在的,它是一種隨時間連續(xù)變化的物理量,為了減少外界的干擾我們需要把它變成數(shù)字量,我們一般可以通過一個模數(shù)轉(zhuǎn)換器把它變成數(shù)字信號(圖1),數(shù)字信號在計算機或數(shù)字設(shè)備中以離散的數(shù)值形式表示和處理,比如用0和1的組合去表示,這里可以了解下PCM編碼,它是一種模擬信號數(shù)字化的方法
當(dāng)然我們也能通過一個數(shù)模轉(zhuǎn)換器把數(shù)字信號還原成模擬信號,以便在揚聲器上播放音頻(圖2)。
這樣音頻信號之間的傳遞就可以通過數(shù)字信號來進行了(圖3),可以減少外界對信號的干擾。
在音頻信號處理和傳輸中,有三個非常重要的參數(shù)決定了音頻質(zhì)量和設(shè)備性能:采樣率、分辨率和 音頻聲道。
采樣率
采樣率就是每秒采集聲音樣本的頻率,這個頻率越快,采樣的數(shù)字信號就越接近原始的聲音的信號,因為采樣的越快,離散數(shù)字曲線每個樣本值之間的過渡就越接近,曲線就會越平滑。這個過程和錄像是類似的,一個是采樣光,一個采樣振動。我們知道錄像其實就是一幀一幀的圖像快速播放,這個采樣速度很快,我們?nèi)庋鄯直娌涣?,看起來就是連續(xù)的。如果錄像時采樣的速度很慢,比如1秒采樣3次,那我們就會丟失掉很多畫面細(xì)節(jié)。采集聲音的時候也是如此,大家可以想象一下,如果采集頻率很慢,聽到的聲音會是什么樣子,會明顯感到聲音聽起來失真不連貫甚至變樣。

每秒鐘采集的音頻樣本數(shù),常見的有8K、16K、44.1K等,采樣率越高,信號還原越精細(xì),一般使用44.1KHz采樣頻率就可以得到比較高保真的聲音。
分辨率
對聲音數(shù)據(jù)采樣后,我們將得到一些離散的樣本點,那我們在一些數(shù)字設(shè)備是如何存儲這些樣本點的呢?我們采樣的數(shù)據(jù)是以二進制的形式存儲的,比如對于每一個采樣點我們用3位二進制來表示(圖4),那么它可以表示的范圍就是2^3=8 即8種量化電平信號(圖5),可以簡單理解為:每個采樣點可以存儲 8種情況的聲音。如果量化位數(shù)越多,根據(jù)我們高中學(xué)過的排列組合知道,得到的樣本值就會越多,那它可以表示自然界聲音的細(xì)節(jié)就越多,或者說能表示的聲音就越豐富。
音頻數(shù)據(jù)的量化位數(shù)或量化深度,常見的有8bit、16bit、24bit、32bit等,位數(shù)越高,信號的動態(tài)范圍和精細(xì)程度越好
音頻聲道
分為單聲道,雙聲道,單聲道是一種只有一個音頻信號通道,所有聲音都合并到一個通道中輸出,無論是通過一個揚聲器還是兩個揚聲器,聽到的聲音是完全相同的。雙聲道分為左聲道和右聲道,具有兩個獨立音頻通道,左聲道和右聲道可以傳遞不同的聲音信號,具有空間感和方向感,也就是我們平常說的立體聲。
怎樣使用I2S傳輸音頻?
使用I2S傳輸音頻的時候,需要用到時鐘信號、控制信號以及數(shù)據(jù)信號(圖6),它們之間是分開傳輸?shù)?。對于?biāo)準(zhǔn)通信模式下的 I2S 總線主要包含以下幾個信號:位時鐘BCLK,字時鐘WS,串行數(shù)據(jù)SD。有的時候還需要MCLK:主時鐘線,該信號線可選,具體取決于從機,主要用于向 I2S 從機提供參考時鐘。
~(注意這幾種信號有幾種其它叫法,這里結(jié)合英文選擇了這幾個名稱,大家只要在使用能區(qū)分就行)~~
位時鐘BCLK
BCLK(Bit Clock,位時鐘)
也叫BCK, SCLK(Serial Clock),對應(yīng)數(shù)字音頻的每一位數(shù)據(jù),是模塊內(nèi)的同步信號BCLK 定義了數(shù)據(jù)傳輸?shù)乃俾剩脕砜刂茢?shù)據(jù)的傳輸節(jié)奏。它的頻率通常是采樣率乘以每個采樣的位數(shù)再乘以聲道數(shù)量。例如,對于 44.1kHz 的采樣率、16 位雙聲道音頻,BCLK 的頻率為 44.1kHz × 16 × 2= 1.4112 MHz。所以對于雙聲道來說,BCLK的頻率=2×采樣頻率×采樣位數(shù)。
字時鐘WS
WS(Word Select , 字選擇時鐘)
也叫 LRCLK (Left Right Clock)即左右聲道時鐘, 用于標(biāo)識當(dāng)前正在傳輸?shù)氖亲舐暤罃?shù)據(jù)還是右聲道數(shù)據(jù)。對于飛利浦公司定義的I2S標(biāo)準(zhǔn),當(dāng) WS 為低電平時表示左聲道,高電平時表示右聲道。一個完整的 WS 信號周期包含兩個聲道的數(shù)據(jù)(左聲道和右聲道)WS 信號的頻率等于音頻的采樣率。
例如,如果音頻采樣率是 44.1kHz,那么 WS 的頻率也是 44.1kHz。
串行數(shù)據(jù)SD
SD(Serial Data,串行數(shù)據(jù))
i2s傳輸時的音頻數(shù)據(jù),是用二進制補碼表示的,具體數(shù)據(jù)傳輸?shù)母袷街饕ǎ篒2S格式,左對齊格式,右對齊格式,每個 BCK 周期會傳輸一位數(shù)據(jù)。數(shù)據(jù)發(fā)送端和接收端會根據(jù) BCK 信號的跳變(上升沿或下降沿)同步數(shù)據(jù)的發(fā)送和接收。當(dāng) WS 為低電平時,SD 傳輸左聲道數(shù)據(jù);當(dāng) WS 為高電平時,SD 傳輸右聲道數(shù)據(jù)。
比如我們傳輸16 位雙聲道音頻,SD數(shù)據(jù)為1 0 1 0 1 1 0 1 1 0 0 0 1 0 0 1 1 1 0 0 1 0 0 1 1 0 0 0 1 0 0 1
它表示
- 每個 BCK 周期傳輸一位音頻數(shù)據(jù)。
- 當(dāng) WS 為低電平時,SD 按位傳輸左聲道的 16 位數(shù)據(jù)1 0 1 0 1 1 0 1 1 0 0 0 1 0 0 1
- 當(dāng) WS 為高電平時,SD 按位傳輸右聲道的 16 位數(shù)據(jù) 1 1 0 0 1 0 0 1 1 0 0 0 1 0 0 1,
個人總結(jié)
字時鐘:高低電平翻轉(zhuǎn),總線在傳輸雙聲道音頻 0為左, 1為右,字時鐘的頻率=采樣率
位時鐘:串行數(shù)據(jù)線的信號會在位時鐘上升沿被采樣,位時鐘的頻率=2×采樣率×采樣位數(shù)。
串行數(shù)據(jù):用二進制補碼表示的音頻數(shù)據(jù),先傳輸高位,再傳輸?shù)臀唬?br /> Tips:字時鐘和位時鐘都是由主機發(fā)送
了解了I2S是如何傳輸后,我們再來看看他的傳輸模型和通信格式。
I2S傳輸模型
I2S通信支持全雙工和半雙工通信,支持主/從模式。主設(shè)備就是發(fā)送時鐘的,從設(shè)備在時鐘的控制下發(fā)送或者接收數(shù)據(jù)。
連接到I2S總線的設(shè)備可以分為兩類:
控制器——控制 SCK 和 WS 信號。
目標(biāo)設(shè)備——接收 SCK 和 WS 信號
總線上只能有一個控制器,但是總線可以有多個目標(biāo)設(shè)備。
音頻設(shè)備,可以分為三類:
發(fā)射器——發(fā)送音頻信號。
接收器——接收音頻信號。
控制器——控制音頻信號
這里我們至少需要一個發(fā)射器和接收器,控制器是可選的,主要用于向 I2S 從機提供參考時鐘
根據(jù)I2S總線誰作為控制器,誰作為目標(biāo)設(shè)備,我們可以有三種I2S傳輸模型:
- 發(fā)射器作為控制器, 接收器作為目標(biāo)設(shè)備
- 發(fā)射器作為目標(biāo)設(shè)備,接收器作為控制器
- 發(fā)射器和接收器都作為目標(biāo)設(shè)備,其他I2S控制器作為控制器
總結(jié):三種經(jīng)典I2S傳輸模型
I2S通信格式
PCM510xA 支持行業(yè)標(biāo)準(zhǔn)的音頻數(shù)據(jù)格式,包括標(biāo)準(zhǔn) I2S 和 左對齊(Left-justified) 格式等。
I2S格式
I2S格式:又稱飛利浦格式(圖7),數(shù)據(jù)最高位總是出現(xiàn)在字時鐘變化后的第二個位時鐘脈沖處(滯后一個位時鐘),這種格式下數(shù)據(jù)MSB的位置是確定的,LSB的位置取決于字長。
左對齊格式
左對齊格式(圖8):數(shù)據(jù)最高位出現(xiàn)在字時鐘變化后的第一個位時鐘脈沖處(無滯后位時鐘)
右對齊格式
右對齊格式:又稱日本格式,這種格式和左對齊差不多,只不過整體是靠右對齊的,即數(shù)據(jù)LSB與WCLK跳變沿對齊。
i2s基本配置
①,i2s的時鐘使能和GPIO口配置 ②,配置為i2s模式
③,i2s標(biāo)準(zhǔn),無論有多少位有效數(shù)據(jù),即數(shù)據(jù)的最高位總是出現(xiàn)在WS變化(也就是一幀開始)后的第2個CK脈沖處。
④,i2s數(shù)據(jù)長度,包括16位,16位擴展(16位數(shù)據(jù)以32位包發(fā)送),24位,32位。 ⑤,設(shè)置i2s時鐘
⑥,設(shè)置i2s空閑狀態(tài)下時鐘電平 ⑦,i2s使能
i2s 底層API
這里我們以ESP32 I2S通信為例,開發(fā)環(huán)境是Arduino IDE,介紹它的相關(guān)底層API,在我們調(diào)庫的時候下面這些函數(shù)會被調(diào)用,我們看一下它的實現(xiàn)過程。
加載I2S驅(qū)動
函數(shù)原型:
esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, int queue_size, void *i2s_queue)
參數(shù)說明::
i2s_port_t i2s_num:指定使用的 I2S 外設(shè)端口。i2s_port_t 是 I2S 外設(shè)端口的枚舉類型,有兩個端口可用:I2S_NUM_0 和 I2S_NUM_1,對應(yīng) ESP32 的第一個和第二個 I2S 外設(shè)。
const i2s_config_t * i2s_config : 設(shè)置I2S 外設(shè)的配置參數(shù)。其中i2s_config_t 是一個結(jié)構(gòu)體,定義了 I2S 外設(shè)的配置選項,這里我們只看常用的配置選項就可以了,主要包括mode、 sample_rate、bits_per_sample等,如下:
int queue_size: 數(shù)據(jù)傳輸?shù)年犃械拇笮oid * i2s_queue:存放和管理 I2S 傳輸?shù)臄?shù)據(jù)。
這個函數(shù)有一個esp_err_t 的返回值,如果返回ESP_OK表示加載I2S驅(qū)動成功。
設(shè)置I2S使用的引腳
函數(shù)原型:
參數(shù)說明:
i2s_port_t i2s_num:指定使用的 I2S 外設(shè)端口,I2S_NUM_0 或I2S_NUM_1。
i2s_pin_config_t * pin:配置I2S接口的各個引腳,i2s_pin_config_t 是一個結(jié)構(gòu)體,里面是關(guān)于I2S引腳,如時鐘引腳,左右聲道選擇引腳,數(shù)據(jù)輸入引腳等引腳的配置。如下:
I2S讀取數(shù)據(jù)
函數(shù)原型:
參數(shù)說明:i2s_port_t i2s_num:I2S_NUM_0 或I2S_NUM_1。
void * dest:讀取目標(biāo)數(shù)據(jù)的緩存區(qū)
size_t size:要讀取的數(shù)據(jù)大小,單位是字節(jié)
size_t * bytes_read:實際讀取到的字節(jié)數(shù)
TickType_t ticks_to_wait:超時等待時間,因為I2S是按一定頻率讀取數(shù)據(jù)的,如果一次傳輸?shù)臄?shù)據(jù)很多就需要等待,這個參數(shù)一般寫入portMAX_DELAY 表示無限等待。
如果返回ESP_OK表示I2S讀取數(shù)據(jù)成功。
I2S發(fā)送數(shù)據(jù)
函數(shù)原型:
參數(shù)說明:i2s_port_t i2s_num:I2S_NUM_0 或I2S_NUM_1。
const void *src:寫入源數(shù)據(jù)的緩存區(qū)
size_t size:要寫入的數(shù)據(jù)大小,單位是字節(jié)
size_t *bytes_written:實際寫入的字節(jié)數(shù)
TickType_t ticks_to_wait:超時等待時間,因為I2S是按一定頻率發(fā)送數(shù)據(jù)的,如果一次傳輸?shù)臄?shù)據(jù)很多就需要等待,這個參數(shù)一般寫入portMAX_DELAY 表示無限等待。
卸載I2S驅(qū)動
函數(shù)原型:
參數(shù)說明: 卸載I2S驅(qū)動的話我們只需要傳入I2S端口就行了。
i2s_port_t i2s_num:指定使用的 I2S 外設(shè)端口。i2s_port_t 是 I2S 外設(shè)端口的枚舉類型,有兩個端口可用:I2S_NUM_0 和 I2S_NUM_1,對應(yīng) ESP32 的第一個和第二個 I2S 外設(shè)。
總結(jié)
以上我們介紹了I2S的相關(guān)知識和配置的相關(guān)函數(shù),下篇文章我們來看一下一個使用ESP32驅(qū)動I2S設(shè)備的小案例!這系列的文章主要是分享一下本人學(xué)習(xí)過程的相關(guān)知識,如果有錯誤可以交流學(xué)習(xí)下!
審核編輯 黃宇
-
I2S
+關(guān)注
關(guān)注
1文章
80瀏覽量
44103 -
ESP32
+關(guān)注
關(guān)注
26文章
1199瀏覽量
21828
發(fā)布評論請先 登錄
音頻總線I2S協(xié)議:I2S收發(fā)模塊FPGA的仿真設(shè)計
全面解析I2S、TDM、PCM音頻總線
ESP32 I2S音頻總線學(xué)習(xí)筆記(二):I2S讀取INMP441音頻數(shù)據(jù)
ESP32輸出的I2S數(shù)據(jù)移位的原因?
ESP32輸出的I2S數(shù)據(jù)移位問題如何解決?
ESP32輸出的I2S數(shù)據(jù)移位問題求解
音頻接口I2S實驗
基于FPGA和AD1836的I2S接口設(shè)計
i2s音頻總線學(xué)習(xí)
幾種常見的I2S數(shù)據(jù)格式
ESP32 I2S音頻總線學(xué)習(xí)筆記(一):初識I2S通信與配置基礎(chǔ)












評論