[原创] 晒设计方案+吊丝生活之用STM32F429i听音乐

sjtitr   2014-1-10 15:44 楼主
崩溃了,板子掉头了,返回去这么久都杳无音信,再不发点什么我的想法都发霉了。 算了,不等板子了,先发想法,板子回来再试验。 第一辑,好吊丝,好音乐。 听音乐,怎么弄?好多童鞋都推荐我使用I2S,只要连接到一个小芯片,一顿送数据,就搞定了,不错不错。 然后我翻看各种资料,终于被我发现了,……这句话! 注:EEWORLD不提供设计经费(包括元器件、PCB+打样等)支持! 好,本吊丝果断放弃该方案。 没有了I2S,用什么办法呢?于是乎问题回归其本源……真是巧呢,最近也一直有网友在研究声音问题,用单片机的PWM回放复杂的声音。 不不不,这太本源了,事实上,我们的429i有其利器,那就是DAC。这样的话,我们只需要一个喇叭和两根接线就OK了。神马?你说没有喇叭,那你太吊丝了,还听什么音乐,自己唱好了;或者你可以像我一样把肾卖掉买个iPhone,然后把上面的喇叭拆下来待用。 又于是,我们要了解声音的有关信息,主要是在数字世界的声音。 其实也很简单,声音嘛,每个1秒中采样有限个数据样本,每个数据样本有限个数据位数。 比较常见的,44KHz,16位采样率,就是说,每次用ADC采16位的数据作为一个样本,每秒钟采44000个样本。 所以要想听到声音,反过来咯。每次用DAC产生一个电压,每秒钟产生44000个。 太多了吧,我看我们这次还是先听点音质差的:8KHz,8位采样——我们的DAC最大支持到12位,至于频率嘛,我说了我现在没有板子,凭空想象的,8KHz设置频率,应该没问题,不行再想别的办法! 然后就是操作啦, 首先你应当有音乐的数据。还在同WinXP的孩纸们方便啦,使用录音机就可以很方便的搞出个上述指标的声音文件,然后找个16进制编辑器把其中的声音数据抓出来形成一个大型的数组——OK,这就是数据源啦。 wav.jpg 接下来,我们到官网上找到429i评价板的官方例程,从中取出:DAC_SignalsGeneration 官方例程里产生了一堆波形,我作为一个好吊丝我不想看波形,我只想听音乐,于是乎拿里面的代码改吧。从正弦函数图像入手就可以了。
  1. const uint16_t Sine12bit[32] = {
  2. 2047, 2447, 2831, 3185, 3498, 3750, 3939, 4056, 4095, 4056,
  3. 3939, 3750, 3495, 3185, 2831, 2447, 2047, 1647, 1263, 909,
  4. 599, 344, 155, 38, 0, 38, 155, 344, 599, 909, 1263, 1647};
从源代码中我们可以看到正弦波形就是用数组来实现的,把数组里的内容顺序送给DAC,漂亮的波形就产生了。同样的,只要把我们的音乐数据顺序送给DAC,……莫名其妙的声音就能出来……前提是你已经把喇叭串联在DAC输出口和地线之间了。木有板子,我现在主观认为产生的波形应该是莫名其妙的声音。因为DMA的设定,送给DAC的数据的频率,可能不是8KHz的,而且明显的,源程序送数是16位的,我们的声音是8位的。所以还有好多参数要调整正确啊。 接下来调整参数: 1.送数改为8位,原来16位的代码在此,看看里面有几个参数明显的需要修改呢,没有实验就没有真知,所以我先不提供修改方案了。
  1. void DAC_Ch2_SineWaveConfig(void)
  2. {
  3. DMA_InitTypeDef DMA_InitStructure;
  4. /* DAC channel2 Configuration */
  5. DAC_InitStructure.DAC_Trigger = DAC_Trigger_T6_TRGO;
  6. DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
  7. DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
  8. DAC_Init(DAC_Channel_2, &DAC_InitStructure);
  9. /* DMA1_Stream5 channel7 configuration **************************************/
  10. DMA_DeInit(DMA1_Stream5);
  11. DMA_InitStructure.DMA_Channel = DMA_Channel_7;
  12. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)DAC_DHR12R2_ADDRESS;
  13. DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&Sine12bit;
  14. DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  15. DMA_InitStructure.DMA_BufferSize = 32;
  16. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  17. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  18. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  19. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  20. DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  21. DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  22. DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  23. DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  24. DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  25. DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  26. DMA_Init(DMA1_Stream5, &DMA_InitStructure);
  27. /* Enable DMA1_Stream5 */
  28. DMA_Cmd(DMA1_Stream5, ENABLE);
  29. /* Enable DAC Channel2 */
  30. DAC_Cmd(DAC_Channel_2, ENABLE);
  31. /* Enable DMA for DAC Channel2 */
  32. DAC_DMACmd(DAC_Channel_2, ENABLE);
  33. }
起始不提供修改方案,更重要的一个原因就是,这个DMA可能无法设定成8KHz的频率来送数,这不符合DMA思想,这样做不科学…… 十有八九,我们的第二个问题: 2.设定送数频率为8KHz,有可能需要使用一个定时器来做了,还是定时器比较王道啊,呵呵。 嗯嗯,这下思路清楚了,就坐等板子归来调试了。 意淫之中,板子已经开始演奏美妙的音乐了。…… ——本辑结束—— 片花: ……尼玛,你怎么把喇叭直接按在引脚上啦……而且空间不够啊,每次换个歌都得重新烧啊……我还想用屏幕看歌词啊有木有……音质好差啊,还有木有好办法啊,啊啊~…… 本帖最后由 sjtitr 于 2014-1-10 15:44 编辑

回复评论 (1)

给楼主捧个场,板子返回来立刻给你寄过去,希望早日能看到楼主杰作
点赞  2014-1-10 17:48
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复