Gitee倉(cāng)庫(kù):https://gitee.com/openharmony-sig/knowledge_demo_temp/tree/master/dev/team_x/demo_record_pen
一、Codec介紹
WM8978為DAC+ADC芯片,本身并不具備編解碼的功能,一方面,可通過(guò)I2S接口接收PCM數(shù)據(jù),轉(zhuǎn)為模擬信號(hào)輸出,此為DAC過(guò)程,即放音;一方面,可接收模擬信號(hào)轉(zhuǎn)為數(shù)字信號(hào),通過(guò)I2S接口傳輸給MCU,此為ADC過(guò)程,即錄音。WM8978還使用I2C接口配置其工作參數(shù),比如音量,EQ,3D環(huán)繞等。WM8978本身可直連1W/8歐的小喇叭。

引腳配置:

1、I2S和I2C的使能
首先需要打開config下usr_config.mk文件,打開編譯I2S和I2C的使能

2、導(dǎo)入lal_audio文件
打開使能后進(jìn)行編譯,導(dǎo)入lal_audio文件,可見wm8978_init函數(shù),對(duì)引腳進(jìn)行使能:

3、WM8978的I2C配置
WM8978需要使用I2C引腳對(duì)輸入方式、喇叭音量、輸入增益等等進(jìn)行控制,詳情可見lal_audio中其它函數(shù)

如上圖,進(jìn)行初始化后即可對(duì)錄音和放音進(jìn)行測(cè)試;
4、WM8978錄音測(cè)試
其中需要用到I2S的讀寫函數(shù),本文件中設(shè)置的采集頻率和位寬是16K和16位(方便后續(xù)語(yǔ)音識(shí)別)

使用二維數(shù)組緩存的方式進(jìn)行讀取和播放,經(jīng)驗(yàn)證后滿足要求。
hi_u32 WM8978_Write_Reg(hi_u8 reg, hi_u16 val)
{
//unsigned char buf[2];
//buf[0] = (reg<1)|((val?>>8)&0X01);
//buf[1] = val&0XFF;
hi_i2c_data i2c_data;
hi_u8 send_data[2]= { 0 };
send_data[0] = (reg<1)|((val?>>8)&0X01);
send_data[1] = val&0XFF;
/* send_data[0] = reg;
send_data[1] = val; */
i2c_data.send_buf = send_data;
i2c_data.send_len = 2;
//(WM8978_DEVICE_ADDR>>1)|0
wm8978_register_tbl[reg] = val;
// return hi_i2c_writeread(HI_I2C_IDX_1,(WM8978_DEVICE_ADDR<1), &i2c_data);
//hi_i2c_write
return hi_i2c_write(HI_I2C_IDX_1,(WM8978_DEVICE_ADDR<1), &i2c_data);
}
hi_u32 WM8978_Read_Reg(hi_u8 reg)
{
return wm8978_register_tbl[reg];
}
//WM8978 AUXR,AUXL(PWM音頻部分)增益設(shè)置(AUXR/L--?>ADC輸入部分的增益)
//gain:0~7,0表示通道禁止,1~7,對(duì)應(yīng)-12dB~6dB,3dB/Step
void WM8978_AUX_Gain(hi_u8 gain)
{
hi_u16 regval;
gain&=0X07;
regval=WM8978_Read_Reg(47); //讀取R47
regval&=~(7<0); //清除原來(lái)的設(shè)置
WM8978_Write_Reg(47,regval|gain<0);//設(shè)置R47
regval=WM8978_Read_Reg(48); //讀取R48
regval&=~(7<0); //清除原來(lái)的設(shè)置
WM8978_Write_Reg(48,regval|gain<0);//設(shè)置R48
}
//WM8978 輸出配置
//dacen:DAC輸出(放音)開啟(1)/關(guān)閉(0)
//bpsen:Bypass輸出(錄音,包括MIC,LINE IN,AUX等)開啟(1)/關(guān)閉(0)
void WM8978_Output_Cfg(hi_u8 dacen,hi_u8 bpsen)
{
hi_u16 regval=0;
if(dacen)regval|=1<0; //DAC輸出使能
if(bpsen)
{
regval|=1<1; //BYPASS使能
regval|=5<2; //0dB增益
}
WM8978_Write_Reg(50,regval);//R50設(shè)置
WM8978_Write_Reg(51,regval);//R51設(shè)置
}
//WM8978 MIC增益設(shè)置(不包括BOOST的20dB,MIC--?>ADC輸入部分的增益)
//gain:0~63,對(duì)應(yīng)-12dB~35.25dB,0.75dB/Step
void WM8978_MIC_Gain(hi_u8 gain)
{
gain&=0X3F;
WM8978_Write_Reg(45,gain); //R45,左通道PGA設(shè)置
WM8978_Write_Reg(46,gain|1<8); //R46,右通道PGA設(shè)置
}
//WM8978 L2/R2(也就是Line In)增益設(shè)置(L2/R2--?>ADC輸入部分的增益)
//gain:0~7,0表示通道禁止,1~7,對(duì)應(yīng)-12dB~6dB,3dB/Step
void WM8978_LINEIN_Gain(hi_u8 gain)
{
hi_u16 regval;
gain&=0X07;
regval=WM8978_Read_Reg(47); //讀取R47
regval&=~(7<4); //清除原來(lái)的設(shè)置
WM8978_Write_Reg(47,regval|gain<4);//設(shè)置R47
regval=WM8978_Read_Reg(48); //讀取R48
regval&=~(7<4); //清除原來(lái)的設(shè)置
WM8978_Write_Reg(48,regval|gain<4);//設(shè)置R48
}
//WM8978 DAC/ADC配置
//adcen:adc使能(1)/關(guān)閉(0)
//dacen:dac使能(1)/關(guān)閉(0)
void WM8978_ADDA_Cfg(hi_u8 dacen,hi_u8 adcen)
{
hi_u16 regval;
regval=WM8978_Read_Reg(3); //讀取R3
if(dacen)regval|=3<0; //R3最低2個(gè)位設(shè)置為1,開啟DACR&DACL
else regval&=~(3<0); //R3最低2個(gè)位清零,關(guān)閉DACR&DACL.
WM8978_Write_Reg(3,regval); //設(shè)置R3
regval=WM8978_Read_Reg(2); //讀取R2
if(adcen)regval|=3<0; //R2最低2個(gè)位設(shè)置為1,開啟ADCR&ADCL
else regval&=~(3<0); //R2最低2個(gè)位清零,關(guān)閉ADCR&ADCL.
WM8978_Write_Reg(2,regval); //設(shè)置R2
}
//WM8978 輸入通道配置
//micen:MIC開啟(1)/關(guān)閉(0)
//lineinen:Line In開啟(1)/關(guān)閉(0)
//auxen:aux開啟(1)/關(guān)閉(0)
void WM8978_Input_Cfg(hi_u8 micen,hi_u8 lineinen,hi_u8 auxen)
{
hi_u16 regval;
regval=WM8978_Read_Reg(2); //讀取R2
if(micen)regval|=3<2; //開啟INPPGAENR,INPPGAENL(MIC的PGA放大)
else regval&=~(3<2); //關(guān)閉INPPGAENR,INPPGAENL.
WM8978_Write_Reg(2,regval); //設(shè)置R2
regval=WM8978_Read_Reg(44); //讀取R44
if(micen)regval|=3<4|3<0; //開啟LIN2INPPGA,LIP2INPGA,RIN2INPPGA,RIP2INPGA.
else regval&=~(3<4|3<0); //關(guān)閉LIN2INPPGA,LIP2INPGA,RIN2INPPGA,RIP2INPGA.
WM8978_Write_Reg(44,regval);//設(shè)置R44
if(lineinen)WM8978_LINEIN_Gain(5);//LINE IN 0dB增益
else WM8978_LINEIN_Gain(0); //關(guān)閉LINE IN
if(auxen)WM8978_AUX_Gain(7);//AUX 6dB增益
else WM8978_AUX_Gain(0); //關(guān)閉AUX輸入
}
//設(shè)置I2S工作模式
//fmt:0,LSB(右對(duì)齊);1,MSB(左對(duì)齊);2,飛利浦標(biāo)準(zhǔn)I2S;3,PCM/DSP;
//len:0,16位;1,20位;2,24位;3,32位;
void WM8978_I2S_Cfg(hi_u8 fmt,hi_u8 len)
{
fmt&=0X03;
len&=0X03;//限定范圍
WM8978_Write_Reg(4,(fmt<3)|(len<5)); //R4,WM8978工作模式設(shè)置
}
//設(shè)置耳機(jī)左右聲道音量
//voll:左聲道音量(0~63)
//volr:右聲道音量(0~63)
void WM8978_HPvol_Set(hi_u8 voll,hi_u8 volr)
{
voll&=0X3F;
volr&=0X3F;//限定范圍
if(voll==0)voll|=1<6;//音量為0時(shí),直接mute
if(volr==0)volr|=1<6;//音量為0時(shí),直接mute
WM8978_Write_Reg(52,voll); //R52,耳機(jī)左聲道音量設(shè)置
WM8978_Write_Reg(53,volr|(1<8)); //R53,耳機(jī)右聲道音量設(shè)置,同步更新(HPVU=1)
}
//設(shè)置喇叭音量
//voll:左聲道音量(0~63)
void WM8978_SPKvol_Set(hi_u8 volx)
{
volx&=0X3F;//限定范圍
if(volx==0)volx|=1<6;//音量為0時(shí),直接mute
WM8978_Write_Reg(54,volx); //R54,喇叭左聲道音量設(shè)置
WM8978_Write_Reg(55,volx|(1<8)); //R55,喇叭右聲道音量設(shè)置,同步更新(SPKVU=1)
}
void I2C_TEST()
{
hi_u32 ret;
hi_io_set_func(HI_IO_NAME_GPIO_0, HI_IO_FUNC_GPIO_0_I2C1_SDA);
hi_io_set_func(HI_IO_NAME_GPIO_1, HI_IO_FUNC_GPIO_1_I2C1_SCL);
ret = hi_i2c_deinit(HI_I2C_IDX_1); /* if wake_up from deep sleep, should deinit first */
if (ret != HI_ERR_SUCCESS) {
printf("I2C delete errorrn");
return;
}
ret = hi_i2c_init(HI_I2C_IDX_1, 100000); /* baudrate: 100000 */
if (ret != HI_ERR_SUCCESS) {
printf("I2C errorrn");
return;
}
printf("IIC sucessfullyrn");
ret = WM8978_Write_Reg(0,0);
if (ret != HI_ERR_SUCCESS) {
printf("8978 errorrn");
printf("flash partition table init fail:0x%x rn", ret);
return;
}
printf("8978 passrn");
}
審核編輯:湯梓紅
-
PCM
+關(guān)注
關(guān)注
1文章
202瀏覽量
54295 -
嵌入式
+關(guān)注
關(guān)注
5152文章
19675瀏覽量
317606 -
錄音筆
+關(guān)注
關(guān)注
0文章
92瀏覽量
13435 -
WM8978
+關(guān)注
關(guān)注
1文章
5瀏覽量
3931 -
Hi3861
+關(guān)注
關(guān)注
1文章
63瀏覽量
7073
發(fā)布評(píng)論請(qǐng)先 登錄
評(píng)論