你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【我爱DIY】简易WAV播放器  

[复制链接]
creep 发布时间:2017-8-19 21:10
本帖最后由 creep 于 2017-8-22 08:56 编辑 0 Y, H3 o" \; x7 D, {
8 g+ B* G: T! @) p' K; S8 ^
      STM32F769-DISCO 上面有个WM8994可以用于音频解码。WM8994具有高性能低功耗体积小等优点,曾用在早期的三星安卓手机上用到。下面的测试主要是使用WM8994播放WAV文件。
, p3 i0 u8 _: ^6 q: o( q4 ]5 w0 Y) W. b( r1 ^! n
1 _& Z3 Y  A- Q& u
1、串行音频接口(SAI)& c) B( K0 f2 X5 `( M
SAI 接口(串行音频接口)灵活性高、配置多样,可支持多种音频协议。该接口适用于许多立体声或单声道应用。例如,它可配置为支持 I2S 标准、 LSB 或 MSB 对齐、 PCM/DSP、TDM 和 AC’97 等协议。将音频模块配置为发送器时, SAI 接口可提供 SPDIF 输出。SAI 通过两个完全独立的音频子模块来实现这种灵活性和可配置性。每个模块都有自己的时钟发生器和 I/O 线控制器。SAI 可以配置为主模式或配置为从模式。音频子模块既可作为接收器,又可作为发送器;既可与另一模块同步,又可以不同步。8 A7 l, K/ Q; K( B( F
SAI 主要由两个各自带有时钟发生器的音频子模块组成,每个音频模块集成一个 32 位移位寄存器,该寄存器由模块自身的功能状态机控制。数据存储和读取都是通过专用的 FIFO 来完成。 FIFO 可通过 CPU 访问,也可通过 DMA 访问以减轻 CPU 的通信负担。每个音频模块是独立的。这两个音频子模块可彼此同步。SAI 中指定音频模块的 4 个专用引脚IO口( SD、 SCK、 FS、 MCLK)。/ k# _/ z; C& v8 s( z

+ _+ R, p# B- w0 x0 Q2 @8 z% w
9 K- h; `' l+ `2 {) H* n7 M, ]功能框图如下:
2 b- D* B9 _6 T4 H$ x- g TIM截图20170819170314.png
5 [4 z% A& @7 m( g9 S4 {4 E& H" L  z# E/ g7 f: }" I% ?$ N
STM32F769-DISOC 上面的WM8994通过SAI1_Block_A和MCU进行解码数据通信,WM8994的初始化和各项配置则通过IIC实现。
% `1 U! ^. Q3 [4 B  n' N, {
: t" r( E) N# V* j9 c4 Y" L6 {
  A- u( D$ J4 E- ~! q7 ] TIM截图20170819171150.png
; F/ N( A  t1 s
- s1 t  y0 V$ i8 }2、WAV格式文件
) n- O9 m/ {' P7 c7 `9 g1 C" NWAVE文件是计算机领域最常用的数字化声音文件格式之一,它是微软专门为Windows系统定义的波形文件格式(Waveform Audio)。WAVE是录音时用的标准的WINDOWS文件格式,文件的扩展名为“WAV”,数据本身的格式为PCM或压缩型。简单的理解WAV文件有一个文件头和数据部分组成,文件头里面包含该WAV的详细信息。一个典型的文件头格式如下:4 a$ a) T5 N' P$ y7 f) b
TIM截图20170819173349.png
0 C) \: q/ P5 r9 u 这个文件头共有44字节,不同的格式文件头可能长度不同,为了方便处理我使用开源软件Audacity将WAV的头文件格式都转为相同的44字节模式,其他的参数为立体声44.1KHZ.
; T8 l5 b6 t" o1 c" n$ y, O4 b( @4 C6 y- o$ X, {* P

$ g; S/ g0 e' V* P( Z3 T TIM截图20170819175532.png
) J$ [! W# n& w* N+ b/ x1 l$ I2 q; P* V$ v8 a
3、软件解码# h( u2 R: i: w
8 d% I5 W, m. S; ~* v
   播放的WAV文件放在TF卡里面,文件系统使用开源的FATFS,为了支持较长的歌曲名字,需要在FATFS中打开长文件名支持模式。同时为了支持中文显示,我把汉字点阵放到了
1 U. {' P4 p, Z! @: K0 KSTM32F769-DISCO 的外置NORFLASH里面,具体的操作可以查看之前的帖子。
8 X# H  `& X, C) Z& |0 \; W" ]! {4 b7 |- O1 J! d& P
WAV的播放是使用DMA 循环模式把数据从SD卡搬送到codec进行解码,其中DMA使能了HalfTransfer和TransferComplete来不断的更新要解码的数据文件。- M: I) _6 c3 Y
最开始的时候先将要解码的缓存写满,然后开始DMA传输,当传输完成一半时在使能标记开始更新前半部缓存,等传输完成继续更新后半部分缓存,这样可以实现更新缓存和
4 r) E) `9 N/ j( Z界面数据“同时进行”,当然这样做的前提是更新缓存数据速度要快于解码的数据,通过测试STM32F7完全没有压力。
! t9 L) E' O2 b1 n4 F4 s. Y8 h& z- ~+ S2 J6 s6 W
程序的流程如下:1 I, |: t# u* L6 u6 [) `, B/ ]  I
  • 先扫描SD卡找到WAV文件,将找到的WAV文件信息放入到一个链表中。
  • 显示找到的WAV文件名称到LCD上,并更新要播放的文件(名称为绿色字体)。
  • 根据预设的要播放的文件序号找到要要播放的WAV文件的信息,从SD卡里面读取填充播放缓存。
  • 开始播放WAV后不断的填充播放缓存直到播放完成。
  • 播放完成一个WAV文件后,根据播放模式(单曲循环、列表循环、随机循环)播放下一个WAV文件。
  • 播放的过程中可以通过用户按键切换下一个WAV文件进行播放。2 Y+ @* w# v& c. H& Z

6 c" M: Z. \  z0 @0 O程序下载后的:' t$ @( z) E' T: b% U. x( e* R( r
) R9 W& G# l/ e2 v
IMG_0161.JPG 5 N# N# w* P7 ~
3 ?. u1 |; v# d& O5 H1 K; |
使用按键切换歌曲:, g: d) e1 ^, q. g0 ]) a) j
9 Q6 v! C9 G- c
DJDL9465.GIF ( ~# t4 i1 H6 k+ f
+ w) N. ~; D& H  x/ d
mian 函数如下:$ q/ |5 z; N' M) y) {* L
  1.     _listfile_list *playfile;
    , Q9 l. ?+ V7 k5 x9 L6 ?& i
  2.     CPU_CACHE_Enable();
    3 `  Z2 L/ ~) L+ f% C) A6 D( Y
  3.     HAL_Init();
    / Y0 m+ i- k) {# j5 F
  4.     SystemClock_Config();
    - e1 |( k+ Z! ^$ D! Y! ?+ r
  5.     USART1_Init();5 O: N& X) C: C, }
  6.     HAL_Delay(200);* V/ D& q5 [. j9 x; \# `9 @9 J" D
  7.     BSP_LED_Init(LED_GREEN);" a0 M4 K' y# a! Q
  8.     BSP_LCD_Init();
    7 |  d$ R* h- W- _" Y
  9.     BSP_LCD_LayerDefaultInit(0, LCD_FB_START_ADDRESS);
    1 y+ ]$ D6 i$ W: p
  10.     BSP_LCD_SetTextColor(LCD_COLOR_RED);: h  j% {) k5 \" \* `+ j& @
  11.     BSP_LCD_SetBackColor(LCD_COLOR_BLACK);
    + K# `' J+ G* J
  12.     HAL_Delay(500);
    # R8 A9 I% T* \/ q9 R! _" M
  13.     BSP_QSPI_Init();3 y! |2 a( N! K. `6 J+ b
  14.     CopyFont2NorFlash();  M, ]& X* K8 f' a9 W: k0 ~
  15.     BSP_QSPI_EnableMemoryMappedMode();) F2 _3 w5 b$ I) N; @) I% l
  16.     CheckGBKFont4NorFlash();4 Z& ?6 M' W/ C4 d
  17.     BSP_LCD_Clear(LCD_COLOR_WHITE);' J& a, B0 p; Z/ {
  18. 2 F; s3 R9 n, F1 H
  19.     FatFs_SD_Init();
    . b! }+ ]! B# c
  20.     wavfilenum = ScanWavFiles("/");
    0 ?; Q0 A- k' G. B* C2 z
  21.     PrintfWavFileTest();
    % P" x2 i9 _" _
  22.     UpdateWavFileColor(playfilepos,playfilepos);
    " }! w& O- }1 S% W6 r( {- f
  23.     playfile = list_search(WavFileList, playfilepos);
    # e4 q* K" g& j8 |, ~: F0 h
  24. " P, U$ u) R7 D% {1 l! i* K
  25.     if(playfile == NULL)while(1);" O8 v: A$ z9 W( d2 c
  26. ; J; A' p1 h1 T9 y+ E. r
  27.     //´
    6 E$ \% ]7 g( j& q0 X# [# b  m
  28.     wavFileLen = OpendWavFile(playfile->filename);: W9 S! v9 ^& B/ R! x0 Q
  29.     //( p2 i" z, D6 N" t, p* }
  30.     ReadWaveFile(BuffHead, PLAY_HEADER);
    . U6 g$ ?( W2 }1 y
  31.     //
    ! H' S, |" d! q* i; p* G7 i
  32.     ReadWaveFile((uint8_t *)PlayBuff, PLAY_BUFF_SIZE * 2);$ ^7 Z6 S$ q/ W, ?* @+ j
  33.     Playback_Init();' I% |; h4 _' o4 Y! H

  34. ; T: |9 n4 F1 o8 U
  35.     /* Start the playback */
    7 u) ~8 v3 y( h9 Q$ C
  36.     if(0 != audio_drv->Play(AUDIO_I2C_ADDRESS, NULL, 0))
    9 e2 F& T9 ], M2 e
  37.     {
    2 ^; I1 J, p+ I  K
  38.         while(1);
    * N  S. d4 A( ~  q# ?4 T
  39.     }5 j$ W$ m" V% J+ I6 L$ p

  40. , z7 Q( _* W+ T7 A! o  \6 p9 g
  41.     if(HAL_OK != HAL_SAI_Transmit_DMA(&SaiHandle, (uint8_t *)PlayBuff, PLAY_BUFF_SIZE))
    / Z) e  s0 u5 Y: f9 {1 _/ N
  42.     {
    % r& L+ R* ]$ q1 H
  43.         while(1);
    : c7 Z( i9 }6 f" Q8 g, E
  44.     }
复制代码
需要注意的是程序里面默认播放是44.1KHZ立体声的WAV文件,如果是其他的格式的要在播放之前更新SAI的配置。5 h8 F! L+ q- J2 Z. N& i0 s
  1.    SaiHandle.Init.AudioMode      = SAI_MODEMASTER_TX;
    1 l8 p7 W' }  X$ O7 R$ J! f5 v
  2.     SaiHandle.Init.Synchro        = SAI_ASYNCHRONOUS;
    . s' v& v( u/ Z- y. E) v' P
  3.     SaiHandle.Init.OutputDrive    = SAI_OUTPUTDRIVE_ENABLE;
    ! T1 D* g9 ~, E' {# ?! z! |
  4.     SaiHandle.Init.NoDivider      = SAI_MASTERDIVIDER_ENABLE;# V, Z: `8 k/ S. P8 S
  5.     SaiHandle.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_1QF;
    : a9 c) k3 `6 c0 w2 L, G( u
  6.     SaiHandle.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_44K;
    # J; H; M+ D* Y/ S9 R' B: F
  7.     SaiHandle.Init.Protocol       = SAI_FREE_PROTOCOL;
    / ]( i0 ?3 C* F4 `
  8.     SaiHandle.Init.DataSize       = SAI_DATASIZE_16;
    + H: _7 F4 b' g) }
  9.     SaiHandle.Init.FirstBit       = SAI_FIRSTBIT_MSB;
    . D) ]$ p' I/ l3 C4 ?1 }0 T
  10.     SaiHandle.Init.ClockStrobing  = SAI_CLOCKSTROBING_FALLINGEDGE;
      I. k8 V/ g, S* E( m6 m

  11. 2 J% h  L2 q- P6 i% m
  12.     SaiHandle.FrameInit.FrameLength       = 32;
    + r  Y" G& p  F# v
  13.     SaiHandle.FrameInit.ActiveFrameLength = 16;7 \+ y9 o' o, I1 c  r. G
  14.     SaiHandle.FrameInit.FSDefinition      = SAI_FS_CHANNEL_IDENTIFICATION;! s8 B( z8 `0 q" s
  15.     SaiHandle.FrameInit.FSPolarity        = SAI_FS_ACTIVE_LOW;' I* F3 O; T- N
  16.     SaiHandle.FrameInit.FSOffset          = SAI_FS_BEFOREFIRSTBIT;
    , }+ F9 N6 q* z' S& b7 B, w$ r

  17. ; d) G8 b! b, a5 G, x
  18.     SaiHandle.SlotInit.FirstBitOffset = 0;* S% Y' l5 A% R# @
  19.     SaiHandle.SlotInit.SlotSize       = SAI_SLOTSIZE_DATASIZE;
    6 q7 q: L" K, s
  20.     SaiHandle.SlotInit.SlotNumber     = 2;
    ; A. o+ p6 e0 {9 f+ j9 _
  21.     SaiHandle.SlotInit.SlotActive     = (SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1);
    * o+ K) r" K$ f
复制代码
+ S" W/ s2 L* t3 f& S" I

. Z/ O; X- z" |4 F: z; v0 x
* l5 G  R' ^6 t' s8 V) H8 [7 ~' P* L5 s2 u" x
$ E. {* m$ b1 g1 L4 n' R" E" u
4、最后
9 _! @) v/ J) }+ e" r1 j/ y# s! M6 x
     使用STM32F769-DISOC配合论坛之前送的小音箱,播放音乐的效果和我手机电脑播放的听不出区别。我用手机语音备忘录录制了一段放在附件里面,感兴趣可以试听下。
& I  u- @" S5 |8 U0 ^* M
9 K0 h2 Y# l' I  @: F2 ^
. G0 E6 @" r/ a) d; G& oPS:附件的源码里面我默认关闭了汉字库下载到NORFLASH,如果是第一次运行程序请打开相应的宏定义加载字库。
3 y* w9 x, l- m- H; [0 w5 ?( i7 W, C4 F. W3 B. d: G( u
' [- l1 G& m% y3 f/ J
测试代码和文件:& C* Z# i' c8 a2 a( Q& Z: g$ r7 \3 l
audio.rar (3.89 MB, 下载次数: 370)
1 收藏 7 评论18 发布时间:2017-8-19 21:10

举报

18个回答
wamcncn 回答时间:2017-8-25 15:24:58
学习            
jocelynxx 回答时间:2020-12-25 08:24:10
这个为什么会显示那个stm32xx.h头文件打不开
yijuanzhi 回答时间:2019-1-21 11:30:56
谢谢分享辛苦了,先看看怎么用
netlhx 回答时间:2017-8-20 08:43:00
顶,好贴
戏如人生 回答时间:2017-8-20 18:16:08
赞一个!
andey 回答时间:2017-8-20 23:35:43
提示: 作者被禁止或删除 内容自动屏蔽
zero99 回答时间:2017-8-21 08:31:15
顶,好贴
Stm32McuLover 回答时间:2017-8-21 12:49:52

5 e2 B. K6 \, c4 w' @顶,好贴
leifeng1 回答时间:2017-8-21 23:59:39
刚好有这个开发板,回头试试
群星闪烁 回答时间:2017-8-22 11:00:37
谢谢分享,学习了
Paderboy 回答时间:2017-8-28 08:52:42
赞,刚看到。。。。支持晚了。。
张亚飞 回答时间:2017-8-28 15:17:04
不错,学习了l
cp1300 回答时间:2020-2-14 09:26:52
顶一个   
Amaker 回答时间:2020-6-28 11:49:06
谢谢分享!
zhi13750358839 回答时间:2020-9-17 11:44:00
顶,好贴
12下一页

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版