簡(jiǎn)介
在音頻處理領(lǐng)域,I2S是一種廣泛使用的通信協(xié)議,它專門用于芯片之間的音頻數(shù)據(jù)傳輸。ESP32 作為一款高性能的微控制器,不僅支持 I2S 通信,還提供了強(qiáng)大的硬件接口和靈活的軟件庫(kù),使其成為音頻項(xiàng)目開發(fā)的理想選擇。本篇文章將介紹I2S的相關(guān)知識(shí)和使用ESP32驅(qū)動(dòng)I2S音頻設(shè)備時(shí)比較常用的相關(guān)底層API函數(shù)。
I2S即Inter-IC Sound, 簡(jiǎn)稱I2S,意思是芯片間音頻總線,它是由飛利浦開發(fā)的一種用于數(shù)字音頻設(shè)備的通信協(xié)議,常用于麥克風(fēng)、揚(yáng)聲器、音頻處理器等設(shè)備之間的音頻數(shù)據(jù)傳輸。
為什么需要I2S?
傳統(tǒng)的音頻設(shè)備,像模擬電路,傳遞的是電壓信號(hào),這種方式容易受到干擾,比如噪聲或者信號(hào)衰減。而數(shù)字音頻需要傳輸數(shù)據(jù),通常是二進(jìn)制的“0”和“1”,直接用模擬接口傳輸會(huì)很麻煩。而 I2S就是為了解決這個(gè)問(wèn)題的一種數(shù)字音頻接口,它讓音頻數(shù)據(jù)的傳輸變得簡(jiǎn)單、高效、而且抗干擾能力強(qiáng)。 使用 I2S可以很方便地把數(shù)字音頻信號(hào)從一個(gè)芯片傳遞到另一個(gè)芯片,對(duì)于開發(fā)者來(lái)講只需要配置好芯片的 I2S 模塊,就可以實(shí)現(xiàn)數(shù)字音頻數(shù)據(jù)的傳輸了。
關(guān)于音頻信號(hào)
在自然界中音頻信號(hào)是以模擬量的形式存在的,它是一種隨時(shí)間連續(xù)變化的物理量,為了減少外界的干擾我們需要把它變成數(shù)字量,我們一般可以通過(guò)一個(gè)模數(shù)轉(zhuǎn)換器把它變成數(shù)字信號(hào)(圖1),數(shù)字信號(hào)在計(jì)算機(jī)或數(shù)字設(shè)備中以離散的數(shù)值形式表示和處理,比如用0和1的組合去表示,這里可以了解下PCM編碼,它是一種模擬信號(hào)數(shù)字化的方法
當(dāng)然我們也能通過(guò)一個(gè)數(shù)模轉(zhuǎn)換器把數(shù)字信號(hào)還原成模擬信號(hào),以便在揚(yáng)聲器上播放音頻(圖2)。
這樣音頻信號(hào)之間的傳遞就可以通過(guò)數(shù)字信號(hào)來(lái)進(jìn)行了(圖3),可以減少外界對(duì)信號(hào)的干擾。
在音頻信號(hào)處理和傳輸中,有三個(gè)非常重要的參數(shù)決定了音頻質(zhì)量和設(shè)備性能:采樣率、分辨率和 音頻聲道。
采樣率
采樣率就是每秒采集聲音樣本的頻率,這個(gè)頻率越快,采樣的數(shù)字信號(hào)就越接近原始的聲音的信號(hào),因?yàn)椴蓸拥脑娇欤x散數(shù)字曲線每個(gè)樣本值之間的過(guò)渡就越接近,曲線就會(huì)越平滑。這個(gè)過(guò)程和錄像是類似的,一個(gè)是采樣光,一個(gè)采樣振動(dòng)。我們知道錄像其實(shí)就是一幀一幀的圖像快速播放,這個(gè)采樣速度很快,我們?nèi)庋鄯直娌涣?,看起?lái)就是連續(xù)的。如果錄像時(shí)采樣的速度很慢,比如1秒采樣3次,那我們就會(huì)丟失掉很多畫面細(xì)節(jié)。采集聲音的時(shí)候也是如此,大家可以想象一下,如果采集頻率很慢,聽(tīng)到的聲音會(huì)是什么樣子,會(huì)明顯感到聲音聽(tīng)起來(lái)失真不連貫甚至變樣。
每秒鐘采集的音頻樣本數(shù),常見(jiàn)的有8K、16K、44.1K等,采樣率越高,信號(hào)還原越精細(xì),一般使用44.1KHz采樣頻率就可以得到比較高保真的聲音。
分辨率
對(duì)聲音數(shù)據(jù)采樣后,我們將得到一些離散的樣本點(diǎn),那我們?cè)谝恍?shù)字設(shè)備是如何存儲(chǔ)這些樣本點(diǎn)的呢?我們采樣的數(shù)據(jù)是以二進(jìn)制的形式存儲(chǔ)的,比如對(duì)于每一個(gè)采樣點(diǎn)我們用3位二進(jìn)制來(lái)表示(圖4),那么它可以表示的范圍就是2^3=8 即8種量化電平信號(hào)(圖5),可以簡(jiǎn)單理解為:每個(gè)采樣點(diǎn)可以存儲(chǔ) 8種情況的聲音。如果量化位數(shù)越多,根據(jù)我們高中學(xué)過(guò)的排列組合知道,得到的樣本值就會(huì)越多,那它可以表示自然界聲音的細(xì)節(jié)就越多,或者說(shuō)能表示的聲音就越豐富。
音頻數(shù)據(jù)的量化位數(shù)或量化深度,常見(jiàn)的有8bit、16bit、24bit、32bit等,位數(shù)越高,信號(hào)的動(dòng)態(tài)范圍和精細(xì)程度越好
音頻聲道
分為單聲道,雙聲道,單聲道是一種只有一個(gè)音頻信號(hào)通道,所有聲音都合并到一個(gè)通道中輸出,無(wú)論是通過(guò)一個(gè)揚(yáng)聲器還是兩個(gè)揚(yáng)聲器,聽(tīng)到的聲音是完全相同的。雙聲道分為左聲道和右聲道,具有兩個(gè)獨(dú)立音頻通道,左聲道和右聲道可以傳遞不同的聲音信號(hào),具有空間感和方向感,也就是我們平常說(shuō)的立體聲。
怎樣使用I2S傳輸音頻?
使用I2S傳輸音頻的時(shí)候,需要用到時(shí)鐘信號(hào)、控制信號(hào)以及數(shù)據(jù)信號(hào)(圖6),它們之間是分開傳輸?shù)摹?duì)于標(biāo)準(zhǔn)通信模式下的 I2S 總線主要包含以下幾個(gè)信號(hào):位時(shí)鐘BCLK,字時(shí)鐘WS,串行數(shù)據(jù)SD。有的時(shí)候還需要MCLK:主時(shí)鐘線,該信號(hào)線可選,具體取決于從機(jī),主要用于向 I2S 從機(jī)提供參考時(shí)鐘。
~(注意這幾種信號(hào)有幾種其它叫法,這里結(jié)合英文選擇了這幾個(gè)名稱,大家只要在使用能區(qū)分就行)~~
位時(shí)鐘BCLK
BCLK(Bit Clock,位時(shí)鐘)
也叫BCK, SCLK(Serial Clock),對(duì)應(yīng)數(shù)字音頻的每一位數(shù)據(jù),是模塊內(nèi)的同步信號(hào)BCLK 定義了數(shù)據(jù)傳輸?shù)乃俾?,用?lái)控制數(shù)據(jù)的傳輸節(jié)奏。它的頻率通常是采樣率乘以每個(gè)采樣的位數(shù)再乘以聲道數(shù)量。例如,對(duì)于 44.1kHz 的采樣率、16 位雙聲道音頻,BCLK 的頻率為 44.1kHz × 16 × 2= 1.4112 MHz。所以對(duì)于雙聲道來(lái)說(shuō),BCLK的頻率=2×采樣頻率×采樣位數(shù)。
字時(shí)鐘WS
WS(Word Select , 字選擇時(shí)鐘)
也叫 LRCLK (Left Right Clock)即左右聲道時(shí)鐘, 用于標(biāo)識(shí)當(dāng)前正在傳輸?shù)氖亲舐暤罃?shù)據(jù)還是右聲道數(shù)據(jù)。對(duì)于飛利浦公司定義的I2S標(biāo)準(zhǔn),當(dāng) WS 為低電平時(shí)表示左聲道,高電平時(shí)表示右聲道。一個(gè)完整的 WS 信號(hào)周期包含兩個(gè)聲道的數(shù)據(jù)(左聲道和右聲道)WS 信號(hào)的頻率等于音頻的采樣率。
例如,如果音頻采樣率是 44.1kHz,那么 WS 的頻率也是 44.1kHz。
串行數(shù)據(jù)SD
SD(Serial Data,串行數(shù)據(jù))
i2s傳輸時(shí)的音頻數(shù)據(jù),是用二進(jìn)制補(bǔ)碼表示的,具體數(shù)據(jù)傳輸?shù)母袷街饕ǎ篒2S格式,左對(duì)齊格式,右對(duì)齊格式,每個(gè) BCK 周期會(huì)傳輸一位數(shù)據(jù)。數(shù)據(jù)發(fā)送端和接收端會(huì)根據(jù) BCK 信號(hào)的跳變(上升沿或下降沿)同步數(shù)據(jù)的發(fā)送和接收。當(dāng) WS 為低電平時(shí),SD 傳輸左聲道數(shù)據(jù);當(dāng) WS 為高電平時(shí),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
它表示
- 每個(gè) BCK 周期傳輸一位音頻數(shù)據(jù)。
- 當(dāng) WS 為低電平時(shí),SD 按位傳輸左聲道的 16 位數(shù)據(jù)1 0 1 0 1 1 0 1 1 0 0 0 1 0 0 1
- 當(dāng) WS 為高電平時(shí),SD 按位傳輸右聲道的 16 位數(shù)據(jù) 1 1 0 0 1 0 0 1 1 0 0 0 1 0 0 1,
個(gè)人總結(jié)
字時(shí)鐘:高低電平翻轉(zhuǎn),總線在傳輸雙聲道音頻 0為左, 1為右,字時(shí)鐘的頻率=采樣率
位時(shí)鐘:串行數(shù)據(jù)線的信號(hào)會(huì)在位時(shí)鐘上升沿被采樣,位時(shí)鐘的頻率=2×采樣率×采樣位數(shù)。
串行數(shù)據(jù):用二進(jìn)制補(bǔ)碼表示的音頻數(shù)據(jù),先傳輸高位,再傳輸?shù)臀唬?br /> Tips:字時(shí)鐘和位時(shí)鐘都是由主機(jī)發(fā)送
了解了I2S是如何傳輸后,我們?cè)賮?lái)看看他的傳輸模型和通信格式。
I2S傳輸模型
I2S通信支持全雙工和半雙工通信,支持主/從模式。主設(shè)備就是發(fā)送時(shí)鐘的,從設(shè)備在時(shí)鐘的控制下發(fā)送或者接收數(shù)據(jù)。
連接到I2S總線的設(shè)備可以分為兩類:
控制器——控制 SCK 和 WS 信號(hào)。
目標(biāo)設(shè)備——接收 SCK 和 WS 信號(hào)
總線上只能有一個(gè)控制器,但是總線可以有多個(gè)目標(biāo)設(shè)備。
音頻設(shè)備,可以分為三類:
發(fā)射器——發(fā)送音頻信號(hào)。
接收器——接收音頻信號(hào)。
控制器——控制音頻信號(hào)
這里我們至少需要一個(gè)發(fā)射器和接收器,控制器是可選的,主要用于向 I2S 從機(jī)提供參考時(shí)鐘
根據(jù)I2S總線誰(shuí)作為控制器,誰(shuí)作為目標(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 和 左對(duì)齊(Left-justified) 格式等。
I2S格式
I2S格式:又稱飛利浦格式(圖7),數(shù)據(jù)最高位總是出現(xiàn)在字時(shí)鐘變化后的第二個(gè)位時(shí)鐘脈沖處(滯后一個(gè)位時(shí)鐘),這種格式下數(shù)據(jù)MSB的位置是確定的,LSB的位置取決于字長(zhǎng)。
左對(duì)齊格式
左對(duì)齊格式(圖8):數(shù)據(jù)最高位出現(xiàn)在字時(shí)鐘變化后的第一個(gè)位時(shí)鐘脈沖處(無(wú)滯后位時(shí)鐘)
右對(duì)齊格式
右對(duì)齊格式:又稱日本格式,這種格式和左對(duì)齊差不多,只不過(guò)整體是靠右對(duì)齊的,即數(shù)據(jù)LSB與WCLK跳變沿對(duì)齊。
i2s基本配置
①,i2s的時(shí)鐘使能和GPIO口配置 ②,配置為i2s模式
③,i2s標(biāo)準(zhǔn),無(wú)論有多少位有效數(shù)據(jù),即數(shù)據(jù)的最高位總是出現(xiàn)在WS變化(也就是一幀開始)后的第2個(gè)CK脈沖處。
④,i2s數(shù)據(jù)長(zhǎng)度,包括16位,16位擴(kuò)展(16位數(shù)據(jù)以32位包發(fā)送),24位,32位。 ⑤,設(shè)置i2s時(shí)鐘
⑥,設(shè)置i2s空閑狀態(tài)下時(shí)鐘電平 ⑦,i2s使能
i2s 底層API
這里我們以ESP32 I2S通信為例,開發(fā)環(huán)境是Arduino IDE,介紹它的相關(guān)底層API,在我們調(diào)庫(kù)的時(shí)候下面這些函數(shù)會(huì)被調(diào)用,我們看一下它的實(shí)現(xiàn)過(guò)程。
加載I2S驅(qū)動(dòng)
函數(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ù)說(shuō)明::
i2s_port_t i2s_num:指定使用的 I2S 外設(shè)端口。i2s_port_t 是 I2S 外設(shè)端口的枚舉類型,有兩個(gè)端口可用:I2S_NUM_0 和 I2S_NUM_1,對(duì)應(yīng) ESP32 的第一個(gè)和第二個(gè) I2S 外設(shè)。
const i2s_config_t * i2s_config : 設(shè)置I2S 外設(shè)的配置參數(shù)。其中i2s_config_t 是一個(gè)結(jié)構(gòu)體,定義了 I2S 外設(shè)的配置選項(xiàng),這里我們只看常用的配置選項(xiàng)就可以了,主要包括mode、 sample_rate、bits_per_sample等,如下:
int queue_size: 數(shù)據(jù)傳輸?shù)年?duì)列的大小void * i2s_queue:存放和管理 I2S 傳輸?shù)臄?shù)據(jù)。
這個(gè)函數(shù)有一個(gè)esp_err_t 的返回值,如果返回ESP_OK表示加載I2S驅(qū)動(dòng)成功。
設(shè)置I2S使用的引腳
函數(shù)原型:
參數(shù)說(shuō)明:
i2s_port_t i2s_num:指定使用的 I2S 外設(shè)端口,I2S_NUM_0 或I2S_NUM_1。
i2s_pin_config_t * pin:配置I2S接口的各個(gè)引腳,i2s_pin_config_t 是一個(gè)結(jié)構(gòu)體,里面是關(guān)于I2S引腳,如時(shí)鐘引腳,左右聲道選擇引腳,數(shù)據(jù)輸入引腳等引腳的配置。如下:
I2S讀取數(shù)據(jù)
函數(shù)原型:
參數(shù)說(shuō)明: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:實(shí)際讀取到的字節(jié)數(shù)
TickType_t ticks_to_wait:超時(shí)等待時(shí)間,因?yàn)镮2S是按一定頻率讀取數(shù)據(jù)的,如果一次傳輸?shù)臄?shù)據(jù)很多就需要等待,這個(gè)參數(shù)一般寫入portMAX_DELAY 表示無(wú)限等待。
如果返回ESP_OK表示I2S讀取數(shù)據(jù)成功。
I2S發(fā)送數(shù)據(jù)
函數(shù)原型:
參數(shù)說(shuō)明: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:實(shí)際寫入的字節(jié)數(shù)
TickType_t ticks_to_wait:超時(shí)等待時(shí)間,因?yàn)镮2S是按一定頻率發(fā)送數(shù)據(jù)的,如果一次傳輸?shù)臄?shù)據(jù)很多就需要等待,這個(gè)參數(shù)一般寫入portMAX_DELAY 表示無(wú)限等待。
卸載I2S驅(qū)動(dòng)
函數(shù)原型:
參數(shù)說(shuō)明: 卸載I2S驅(qū)動(dòng)的話我們只需要傳入I2S端口就行了。
i2s_port_t i2s_num:指定使用的 I2S 外設(shè)端口。i2s_port_t 是 I2S 外設(shè)端口的枚舉類型,有兩個(gè)端口可用:I2S_NUM_0 和 I2S_NUM_1,對(duì)應(yīng) ESP32 的第一個(gè)和第二個(gè) I2S 外設(shè)。
總結(jié)
以上我們介紹了I2S的相關(guān)知識(shí)和配置的相關(guān)函數(shù),下篇文章我們來(lái)看一下一個(gè)使用ESP32驅(qū)動(dòng)I2S設(shè)備的小案例!這系列的文章主要是分享一下本人學(xué)習(xí)過(guò)程的相關(guān)知識(shí),如果有錯(cuò)誤可以交流學(xué)習(xí)下!
審核編輯 黃宇
-
I2S
+關(guān)注
關(guān)注
1文章
77瀏覽量
43697 -
ESP32
+關(guān)注
關(guān)注
21文章
1043瀏覽量
20287
發(fā)布評(píng)論請(qǐng)先 登錄
音頻總線I2S協(xié)議:I2S收發(fā)模塊FPGA的仿真設(shè)計(jì)

全面解析I2S、TDM、PCM音頻總線
ESP32輸出的I2S數(shù)據(jù)移位的原因?
ESP32輸出的I2S數(shù)據(jù)移位問(wèn)題如何解決?
ESP32開啟I2S驅(qū)動(dòng)后,是怎么干擾到RF模塊的?
ESP32輸出的I2S數(shù)據(jù)移位問(wèn)題求解
音頻接口I2S實(shí)驗(yàn)
基于FPGA和AD1836的I2S接口設(shè)計(jì)
i2s音頻總線學(xué)習(xí)

幾種常見(jiàn)的I2S數(shù)據(jù)格式

評(píng)論