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

将STM32F746G-Disco开发板做助听器  

[复制链接]
shaoziyang 发布时间:2016-3-28 15:27
STM32F746G-Disco开发板上带有数字麦克风和音频输出,它们组合起来就可以实现助听器的功能。只要把麦克风的输入信号进行放大,然后在通过音频接口输出。9 X0 }; `' r  ?8 M1 F. W5 S

+ I& h* ?/ k3 l; t下面程序演示了助听器的功能,它来自Mbed例程。首先它通过数字麦克风(U21、U22)获取环境声音,将数据保存到接收缓冲区,然后将数字音频发送到音频输出(U11)。如果我们在CN10(音频输出)上接一个耳机或者扬声器,就可以清楚的听到放大后的环境声音,效果非常不错。在连接耳机时,需要注意保护耳朵,因为开发板上没有音量控制的旋钮,不能调节音量。
2 B( |: C$ H, j: a, C. ]2 k3 X
0 L# D$ b) z! b% k$ |/ n
  1. & P3 w7 u! ]$ V9 y" I

  2. + V8 [& {: \4 E; ~& t7 W* t# Y- Z
  3. #include "mbed.h"
    # ?* I" |  c9 }3 _) |. Z; e
  4. #include "AUDIO_DISCO_F746NG.h" / w- H; C3 w- I) b! M
  5. #include "SDRAM_DISCO_F746NG.h"
    . ^* U4 V, p- w
  6. 0 ^# v0 X( o' ^! f- [
  7. AUDIO_DISCO_F746NG audio; 3 d, F. H4 I, H! t/ x5 H; Z+ q3 `
  8. // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized
    8 ^5 ]6 f2 T( p$ \8 V
  9. // and FMC enabled & W& U4 n! o' r* x
  10. SDRAM_DISCO_F746NG sdram; 6 G- X& Z( C1 J

  11. ' [, R8 b. _8 x; [
  12. DigitalOut led_green(LED1);
    / f& C3 b. O7 o$ E1 P
  13. DigitalOut led_red(LED2); - |1 j/ `/ S/ I4 C2 l
  14. Serial pc(USBTX, USBRX);
    6 S6 F) X- D% k6 P) I
  15. 1 V8 |, c' ~; ?, N
  16. typedef enum
    9 g/ Q+ M# T8 Q4 @0 a. \6 h
  17. { # f) e" Y& X) F6 ^) Y& O
  18.     BUFFER_OFFSET_NONE = 0,
    ( F  ]' H, V8 e. u- y# v. @. g; `
  19.     BUFFER_OFFSET_HALF = 1, * L4 Q/ G  T: _9 Q7 G/ H/ A
  20.     BUFFER_OFFSET_FULL = 2,   ^& ~0 f0 ~0 }6 u3 N* q7 y# ^: F
  21. }BUFFER_StateTypeDef; 5 N' E" O/ h/ `( e) ?8 X. t) M! G
  22. 5 o% i) f" P2 r* b9 c
  23. #define AUDIO_BLOCK_SIZE   ((uint32_t)512) - |  A0 ?9 L6 k  R; N0 L
  24. #define AUDIO_BUFFER_IN     SDRAM_DEVICE_ADDR     /* In SDRAM */
    ; L  o$ F9 P8 |! u+ l: b
  25. #define AUDIO_BUFFER_OUT   (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ 4 s+ h- f) k: T- _' ~# [4 K
  26. __IO uint32_t  audio_rec_buffer_state = BUFFER_OFFSET_NONE; 0 n2 `5 J8 H! D8 [
  27. static uint8_t SetSysClock_PLL_HSE_200MHz(); % \+ M* Q5 H0 p: i
  28. int main() ! z0 L( o( P0 l* ?9 r5 q
  29. { 9 D1 S1 C3 d7 |: P
  30.     SetSysClock_PLL_HSE_200MHz(); 3 b/ ^3 ?% |- r5 c8 X' q; E
  31.     pc.baud(9600);
    + Q# M. e  Y& L4 @) B# y; j! B

  32. 2 `7 T: u, u/ i4 h8 M( T5 z
  33.     pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n");
    * @7 U1 @+ D8 D9 L
  34.     led_red = 0;
    4 L" f  h$ J! S3 ?% T; s9 ~4 _7 K# i
  35.    
    ' A6 ?* D& L: m" k+ j5 [% S
  36.     pc.printf("\nAUDIO RECORD INIT OK\n"); * `- j$ V2 d7 Z( b) ^: B
  37.     pc.printf("Microphones sound streamed to headphones\n");
    ( R5 r* \1 }! O' K# |0 E% _* b
  38.      
    + S5 i' {5 n4 M) f, u
  39.     /* Initialize SDRAM buffers */
    / A+ o* I1 l: r+ S4 Z. l3 ?. {
  40.     memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
    6 M/ p6 R9 t% l3 k0 {0 v# O9 P
  41.     memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
    + `; Q' @' j1 S- h& D
  42.     audio_rec_buffer_state = BUFFER_OFFSET_NONE;
    2 s" w  w  g# C* @

  43. / \. s4 `3 L5 u
  44.     /* Start Recording */ / C+ [5 ]. Y: H
  45.     audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); * [2 J2 ?# i/ |8 I* I9 W

  46.   x/ J5 N, C( H3 z, x: ]- v
  47.     /* Start Playback */
    * g( x8 ^+ R9 H7 a  t3 `" E  [
  48.     audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); / o, B- P; M# f& x7 J/ y+ f6 v
  49.     audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
    / d) m3 @1 A: d- Q5 w

  50. 0 F* y3 S9 i$ i  v/ h0 U
  51.     while (1) {
    & D  T: [& [" c2 n/ A
  52.         /* Wait end of half block recording */ ) X" e$ y" f0 S; W' }0 E% ]+ l* e: F
  53.         while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) {
    * c2 W7 _) w8 P& B7 k9 g
  54.         } / H) k# J+ u4 ^+ m
  55.         audio_rec_buffer_state = BUFFER_OFFSET_NONE; + ]! o/ o3 \4 ?2 T* g
  56.         /* Copy recorded 1st half block */ 6 R3 \* @/ p2 ~* g6 X4 t. f
  57.         memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE); 6 L0 ?5 J/ r) i% ]
  58.         /* Wait end of one block recording */ / Q6 a' R3 Q& o
  59.         while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { 7 i, R8 a8 e! D4 z- F+ G
  60.         }
    3 n8 x, L$ o) p' d0 p
  61.         audio_rec_buffer_state = BUFFER_OFFSET_NONE;
    + S3 S: C4 q3 \% v# R& c; h; D
  62.         /* Copy recorded 2nd half block */ ! @  d; L) F5 T  t* g1 s6 m1 T
  63.         memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN  # ]/ P. s# V9 s0 j! v
  64. + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE); 8 [. P0 S7 `0 F* W0 ~  r2 z
  65.     }   i' _/ ]1 @! o- ^
  66. }
    7 N3 o) `6 Y) |
  67. /*-------------------------------------------------------------------------------------
    ' f( J  @; j/ ^+ @
  68.        Callbacks implementation:
    9 d7 `3 m9 I9 p$ n/ ?
  69.            the callbacks API are defined __weak in the stm32746g_discovery_audio.c file
    ' ^8 z" t7 g% W) r7 |: [
  70.            and their implementation should be done in the user code if they are needed.
    , I3 o! E/ R) v
  71.            Below some examples of callback implementations. $ S% B# {6 C+ O0 w$ e$ K/ J
  72.   -------------------------------------------------------------------------------------*/
    ) f4 n: R7 V# Z4 k; T: c8 k
  73. /** 5 d7 u' ]: T8 v
  74.   * @brief Manages the DMA Transfer complete interrupt. : m# _3 ]) c( M1 y0 u& G# f/ |
  75.   * @param None
    # k7 @  k9 b  T8 U1 h
  76.   * @retval None
    " S3 U% w5 k3 u& V6 h& z% S5 u$ m
  77.   */
    + I, w' s( n8 r* R0 ^4 U% Z
  78. void BSP_AUDIO_IN_TransferComplete_CallBack(void) # t4 H5 ?  t1 x! i' d
  79. { 4 [' K" B" o4 U3 ?8 i% |
  80.   audio_rec_buffer_state = BUFFER_OFFSET_FULL; 7 h( ~) |% H9 `
  81.   return;
    ! V9 A& ^, ?4 q8 X. k% b. H
  82. }
    ) c  r4 y) j( ^3 g/ t
  83. ' S* }( P9 }+ O' }% W- g
  84. /**
    ! F6 }: O: j  O* R, V: i( r
  85.   * @brief  Manages the DMA Half Transfer complete interrupt.
    8 J( G/ `7 Q7 a' s" j
  86.   * @param  None
    0 L. i# j" R- a! |( Z" I9 P
  87.   * @retval None # h2 z" U2 d1 z1 u* S1 g
  88.   */
    3 I+ {! I9 Y4 ^% ~
  89. void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 9 K' n: N$ }' |6 o4 L
  90. {
    1 ]2 a7 @8 L# G$ X
  91.   audio_rec_buffer_state = BUFFER_OFFSET_HALF;
    8 b1 V  d' Z  u, f& ^0 T" Z
  92.   return; / v$ u6 J6 N: ]. c' R3 a9 X) `
  93. }
    5 x+ t$ A0 |3 \* R) }! Z
复制代码

& {7 _: \5 Z: J% F: u& i: c! \( U程序分析:
    . G  V4 p3 s! _% `% N  l
  • 首先定义缓冲区大小和音频输入输出缓冲区
    3 O" M1 q! i0 Y1 e+ ~; S$ f) j# u! U% O! ~, W- a' H+ r* O& ~
    #define AUDIO_BLOCK_SIZE   ((uint32_t)512); g: s- c: b: ]
    #define AUDIO_BUFFER_IN     SDRAM_DEVICE_ADDR     /* In SDRAM */$ Q5 c7 Z2 N* Z: ~$ g
    #define AUDIO_BUFFER_OUT   (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */
  • 然后进行初始化,初始化部分完成下面几个功能:
    ! r4 t( [' P$ U  O' {8 y1 l! Z8 }
    • 分配缓冲区
      7 x  K& V5 T# e  I* n9 z; H. s5 D    /* Initialize SDRAM buffers */
      # ^: N8 _% w) o    memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
      4 t  o& @/ y: y# p    memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
    • 启用录音功能,将音频输入保存到输入缓冲区  e% W5 x* U5 K5 [
          /* Start Recording */8 U" y4 m# P8 ?! A1 t
          audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE);
    • 设置音频回放7 e; S* O) l6 w' n
          audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);+ d3 T6 p' j1 Q7 e. w* _
          audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
      : L' w1 @. |2 p# a
  • 在主循环中,等待音频输入完成,然后将输入缓冲区(AUDIO_BUFFER_IN)的数据复制到输出(AUDIO_BUFFER_OUT)缓冲区。音频输入的录音和回放,都是使用DMA方式自动完成的,所以无需CPU处理。+ @0 I( g: q' x: _$ I0 B* e5 R
1 S- j2 |) K$ h1 A
完整参考程序:3 q' ?# B$ U) X/ ]9 N& `. l" X
DISCO-F746NG_AUDIO_demo_uvision_disco_f746ng.zip (1.47 MB, 下载次数: 69)

评分

参与人数 1 ST金币 +30 收起 理由
沐紫 + 30 赞一个!

查看全部评分

收藏 3 评论27 发布时间:2016-3-28 15:27

举报

27个回答
shaoziyang 回答时间:2016-3-28 15:51:39
沐紫 发表于 2016-3-28 15:33
# N& K: D: b$ j+ y$ h7 z' {谢谢楼主,有实物图或者视频演示就更好啦
* h3 z) _& ^$ q" p- C5 b$ I  J
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
liangwei 回答时间:2016-6-30 09:06:23
shaoziyang 发表于 2016-6-23 09:44
$ e9 u) T9 f% d, b; @  a! h需要有源音箱吧,不然带不动

8 u! m2 S! p% C2 l. M( U+ k% I! A不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
shaoziyang 回答时间:2016-6-23 09:44:08
weiyuliang 发表于 2016-6-22 16:54# |( ^9 \# E+ e7 j1 Z; f: Z6 r
牛,我外接喇叭为啥木声音那
/ ~: l  b& g' Q+ Q' r8 |2 y) k
需要有源音箱吧,不然带不动
沐紫 回答时间:2016-3-28 15:33:47
谢谢楼主,有实物图或者视频演示就更好啦
风子 回答时间:2016-3-28 17:50:05
看看     
DLGG-308046 回答时间:2016-3-28 21:28:03
看看学习下
macosx 回答时间:2016-3-28 23:27:29
能在 F4 上實現嗎?來學習一下!
liangwei 回答时间:2016-6-22 16:54:43
牛,我外接喇叭为啥木声音那
vitence 回答时间:2016-6-30 13:37:27
学习一下
babyfeng 回答时间:2016-7-10 22:24:33
谢谢分享 学习下
DLGG-308046 回答时间:2016-8-29 14:07:36
请教一下,程序中音频输入的录音和回放的DMA配置是怎么实现的?
zhangxu56726 回答时间:2016-8-29 15:07:40
dddddddddddddddddddddddd
涛哥2035 回答时间:2016-8-29 15:55:57
实用的是不是都是模拟的啊?
xyx365 回答时间:2016-8-30 08:46:47
学习一下
12下一页
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版