STM32和WM8960 I2S 利用DMA双缓冲音频播放和录音(一)
这个实验比串口双缓冲要稍微复杂点,音频播放很简单,主要是录音,折腾快一个礼拜了,网上查找资料倒腾来倒腾去,死活就不行,哎。不搞定这个问题,不甘心,
脑子不停的想,这个问题可能出在哪,还有哪个地方没考虑到。就这样,脑子兴奋的很,都没什么困意,要不是第二天要赶着上班,都不用睡了,功夫不负有心人,经过几天折腾终于调通了。。。
吐槽一下,现在网上都养成了一种风气,下载一些参考资料都是要付金币,付了金币下载后,发现有些资料一点技术含量都没,基本上没什么参考价值,真气人。
言归正传,首先设置WM8960寄存器,配置播放路径,参数配置比较简单。播放时,STM做主机,WM8960配置从机,可以对照资料查看各个寄存器
WM8960 寄存配置:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//播放时,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, };
音频播放数据走向如下图
设置WM8960寄存器,配置录音和播放路径,这里的STM配置的是从机,WM8960做主机。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//录音时,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 }
(1)、录音和播放:对麦克风讲话,音频数据直接通过WM8960内部路径直接到耳机进行播放。音频数据整体走向图如下。
还有一种播放是将录音的数据保存到STM,然后STM再将录的音频数据播放出来
录音前端设置,用的是LINPUT1和RINPUT1,这里只贴LINPUT1配置图,RINPUT1参考这个配置就行
播放后端配置图
还有重要的配置,时钟。时钟结构图配置
//录音时,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 | //----------------------------------------------------------------------------------------------------------------------------------- 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的值; 0x14,0x0f9 }