STM32和WM8960 I2S 利用DMA双缓冲音频播放和录音(一)

这个实验比串口双缓冲要稍微复杂点,音频播放很简单,主要是录音,折腾快一个礼拜了,也是网上找相关例子倒腾来倒腾去,死活就不行,哎。。。

吐槽一下,现在网上都养成了一种风气,下载一些参考资料都是要付金币,付了金币下载后,发现有些资料一点技术含量都没,基本上没什么参考价值。

言归正传,首先设置WM8960寄存器,配置播放路径,参数配置比较简单。播放时,STM做主机,WM8960配置从机,可以对照资料查看各个寄存器

WM8960 寄存配置:

//播放时,ST设置的是主机,WM8960是从机
const u16 wm8960_reg_slave[]=
{
    0x0f,0x000,   //SOFT reset
    0x19,0x1c0,
    0x1a,0x1f8,
    0x2f,0x00c,
    
    0x04,0x000,
    0x00,0x13f,
    0x01,0x13f,
    0x00,0x13f,
    0x01,0x13f,
    0x15,0x1f3,
    0x16,0x1f3,
    0x19,0x1ee,
    0x20,0x138,
    0x21,0x138,
    0x2b,0x000,
    0x2c,0x000,
    0x05,0x000,
    0x07,0x002,
    0x02,0x15F,
    0x03,0x15F,
    0x28,0x17F,
    0x29,0x17F,
    0x31,0x0F7,
    0x0a,0x1FF,
    0x0b,0x1FF,
    0x22,0x180,
    0x25,0x180,
    0x18,0x000,
    0x17,0x1c3,
    0x30,0x009,
};
View Code

音频播放数据走向如下图

设置WM8960寄存器,配置录音播放路径,这里的STM配置的是从机,WM8960做主机

//录音时,ST设置的是从机,WM8960设置主机
//WM8960 master mode   MCLK使用的是外部有源晶振24MHz
//f2=4×2×11.2896MHz的=90.3168MHz
//R = 90.3168 / 12 = 7.5264
//PLLN = int R = 7
// K = int ( 2^24 x (7.5264 – 7)) = 8831526 = 86C226h
//-----------------------------------------------------------------------------------------------------------------------------------
//|    mclk  | DESIRED OUTPUT |   f2    | PRESCALE DIVIDE | POSTSCALE DIVIDE |    FIXED POST-DIVIDE | R          |    N   |   K     |
//|    (f1)  | (SYSCLK)       | (MHz)   | (PLLPRESCALE)   | (SYSCLKDIV[1:0]) |                      |            |        |         |
//|    (MHz) | (MHz)          |         |                 |                  |                      |            |        |         |
//|----------------------------------------------------------------------------------------------------------------------------------
//|    24    | 11.2896        | 90.3168 |            2    |       2          |            4         |    7.5264  |    7h  | 86C226h |
//-----------------------------------------------------------------------------------------------------------------------------------
const u16 wm8960_reg_master[]=
{
    0x0f,0x000,   //SOFT reset
    0x19,0x17e,        // enable MIC and MICBias
    0x1a,0x1e0,        // enable DAC and ROUTPUT LOUTPUT
    0x2f,0x03c,        // enable output mixer
    0x04,0x000,        //MCLK->div1->SYSCLK->DAC/ADC sample Freq = (SYSCLK)/(1*256) = 11.2896/256 =44.1KHz
    0x20,0x138,        //LINPUT1 Microphone config
    0x21,0x138,        //RINPUT1 Microphone config
    0x2b,0x000,        // mute LINPUT3 to Left Mixer
    0x2c,0x000,        // mute RINPUT3 to Left Mixer
    0x00,0x17f,
    0x01,0x17f,
    0x05,0x000,
    0x06,0x000,
    0x07,0x002,
    0x18,0x004,
    0x30,0x000,
    0x02,0x151,//LOUT1 Volume
    0x03,0x151,//ROUT1 Volume
    0x03,0x151,//ROUT1 Volume
    0x22,0x100,//Enable Left DAC to Left Output Mixer
    0x25,0x100,//Enable Right DAC to Right Output Mixer 
    0x2d,0x080,//Left Input Boost Mixer to Left Output Mixer
    0x2e,0x080, //Right Input Boost Mixer to Right Output Mixer
    
    0x1a,0x1e1,        // enable DAC and ROUTPUT LOUTPUT;bit0=1, PLL en
    0x04,0x005,        //DAC/ADC sample Freq = (11.2896)/(1*256)=44.1K bit[0](CLKSEL)置1:选择PLL输出的时钟(置0表示选择MCLK时钟);bit[2:1](SYSCLKDIV)置10:分频(除以2)
    0x07,0x042,  //bit6=1, Enable master mode; bit[1:0]=10,I2S Format;bit[3:2]=00,16 bits
    0x08,0x1C4,     // BCLKDIV[3:0]=0100 BCLK Frequency = SYSCLK/4=11.2896/4=2.8224MHz
    
    0x34,0x037, //bit4(PLLPRESCALE)置1:预分频,如果MCLK=12M就不用设置该位了;bit[3:0](PLLN)置0111:设置PLLN的值;;bit5(SDM)置1:选择为小数模式;
    0x35,0x086,//bit[8:0](PLLK)置01000 0110:设置PLLK的值;
    0x36,0x0c2,//bit[8:0](PLLK)置01100 0010:设置PLLK的值;
    0x37,0x026,//bit[8:0](PLLK)置00010 0110:设置PLLK的值;
    
    0x14,0x0f9
}
View Code

(1)、录音和播放:对麦克风讲话,音频数据直接通过WM8960内部路径直接到耳机进行播放。音频数据整体走向图如下。

  (a)、麦克风前端输入路径设置,这里使用的LINPUT1和RINPUT1,LINPUT1设置如下图,ALC功能可以先不考虑,RINPUT1配置雷同。

   (b)、后端的播放路径,如下图,设置增益,也就是控制音量,这里主要打通通路,音质后续可慢慢调。

(2)、STM32配置从机,WM8960配置主机,主要方便后续STM 利用DMA双缓冲能收到数据。STM32做主机配置DMA接收数据时,始终收不到数据,当然也就进不了中断,

至于为什么接不到数据后面代码中会讲解到。

(3)、WM8960使用的是外部晶振提供24MHz,所以时钟配置也得按照资料上配置好,配置时钟参数如下

//录音时,ST设置的是从机,WM8960设置主机
//WM8960 master mode   MCLK使用的是外部有源晶振24MHz
//f2=4×2×11.2896MHz=90.3168MHz//R = 90.3168 / 12 = 7.5264
//PLLN = int R = 7
// K = int ( 2^24 x (7.5264 ¨C 7)) = 8831526 = 86C226h
//----------------------------------------------------------------------------------------------------------------------------------
//|    mclk  | DESIRED OUTPUT |   f2    | PRESCALE DIVIDE | POSTSCALE DIVIDE |    FIXED POST-DIVIDE | R       |    N     |  K      |
//|    (f1)  | (SYSCLK)       | (MHz)   | (PLLPRESCALE)   | (SYSCLKDIV[1:0]) |                      |         |          |         |
//|    (MHz) | (MHz)          |         |                 |                  |                      |         |          |         |
//|---------------------------------------------------------------------------------------------------------------------------------
//|    24    | 11.2896        | 90.3168 |            2    |       2          |            4         |  7.5264 |    7h    | 86C226h |
//----------------------------------------------------------------------------------------------------------------------------------
    0x04,0x000,        //MCLK->div1->SYSCLK->DAC/ADC sample Freq = (SYSCLK)/(1*256) = 11.2896/256 =44.1KHz
    0x1a,0x1e1,        // enable DAC and ROUTPUT LOUTPUT;bit0=1, PLL en
    0x04,0x005,        //DAC/ADC sample Freq = (11.2896)/(1*256)=44.1K bit[0](CLKSEL)置1:选择PLL输出的时钟(置0表示选择MCLK时钟);bit[2:1](SYSCLKDIV)置10:分频(除以2)
    0x07,0x042,  //bit6=1, Enable master mode; bit[1:0]=10,I2S Format;bit[3:2]=00,16 bits
    0x08,0x1C4,     // BCLKDIV[3:0]=0100 BCLK Frequency = SYSCLK/4=11.2896/4=2.8224MHz
    
    0x34,0x037, //bit4(PLLPRESCALE)置1:预分频,如果MCLK=12M就不用设置该位了;bit[3:0](PLLN)置0111:设置PLLN的值;;bit5(SDM)置1:选择为小数模式;
    0x35,0x086,//bit[8:0](PLLK)置01000 0110:设置PLLK的值;
    0x36,0x0c2,//bit[8:0](PLLK)置01100 0010:设置PLLK的值;
    0x37,0x026,//bit[8:0](PLLK)置00010 0110:设置PLLK的值

 时钟结构图及配置

猜你喜欢

转载自www.cnblogs.com/wen2376/p/12345089.html