数字麦克风接收的音频到底对不对,还得有办法检查一下。从STM32F413的12-bit DAC输出是一个办法,但对音频来说这个精度不够。用专用的数字音频接口吧:I2S或者SAI都可以胜任。
在STM32系列里面,I2S功能通常是和SPI复用的:大多数的SPI硬件都有I2S模式。但是这个硬件I2S不是很好用,特别是Slave模式有bug。ST在新一代的MCU里面加入了SAI——串行音频接口,就强多了。一个SAI有两个串行收发部分,可以同步也可以独立工作。
现在我必须要开始吐槽一下STM32F413的手册了,上面这段是从Datasheet里面截图出来的,请注意,支持
SPDIF 输出哦。然后,看Reference manual的SAI部分
竟然这里就没提 SPDIF ! 我搜遍整个Reference manual, 只字未提
SPDIF ST啊,Nucleo你出一个ES工程版的也就罢了,手册也要来ES版吗?
下面是RCC章节部分Clock tree的图
PLL1的输出这里是连错了,R输出废弃么?
ck_plli2s_ext 这是引脚么?还是什么信号?通篇都找不到。I2S_CKIN这是要标给什么呢?
PLLDIVR,这里说的是 div 1 到 32,看好了
但是后面描述的时候是这么说的
对,说的是 div只能从1~31。还有,请注意 PLLDIVR 在寄存器中是 12:8 位,但是前面的表里面是这样的
表格里面是 bit13 到 bit9,前后不符!我在这里就遇到了错误,怎么设都是蹊跷。后来才发现是手册上面自相矛盾。
还有这样的错,一眼就能看出来。拜托,发布手册不要这么着急好么?
排除了手册的bug,我终于把SAI的I2S master模式调通了。按44100采样频率的设计,从PLL需要产生271MHz的时钟,除以6以后得到45.1667MHz, 再除以1024得到44.1081kHz,是很接近组合。因为PLL R输出最多只能除以7,所以后面分频是用PLLDIVR来除以4, 得到11.2917MHz 作为SAI部分的时钟。同时,PLL R时钟也给DFSDM1, 因为它内部有最大256的分频系数,用在麦克风没有问题,除以16是麦克风的Clock.
在SAI A block中,11.2917MHz 除以4是SCK_A的频率,再除以64就是FS_A的频率。协议及数据格式设置如下:
SAI1_Block_A->CR1 = SAI_xCR1_DS_2|SAI_xCR1_DS_1;
// 24-bit, master out, sync mode, free protocol
SAI1_Block_A->FRCR = SAI_xFRCR_FSOFF|SAI_xFRCR_FSDEF|(31<<8)|63;
SAI1_Block_A->SLOTR = (3<<16)|(1<<8)|SAI_xSLOTR_SLOTSZ_1; // slot 0 & 1, 32-bit
因为DFSDM1和SAI1用同一个时钟,数据速率也相同,因此传输是同步的。可以用两个DMA通道来实现自动传输,CPU完全闲出来处理其它事情。这样,数字麦克风的1-bit 64倍超采样信号经DFSDM降采样处理后,得到44100采样频率的PCM数据流,再送给SAI,以I2S数据格式输出。我用自己手头别的硬件工具可以采集I2S数据传入电脑了。
用Cooledit一分析,声音是采到了,回放听起来正常,但增益实在太高了,容易截顶失真。需要增加设置 DFSDM1 中积分器之后数据右移,偏移量也需要再修正一下。
总结:STM32F413 有丰富的硬件资源给音频相关应用提供便利。再结合100MHz处理速度和320kB片上SRAM、FPU,在音频领域发挥一下创意还是很有前途的。
本帖最后由 cruelfox 于 2016-12-25 22:40 编辑