成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

I2S總線

yunhao / 3800人閱讀

摘要:一簡介也叫,即總線又稱集成電路內(nèi)置音頻總線,是飛利浦公司為數(shù)字音頻設(shè)備之間的音頻數(shù)據(jù)傳輸而制定的一種總線標(biāo)準(zhǔn),該總線專責(zé)于音頻設(shè)備之間的數(shù)據(jù)傳輸,廣泛應(yīng)用于各種多媒體系統(tǒng)。位,這兩個位用于選擇標(biāo)準(zhǔn),設(shè)置為,選擇飛利浦標(biāo)準(zhǔn)。

一、I2S簡介

I2S(也叫IIS,即:Inter IC Sound)總線, 又稱集成電路內(nèi)置音頻總線,是飛利浦公司為數(shù)字音頻設(shè)備之間的音頻數(shù)據(jù)傳輸而制定的一種總線標(biāo)準(zhǔn),該總線專責(zé)于音頻設(shè)備之間的數(shù)據(jù)傳輸,廣泛應(yīng)用于各種多媒體系統(tǒng)。它采用了沿獨立的導(dǎo)線傳輸時鐘與數(shù)據(jù)信號的設(shè)計,通過將數(shù)據(jù)和時鐘信號分離,避免了因時差誘發(fā)的失真,為用戶節(jié)省了購買抵抗音頻抖動的專業(yè)設(shè)備的費用。
特點
●支持全雙工/半雙工通信
●支持主/從模式設(shè)置
●8位可編程線性預(yù)分頻器,可實現(xiàn)精確的音頻采樣頻率(8~192Khz)
●支持16位/24位/32位數(shù)據(jù)格式
●數(shù)據(jù)包幀固定為16位(僅16位數(shù)據(jù)幀)或32位(可容納16/24/32位數(shù)據(jù)幀)
●可編程時鐘極性
●支持MSB對齊(左對齊)、LSB對齊(右對齊)、飛利浦標(biāo)準(zhǔn)和PCM標(biāo)準(zhǔn)等I2S標(biāo)準(zhǔn)
●支持DMA數(shù)據(jù)傳輸(16位寬)
●數(shù)據(jù)方向固定位MSB在前
●支持主時鐘輸出(固定為256*fs,fs即音頻采樣率)

二、I2S框圖以及信號

I2S框圖
STM32F4的I2S是與SPI部分共用的,通過設(shè)置SPI_I2SCFGR寄存器的I2SMOD位即可開啟I2S功能,I2S接口使用了幾乎與SPI相同的引腳、標(biāo)志和中斷。


信號
1,SD:串行數(shù)據(jù)(映射到 MOSI 引腳),用于發(fā)送或接收兩個時分復(fù)用的數(shù)據(jù)通道上的數(shù)據(jù)(僅半雙工模式)。
2,WS:字選擇(映射到NSS引腳),即左右時鐘,用于切換左右聲道的數(shù)據(jù)。WS頻率等于音頻信號采樣率(fs)。
3,CK:串行時鐘(映射到SCK引腳),即位時鐘,是主模式下的串行時鐘輸出以及從模式下的串行時鐘輸入。CK頻率=WS頻率(fs)216(16位寬),如果是32位寬,則是:CK頻率=WS頻率(fs)232(32位寬)。
4,I2S2ext_SD和I2S3ext_SD:用于控制I2S全雙工模式的附加串行數(shù)據(jù)引腳(映射到MISO引腳),這兩個引腳僅用于全雙工模式。
5,MCK:即主時鐘輸出,當(dāng)I2S配置為主模式(且SPI_I2SPR寄存器的MCKOE位置1)時,使用此時鐘,該時鐘頻率為 256×fs,fs:音頻信號采樣頻率。

STM32F4為支持I2S全雙工模式,除了I2S2和I2S3,還可以使用兩個額外的I2S,它們稱為擴(kuò)展I2S(I2S2_ext、I2S3_ext),其框圖為:

擴(kuò)展I2S (I2Sx_ext)只能用于全雙工模式。I2Sx_ext始終在從模式下工作。I2Sx和I2Sx_ext 均可用于發(fā)送和接收。

三、幀格式

STM32F4的I2S支持4種數(shù)據(jù)和幀格式組合,分別是:
1,將16位數(shù)據(jù)封裝在16位幀中;
2,將16位數(shù)據(jù)封裝在32位幀中;
3,將24位數(shù)據(jù)封裝在32位幀中;
4,將32位數(shù)據(jù)封裝在32位幀中;

將16位數(shù)據(jù)封裝在32位幀中時,前16位(MSB)為有效位,16位LSB被強(qiáng)制清零,無需任何軟件操作或DMA請求(只需一個讀/寫操作)。如果應(yīng)用程序選則DMA,則24位和32位數(shù)據(jù)幀需要對SPI_DR執(zhí)行兩次CPU讀取或?qū)懭氩僮?,或者需要兩次DMA操作。24位的數(shù)據(jù)幀,硬件會將8位非有效位擴(kuò)展到帶有0位的32位數(shù)據(jù)幀。
4種幀標(biāo)準(zhǔn):
1,飛利浦標(biāo)準(zhǔn);
2,MSB 對齊(左對齊)標(biāo)準(zhǔn);
3,LSB 對齊(右對齊)標(biāo)準(zhǔn);
4,PCM標(biāo)準(zhǔn);

I2S飛利浦標(biāo)準(zhǔn)幀24位數(shù)據(jù),32位幀格式

I2S飛利浦標(biāo)準(zhǔn),使用WS信號來指示當(dāng)前正在發(fā)送的數(shù)據(jù)所屬的通道。該信號從當(dāng)前通道數(shù)據(jù)的第一個位(MSB)之前的一個時鐘開始有效。發(fā)送方在時鐘信號(CK)的下降沿改變數(shù)據(jù),接收方在上升沿讀取數(shù)據(jù)。WS信號也在CK的下降沿變化。在24位模式下數(shù)據(jù)傳輸,需要對SPI_DR執(zhí)行兩次讀取或?qū)懭氩僮?。比如要發(fā)送0X8EAA33這個數(shù)據(jù),就要分兩次寫入SPI_DR,第一次寫入:0X8EAA,第二次寫入0X33xx(xx可以為任意數(shù)值),這樣就把0X8EAA33發(fā)送出去了。
注意:從SD卡讀取到的24位WAV數(shù)據(jù)流,是低字節(jié)在前,高字節(jié)在后的,比如,我們讀到一個聲道的數(shù)據(jù)(24bit),存儲在buf[3]里面,那么要通過SPI_DR發(fā)送這個24位數(shù)據(jù),過程如下:
SPI_DR=((u16)buf[2]<<8)+buf[1];
SPI_DR=(u16)buf[0]<<8;
這樣,第一次發(fā)送高16位數(shù)據(jù),第二次發(fā)送低8位數(shù)據(jù),完成一次24bit數(shù)據(jù)的發(fā)送。

四、I2S時鐘


上圖中的I2SxCLK,可以來自PLLI2S輸出(通過R系數(shù)分頻)或者來自外部時鐘(I2S_CKIN引腳),一般使用前者作為I2SxCLK輸入時鐘。
需要根據(jù)音頻采樣率(fs)來計算各個分頻器的值,常用的音頻采樣率有:22.05Khz、44.1Khz、48Khz、96Khz、196Khz等。

當(dāng)MCK輸出使能時,fs頻率計算公式如下:
fs=I2SxCLK/[256 * (2 * I2SDIV+ODD)]
其中:I2SxCLK=(HSE/pllm)* PLLI2SN/PLLI2SR。 HSE是8Mhz,而pllm在系統(tǒng)時鐘初始化就確定了,是8,這樣結(jié)合以上式,可得計算公式如下:

fs= (1000 * PLLI2SN/PLLI2SR )/[256 * (2 * I2SDIV+ODD)]
fs單位是:Khz。其中:PLLI2SN取值范圍:192~ 432;PLLI2SR取值范圍:2~ 7;I2SDIV取值范圍:2~255;ODD取值范圍:0/1。

根據(jù)以上約束條件,便可根據(jù)fs來設(shè)置各個系數(shù)的值了,不過很多時候,并不能取得和fs一模一樣的頻率,只能近似等于fs,比如44.1Khz采樣率,設(shè)置PLLI2SN=271,PLLI2SR=2,I2SDIV=6,ODD=0,得到fs=44.108073Khz,誤差為:0.0183%。晶振頻率決定了有時無法通過分頻得到我們所要的fs,所以,某些fs如果要實現(xiàn)0誤差,必須得選用外部時鐘才可以。
為了方便可以將常用的fs建立對應(yīng)的表格。

//表格式:采樣率/10,PLLI2SN,PLLI2SR,I2SDIV,ODDconst u16 I2S_PSC_TBL[][5]={        {800 ,256,5,12,1},		//8Khz采樣率        {1102,429,4,19,0},		//11.025Khz采樣率        {1600,213,2,13,0},	//16Khz采樣率        {2205,429,4, 9,1},		//22.05Khz采樣率        {3200,213,2, 6,1},		//32Khz采樣率        {4410,271,2, 6,0},		//44.1Khz采樣率        {4800,258,3, 3,1},		//48Khz采樣率        {8820,316,2, 3,1},		//88.2Khz采樣率        {9600,344,2, 3,1},  	//96Khz采樣率        {17640,361,2,2,0},  	//176.4Khz采樣率        {19200,393,2,2,0},  	//192Khz采樣率};

五、I2S寄存器

1、SPI_I2S配置寄存器(SPI_I2SCFGR)

I2SMOD位,設(shè)置為1,選擇I2S模式,注意,必須在I2S/SPI禁止的時候,設(shè)置該位。
I2SE位,設(shè)置為1,使能I2S外設(shè),該位必須在I2SMOD位設(shè)置之后再設(shè)置。
I2SCFG[1:0]位, 這兩個位用于配置I2S模式,設(shè)置為10,選擇主模式(發(fā)送)。
I2SSTD[1:0]位,這兩個位用于選擇I2S標(biāo)準(zhǔn),設(shè)置為00,選擇飛利浦標(biāo)準(zhǔn)。
CKPOL位,用于設(shè)置空閑時時鐘電平,設(shè)置為0,空閑時時鐘低電平。
DATLEN[1:0]位,用于設(shè)置數(shù)據(jù)長度,00,表示16位數(shù)據(jù);01表示24位數(shù)據(jù)。
CHLEN位,用于設(shè)置通道長度,即幀長度,0,表示16位;1,表示32位。
2、SPI_I2S預(yù)分頻器寄存器(SPI_I2SSPR)

設(shè)置MCKOE為1,開啟MCK輸出,ODD和I2SDIV則根據(jù)不同的fs,查表進(jìn)行設(shè)置。
3、PLLI2S配置寄存器(RCC_PLLI2SCFGR)

該寄存器用于配置PLLI2SR和PLLI2SN兩個系數(shù),PLLI2SR的取值范圍是:2~ 7,PLLI2SN的取值范圍是:192~432。同樣,這兩個也是根據(jù)fs的值來設(shè)置的。

六、I2S初始化步驟

  • 1)初始化WM8978
    這個過程就是配置上一講講介紹的WM8978那十幾個寄存器,包括軟復(fù)位、DAC設(shè)置、輸出設(shè)置和音量設(shè)置等。
  • 2)初始化I2S
    此過程主要設(shè)置SPI_I2SCFGR寄存器,設(shè)置I2S模式、I2S標(biāo)準(zhǔn)、時鐘空閑電平和數(shù)據(jù)幀長等,最后開啟I2S TX DMA,使能I2S外設(shè)。
  • 3)解析WAV文件,獲取音頻信號采樣率和位數(shù)并設(shè)置I2S時鐘分頻器
    解析WAV文件,取得音頻信號的采樣率(fs)和位數(shù)(16位或24位),根據(jù)這兩個參數(shù),來設(shè)置I2S的時鐘分頻,用前面介紹的查表法來設(shè)置。
  • 4)設(shè)置DMA
    I2S播放音頻,一般采用DMA來傳輸數(shù)據(jù),這里我們用I2S2,其TX用DMA1數(shù)據(jù)流4的通道0來傳輸數(shù)據(jù)。并且,STM32F4的DMA具有雙緩沖機(jī)制,這樣可以提高效率。這里,我們將DMA1數(shù)據(jù)流4設(shè)置為:雙緩沖循環(huán)模式,外設(shè)和存儲器都是16位寬,并開啟DMA傳輸完成中斷(方便填充數(shù)據(jù))。
  • 5)編寫DMA傳輸完成中斷服務(wù)函數(shù)
    為了方便填充音頻數(shù)據(jù),我們使用DMA傳輸完成中斷,每當(dāng)一個緩沖數(shù)據(jù)發(fā)送完后,硬件自動切換為下一個緩沖,同時進(jìn)入中斷服務(wù)函數(shù),填充數(shù)據(jù)到發(fā)送完的這個緩沖。如下圖所示:
  • 6)開啟DMA傳輸,填充數(shù)據(jù)
    最后,只需要開啟DMA傳輸,然后及時填充WAV數(shù)據(jù)到DMA的兩個緩存區(qū)即可。此時,就可以在WM8978的耳機(jī)和喇叭通道聽到所播放音樂了。

七、播放WAV文件代碼

//播放某個WAV文件//fname:wav文件路徑.//返回值://KEY0_PRES:下一曲//KEY1_PRES:上一曲//其他:錯誤u8 wav_play_song(u8* fname){	u8 key;	u8 t=0; 	u8 res;  	u32 fillnum; 	audiodev.file=(FIL*)mymalloc(SRAMIN,sizeof(FIL));	audiodev.i2sbuf1=mymalloc(SRAMIN,WAV_I2S_TX_DMA_BUFSIZE);	audiodev.i2sbuf2=mymalloc(SRAMIN,WAV_I2S_TX_DMA_BUFSIZE);	audiodev.tbuf=mymalloc(SRAMIN,WAV_I2S_TX_DMA_BUFSIZE);	if(audiodev.file&&audiodev.i2sbuf1&&audiodev.i2sbuf2&&audiodev.tbuf)	{ 		res=wav_decode_init(fname,&wavctrl);//得到文件的信息		if(res==0)//解析文件成功		{			if(wavctrl.bps==16)			{				WM8978_I2S_Cfg(2,0);	//飛利浦標(biāo)準(zhǔn),16位數(shù)據(jù)長度				I2S2_Init(I2S_Standard_Phillips,I2S_Mode_MasterTx,I2S_CPOL_Low,I2S_DataFormat_16bextended);		//飛利浦標(biāo)準(zhǔn),主機(jī)發(fā)送,時鐘低電平有效,16位擴(kuò)展幀長度			}else if(wavctrl.bps==24)			{				WM8978_I2S_Cfg(2,2);	//飛利浦標(biāo)準(zhǔn),24位數(shù)據(jù)長度				I2S2_Init(I2S_Standard_Phillips,I2S_Mode_MasterTx,I2S_CPOL_Low,I2S_DataFormat_24b);		//飛利浦標(biāo)準(zhǔn),主機(jī)發(fā)送,時鐘低電平有效,24位擴(kuò)展幀長度			}			I2S2_SampleRate_Set(wavctrl.samplerate);//設(shè)置采樣率			I2S2_TX_DMA_Init(audiodev.i2sbuf1,audiodev.i2sbuf2,WAV_I2S_TX_DMA_BUFSIZE/2); //配置TX DMA			i2s_tx_callback=wav_i2s_dma_tx_callback;			//回調(diào)函數(shù)指wav_i2s_dma_callback			audio_stop();			res=f_open(audiodev.file,(TCHAR*)fname,FA_READ);	//打開文件			if(res==0)			{				f_lseek(audiodev.file, wavctrl.datastart);		//跳過文件頭				fillnum=wav_buffill(audiodev.i2sbuf1,WAV_I2S_TX_DMA_BUFSIZE,wavctrl.bps);				fillnum=wav_buffill(audiodev.i2sbuf2,WAV_I2S_TX_DMA_BUFSIZE,wavctrl.bps);				audio_start();  				while(res==0)				{ 					while(wavtransferend==0);//等待wav傳輸完成; 					wavtransferend=0;					if(fillnum!=WAV_I2S_TX_DMA_BUFSIZE)//播放結(jié)束?					{						res=KEY0_PRES;						break;					}  					if(wavwitchbuf)fillnum=wav_buffill(audiodev.i2sbuf2,WAV_I2S_TX_DMA_BUFSIZE,wavctrl.bps);//填充buf2					else fillnum=wav_buffill(audiodev.i2sbuf1,WAV_I2S_TX_DMA_BUFSIZE,wavctrl.bps);//填充buf1					while(1)					{						key=KEY_Scan(0); 						if(key==WKUP_PRES)//暫停						{							if(audiodev.status&0X01)audiodev.status&=~(1<<0);							else audiodev.status|=0X01;  						}						if(key==KEY2_PRES||key==KEY0_PRES)//下一曲/上一曲						{							res=key;							break; 						}						wav_get_curtime(audiodev.file,&wavctrl);//得到總時間和當(dāng)前播放的時間 						audio_msg_show(wavctrl.totsec,wavctrl.cursec,wavctrl.bitrate);						t++;						if(t==20)						{							t=0; 							LED0=!LED0;						}						if((audiodev.status&0X01)==0)delay_ms(10);						else break;					}				}				audio_stop(); 			}else res=0XFF; 		}else res=0XFF;	}else res=0XFF; 	myfree(SRAMIN,audiodev.tbuf);	//釋放內(nèi)存	myfree(SRAMIN,audiodev.i2sbuf1);//釋放內(nèi)存	myfree(SRAMIN,audiodev.i2sbuf2);//釋放內(nèi)存 	myfree(SRAMIN,audiodev.file);	//釋放內(nèi)存 	return res;} 

音樂播放就講到這里啦?。?!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/122389.html

相關(guān)文章

  • STM32學(xué)習(xí)筆記 第二章 STM32資源介紹

    摘要:總線掛載的外設(shè)有等。外設(shè)地址映射片上外設(shè)區(qū)分為三條總線,根據(jù)外設(shè)速度的不同,不同總線掛載著不同的外設(shè),掛載低速外設(shè),和掛載高速外設(shè)。 第二章 STM32資源介紹 2...

    G9YH 評論0 收藏0
  • 【程序員基礎(chǔ)必備】計算機(jī)組成原理概念大全

    摘要:計算機(jī)組成原理是大學(xué)中的專業(yè)必修課,也是程序員需要掌握的專業(yè)知識。所以說計算機(jī)組成原理是非常重要的一門課程,本文總結(jié)了五十個組原中的重要概念,供大家學(xué)習(xí)。通道程序通道程序由通道指令組成,他完成某種外圍設(shè)備與主存?zhèn)魉托畔⒌牟僮鳌? 計算機(jī)組成原理是大學(xué)中的專業(yè)必修課,也是程序員需要掌握的專業(yè)...

    OBKoro1 評論0 收藏0
  • 全志R528核心板和開發(fā)板

    摘要:產(chǎn)品概述是我司傾力打造的一款基于全志雙核處理器的高性能核心板,可廣泛應(yīng)用于智能家居工業(yè)顯示語控設(shè)備醫(yī)療電子等產(chǎn)品。 產(chǎn)品概述 ? ?R5是我司傾力打造的一款基于全志R528-S3A雙核處理器的高性能Linux核心板,可廣泛應(yīng)用于智能家居、工業(yè)顯示、語控設(shè)備、醫(yī)療電子等產(chǎn)品。 ? 核心板體積小...

    nanfeiyan 評論0 收藏0
  • YodaOS開發(fā)套件征集活動

    摘要:為了能讓感興趣的開發(fā)者小伙伴第一時間體驗到,聯(lián)合社區(qū)趕在春節(jié)前發(fā)起開發(fā)套件試用征集活動,該套件是基于自研語音解決方案平臺打造而成。與此同時,我們也同樣提供高度定制化模塊化的整體架構(gòu),開發(fā)者亦可方便地選擇想要集成的模塊對整個操作系統(tǒng)重新組裝。 1月28日,Rokid為人機(jī)交互設(shè)備開發(fā)的開源人工智能操作系統(tǒng)——YodaOS正式上線,可用于智能音箱、智能家居、智能穿戴和車載等多種設(shè)備和場景。...

    canger 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<