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

将STM32F746G-Disco开发板做助听器  

[复制链接]
shaoziyang 发布时间:2016-3-28 15:27
STM32F746G-Disco开发板上带有数字麦克风和音频输出,它们组合起来就可以实现助听器的功能。只要把麦克风的输入信号进行放大,然后在通过音频接口输出。5 Q# y- ]: L: C+ B/ d3 \4 V! [! d

* B% q& [7 f" s5 \& R下面程序演示了助听器的功能,它来自Mbed例程。首先它通过数字麦克风(U21、U22)获取环境声音,将数据保存到接收缓冲区,然后将数字音频发送到音频输出(U11)。如果我们在CN10(音频输出)上接一个耳机或者扬声器,就可以清楚的听到放大后的环境声音,效果非常不错。在连接耳机时,需要注意保护耳朵,因为开发板上没有音量控制的旋钮,不能调节音量。
2 I- A% `' `0 E# u: H( D/ ~* z9 }- H7 B  P  {; |

  1. 9 K2 x" @* s) \, r5 z9 j0 X
  2. / n* P4 A2 a' h2 z+ j
  3. #include "mbed.h"
    % b- p2 R! b) c( q/ ]. D( y5 c
  4. #include "AUDIO_DISCO_F746NG.h"
    : l. C! S2 L- f+ i) Y: e" Q# E
  5. #include "SDRAM_DISCO_F746NG.h" 4 f! f4 ?! t( W8 g- d$ m% u1 |

  6. 1 i: e% m6 P% d+ y
  7. AUDIO_DISCO_F746NG audio; 8 e3 L8 b# W. T7 _/ ?6 ?) V9 T
  8. // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized
    7 N/ U+ s* {  n6 ^7 {6 K
  9. // and FMC enabled
      a4 C9 |6 @/ ~# }
  10. SDRAM_DISCO_F746NG sdram; ! A' W# v1 G) f- R  {: K% z
  11. ' G, h/ j) L7 J' n
  12. DigitalOut led_green(LED1);
    7 I, E: E7 A* E4 _3 F
  13. DigitalOut led_red(LED2);
    4 \- Z: a& [* n" H& q" H/ i$ `
  14. Serial pc(USBTX, USBRX);
    % ~6 `# m5 X+ e" s1 \

  15. 1 q- c  ~1 F9 v: y7 Y5 ]* Q
  16. typedef enum
    , o% F* J1 ~& O) ]0 ~% @$ O9 U* J
  17. {
    7 h) x: |5 O6 M6 S/ K6 A# F
  18.     BUFFER_OFFSET_NONE = 0,
    ) V" w& D; N% q; `) o, j& d" D. ^
  19.     BUFFER_OFFSET_HALF = 1, 9 k3 c& o/ b5 n7 S- `
  20.     BUFFER_OFFSET_FULL = 2,
    " J& M( l  B' ?: J5 ~
  21. }BUFFER_StateTypeDef; 0 Q" R% s! t: ?

  22. 3 B: ]) @8 ?: z& d- b; @" H
  23. #define AUDIO_BLOCK_SIZE   ((uint32_t)512) ( k; J( t7 i0 b
  24. #define AUDIO_BUFFER_IN     SDRAM_DEVICE_ADDR     /* In SDRAM */
    ! z" S3 K5 n' F; d) ]& u* V
  25. #define AUDIO_BUFFER_OUT   (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ + m# V. J2 m5 ^
  26. __IO uint32_t  audio_rec_buffer_state = BUFFER_OFFSET_NONE; 1 P- g/ ^  S- }. p& i
  27. static uint8_t SetSysClock_PLL_HSE_200MHz(); * F; x. _, M9 j4 l
  28. int main() % G' S5 v( X. _' C
  29. {   H0 M, R5 E& c9 r
  30.     SetSysClock_PLL_HSE_200MHz();
    1 `# X. A2 ]; w1 e& a
  31.     pc.baud(9600);
    ) {8 d5 {. U  G: Q+ H  c7 W* w

  32. 7 n  M1 P$ j5 G/ H8 k
  33.     pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n");   `. T* Q5 g' F7 u
  34.     led_red = 0; 3 }/ A* R' K; `# u
  35.    0 D2 g* a6 J+ C# |$ K
  36.     pc.printf("\nAUDIO RECORD INIT OK\n");
    % c* a, j7 U: I/ a2 E
  37.     pc.printf("Microphones sound streamed to headphones\n");
    ' A# T& A$ D2 @9 K9 I  Y
  38.      2 a0 o# o/ H% O
  39.     /* Initialize SDRAM buffers */ 2 b( ?2 P4 y7 V6 O: C1 a* y" n
  40.     memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
    , O1 F( L" j. y& }# N. |
  41.     memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
    * Y) @. a/ _" x8 ]! h' o+ z
  42.     audio_rec_buffer_state = BUFFER_OFFSET_NONE;
    " M: X4 z$ q6 s7 K! K

  43. 0 D0 J: `+ v. s2 G( e
  44.     /* Start Recording */
    3 ?" ]3 D) Y% K0 }$ d, r
  45.     audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE);
    " G7 ^- q+ u# }; a' K) m, U

  46. 1 M8 g) u2 z2 V* j# P! V
  47.     /* Start Playback */
    9 i, f8 i. X$ d9 i
  48.     audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); $ `- `4 [+ f, M
  49.     audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
    8 ]+ _3 _5 b. b  C

  50. 5 n; N$ @- A6 B) H* _% @* X
  51.     while (1) {
    * F1 W( j3 A4 v0 U- K: N
  52.         /* Wait end of half block recording */
    4 P) X3 N/ {) F4 x* m) w; }7 c( C4 g
  53.         while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) { $ \9 \4 K$ ~/ Q% r) H' X
  54.         }
    * U9 y# U' u* s  W5 V- W$ r( R
  55.         audio_rec_buffer_state = BUFFER_OFFSET_NONE;
    * K' q, s. n9 X6 y- o
  56.         /* Copy recorded 1st half block */ ' R  Y" A# Z6 }1 s. T7 T
  57.         memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE);
    ) c7 d4 a3 q" q7 Z& u" Q8 j- S
  58.         /* Wait end of one block recording */ 3 }: v+ x6 D  `. D" B  i
  59.         while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { 9 ~1 |) u- d4 L. B) W
  60.         } 9 {& c: v% z3 l
  61.         audio_rec_buffer_state = BUFFER_OFFSET_NONE;
    4 |1 Z" _) ~0 J5 |- q5 ?
  62.         /* Copy recorded 2nd half block */
    ) X2 j$ |  ]4 k. q* H9 T' l
  63.         memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN  & S  J0 g. m5 D8 M: H3 B, U7 ~2 d4 K
  64. + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE);
    1 c  [1 m0 f9 n" L
  65.     } ! S  p7 w7 F! j! F
  66. } , ?8 j. K+ x& L- }: T# I9 O
  67. /*-------------------------------------------------------------------------------------
    " A- K+ x/ K# p' m9 @2 T
  68.        Callbacks implementation:
    2 X! `5 A% s, Y' p. c; F
  69.            the callbacks API are defined __weak in the stm32746g_discovery_audio.c file + j# P9 M$ m) t# J5 H8 U6 Z! k7 r
  70.            and their implementation should be done in the user code if they are needed.
    ; n" a% [* x* ]2 G, k1 P
  71.            Below some examples of callback implementations. ( L/ X2 l" c& i( r8 N3 F7 \
  72.   -------------------------------------------------------------------------------------*/ - X! f. M" F0 Y9 ^
  73. /**
    6 q/ L7 I4 A2 a( j
  74.   * @brief Manages the DMA Transfer complete interrupt. : s* i- w% e; F) ^. ]
  75.   * @param None
    0 _$ c0 M/ s4 N$ a# U, F
  76.   * @retval None # C, B  S7 C3 L, O4 p9 R
  77.   */
    * M2 l4 T& Q* ~& o* w) R6 C0 c
  78. void BSP_AUDIO_IN_TransferComplete_CallBack(void)
    % \9 g  x2 c( s0 g" i# w
  79. { / W: B, j. J8 Q( U2 o5 M
  80.   audio_rec_buffer_state = BUFFER_OFFSET_FULL; - e; j4 L* T% W; W7 N
  81.   return;
    ; P2 E2 b9 I8 `8 @+ }
  82. } " ^: p& w3 T5 Z; @
  83. + m' {& |; s+ _# J1 T
  84. /** , P3 I1 x. P2 t1 _- O5 T) R
  85.   * @brief  Manages the DMA Half Transfer complete interrupt. $ k; C; H: W5 U+ @
  86.   * @param  None
    7 N7 ~5 u8 z& S6 W% K+ F+ ^* V" }
  87.   * @retval None 4 n% d% o: R: ~  ?) A( k
  88.   */
    " D$ N7 F- {; }% M
  89. void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
    * P# R; a( @/ `! d% a
  90. { ; P- ]) y& ]& H# j7 F, g& ^# s% M
  91.   audio_rec_buffer_state = BUFFER_OFFSET_HALF;
      I4 {& f6 g; j& p3 A3 B5 Y
  92.   return;
    1 s' t0 N2 U0 i- R- w
  93. }8 o- s1 d' n2 f+ y5 ]3 f8 w1 K
复制代码
4 s1 W/ \$ M9 K
程序分析:

    - z' R2 j$ m. B. g: W
  • 首先定义缓冲区大小和音频输入输出缓冲区
      D* D* Z* j" N, t1 Z
    & T) `  b3 q9 I% i$ p/ x6 V#define AUDIO_BLOCK_SIZE   ((uint32_t)512)( ]# K0 M/ Z. Z6 }
    #define AUDIO_BUFFER_IN     SDRAM_DEVICE_ADDR     /* In SDRAM */
    ( G; |1 ]& `! }2 p% R* l#define AUDIO_BUFFER_OUT   (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */
  • 然后进行初始化,初始化部分完成下面几个功能:
    * P' e8 g1 o* g2 s4 @
    • 分配缓冲区% {1 P* \1 R( r& _5 @$ c1 v% @% n+ n
          /* Initialize SDRAM buffers */
      4 L. T& K+ {, b) @7 L: H9 R    memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);- f9 f, K1 f: M7 T" T) O
          memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
    • 启用录音功能,将音频输入保存到输入缓冲区* ]% N8 D$ M0 J' a
          /* Start Recording */; _- a% h# e" ^5 g1 `
          audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE);
    • 设置音频回放
      # B* g5 p' q3 a9 l/ [, J    audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
      % ?$ ~& V+ l7 W& w" k  p    audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);; W* v) ~. B  R! w0 O: i3 R
  • 在主循环中,等待音频输入完成,然后将输入缓冲区(AUDIO_BUFFER_IN)的数据复制到输出(AUDIO_BUFFER_OUT)缓冲区。音频输入的录音和回放,都是使用DMA方式自动完成的,所以无需CPU处理。; I: E- |6 r$ a% h0 s
, q* i5 M/ i: o, }5 w6 c
完整参考程序:
. ~( B5 d( A& n5 Y) c6 V+ H DISCO-F746NG_AUDIO_demo_uvision_disco_f746ng.zip (1.47 MB, 下载次数: 73)

评分

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

查看全部评分

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

举报

27个回答
shaoziyang 回答时间:2016-3-28 15:51:39
沐紫 发表于 2016-3-28 15:33
3 _% f- I& T4 a7 l" f谢谢楼主,有实物图或者视频演示就更好啦
$ F/ f! w( h, b) ]- B7 ?! y% @/ v. \
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
liangwei 回答时间:2016-6-30 09:06:23
shaoziyang 发表于 2016-6-23 09:44
; j. Y6 r) \8 h  N需要有源音箱吧,不然带不动
/ o' R7 ^( l! z8 Q4 p* |
不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
shaoziyang 回答时间:2016-6-23 09:44:08
weiyuliang 发表于 2016-6-22 16:54
3 V, e: W: C0 ~  R, Z; d, u4 S2 R牛,我外接喇叭为啥木声音那
/ I; D% k: ^5 t+ G5 B
需要有源音箱吧,不然带不动
沐紫 回答时间: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管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版