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

将STM32F746G-Disco开发板做助听器  

[复制链接]
shaoziyang 发布时间:2016-3-28 15:27
STM32F746G-Disco开发板上带有数字麦克风和音频输出,它们组合起来就可以实现助听器的功能。只要把麦克风的输入信号进行放大,然后在通过音频接口输出。4 i, u4 q1 |+ h( j6 s& m: N1 w) y

, P* [7 S% I. v下面程序演示了助听器的功能,它来自Mbed例程。首先它通过数字麦克风(U21、U22)获取环境声音,将数据保存到接收缓冲区,然后将数字音频发送到音频输出(U11)。如果我们在CN10(音频输出)上接一个耳机或者扬声器,就可以清楚的听到放大后的环境声音,效果非常不错。在连接耳机时,需要注意保护耳朵,因为开发板上没有音量控制的旋钮,不能调节音量。
( {: t% C( p# _6 U% j% v+ H
. t0 q/ I/ y0 [7 |  C
  1. + H4 m1 K" k4 m. V# A
  2. 4 G: p# n$ o5 t# Z5 q) C1 c
  3. #include "mbed.h" + C2 J8 G; x  D9 N& n2 T
  4. #include "AUDIO_DISCO_F746NG.h"
    ' U! X# U+ _# B
  5. #include "SDRAM_DISCO_F746NG.h" 9 O* A! f9 B. s5 x7 U* q+ m
  6. 2 p" c  @: L; y* T
  7. AUDIO_DISCO_F746NG audio; 4 a0 z# L) ]; a6 Z' S
  8. // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized
    + {3 W5 f' n- [! V9 l" g- Y% [
  9. // and FMC enabled 0 v; P- {6 d) }# ]0 d
  10. SDRAM_DISCO_F746NG sdram; 6 K- n& ?0 S" s! V5 C

  11. 3 j' p8 D& c# h1 h/ [/ H3 L
  12. DigitalOut led_green(LED1);
    8 p$ C" z' D. y6 X% {
  13. DigitalOut led_red(LED2);
    3 ?3 P7 g( f! M7 D6 h: t
  14. Serial pc(USBTX, USBRX); * N1 {/ j7 x% _+ V! a% X% S* E- Q

  15. & Z5 j# A# ~" j9 D. t1 f3 l. N9 p
  16. typedef enum 1 _1 D$ U1 q; w  o' \
  17. {
    ; M7 _0 [1 n0 H; ]) Q$ z4 g
  18.     BUFFER_OFFSET_NONE = 0,
    ( k6 d/ T& a  B
  19.     BUFFER_OFFSET_HALF = 1,
    9 V3 f  \. X/ y& D6 T2 s. j: q
  20.     BUFFER_OFFSET_FULL = 2,
    2 R' D1 h+ t: v) a
  21. }BUFFER_StateTypeDef; ; n+ m* j6 O9 d( J

  22. 2 p( H1 u; h- q! N3 {
  23. #define AUDIO_BLOCK_SIZE   ((uint32_t)512)   @" l' [/ L3 j3 M( s: ~
  24. #define AUDIO_BUFFER_IN     SDRAM_DEVICE_ADDR     /* In SDRAM */ % b/ ~- E  x6 w9 g+ t
  25. #define AUDIO_BUFFER_OUT   (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ 1 a6 a( K5 C5 a4 D" c1 s( o
  26. __IO uint32_t  audio_rec_buffer_state = BUFFER_OFFSET_NONE; 9 N6 ]$ Y& [6 W2 |/ C
  27. static uint8_t SetSysClock_PLL_HSE_200MHz();
    & W/ Y5 y; [. U( S7 C
  28. int main()
    1 ?; K! n: P, Z4 U; g8 G' [: ]4 g
  29. { , ]. z# _# H! U( S
  30.     SetSysClock_PLL_HSE_200MHz();
    $ K/ _: X% Z* b8 F1 c
  31.     pc.baud(9600);
    - K- E4 ~# r0 W3 {7 K
  32. . n- k  {8 J7 e% k) S' q+ }
  33.     pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n"); ) Q' {) H/ w  {: d8 `: [8 G' Q
  34.     led_red = 0;
    1 q/ k: q) P& C$ y: u6 f, k
  35.    
    ) l/ J5 K4 o, }: W1 v9 O; {1 L
  36.     pc.printf("\nAUDIO RECORD INIT OK\n"); 4 _5 D# s! G) t, r! q0 \
  37.     pc.printf("Microphones sound streamed to headphones\n"); $ i+ p) P3 ^, s8 Y, y
  38.      
    ! s7 c1 Z( X  v/ I
  39.     /* Initialize SDRAM buffers */
    ! }  ?1 o9 |( ?, b
  40.     memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
    8 {! N0 F5 n1 l: u) H
  41.     memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2); 7 U4 }$ Q/ I5 I8 U+ k
  42.     audio_rec_buffer_state = BUFFER_OFFSET_NONE; 0 N7 E7 ?3 [  K# Y; w* |3 z
  43.   W' o, X1 y' @8 ~% g
  44.     /* Start Recording */ % ^8 u# B3 b- |. i  @0 ^  L
  45.     audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE);
    , X; z/ M+ j4 g0 S

  46. + F1 Q& T: R$ ^* E* A4 `9 c
  47.     /* Start Playback */
    - y0 }  L" r4 H' u
  48.     audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
    5 M) l$ g$ w; B+ O0 D& D
  49.     audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2); 8 \3 `0 d# y+ A$ Y

  50. 3 e3 u5 z0 _/ B* U
  51.     while (1) {
    1 A* o) {  X7 p% B2 ]/ ]
  52.         /* Wait end of half block recording */
    ; Z# `# T) S. ]9 E" K
  53.         while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) { : j+ f, S" W2 q" d  v
  54.         } ) O2 V$ B. E) c9 ^- l$ a
  55.         audio_rec_buffer_state = BUFFER_OFFSET_NONE;
    ( v. M8 K: |7 d
  56.         /* Copy recorded 1st half block */ " i$ \0 o0 N6 k' ]
  57.         memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE);
    8 p+ E  M' [& G' S5 z* e3 k' E
  58.         /* Wait end of one block recording */ ; f! d4 D. P6 l. t" V& l
  59.         while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { 6 L( b: D. q" G. w4 W- N
  60.         }
    2 k- z; \7 G5 ?- z( T/ H; x: F
  61.         audio_rec_buffer_state = BUFFER_OFFSET_NONE;
    ' x, O0 W. b  t9 K. P: x+ G
  62.         /* Copy recorded 2nd half block */
    ! [# x% a! @- l4 T. t
  63.         memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN  + V2 \! F/ M* T+ \$ W% o
  64. + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE); + l+ b# O2 y  L. U. s: S7 X0 e7 q4 Q
  65.     }
    2 s" z- m* e5 ^5 M
  66. } 2 ~4 T! y, W; k2 w  I1 a3 o
  67. /*-------------------------------------------------------------------------------------
    $ C. i" w% O( E1 y
  68.        Callbacks implementation:
    : A4 v1 Z& u; D) U% U
  69.            the callbacks API are defined __weak in the stm32746g_discovery_audio.c file + P' @8 E! `# F+ d: ~' n
  70.            and their implementation should be done in the user code if they are needed.
    % }5 i# N1 z2 y! I6 P* H
  71.            Below some examples of callback implementations. ' x( O, c0 X  n0 h7 o6 k% i" A
  72.   -------------------------------------------------------------------------------------*/ # r* \  q8 a8 \+ e
  73. /** / w& r2 ]) e. o( O' X, ]
  74.   * @brief Manages the DMA Transfer complete interrupt.
    8 F* C9 T  z, p) k0 N  F
  75.   * @param None & r: p4 j9 H" Q8 k  w) A
  76.   * @retval None
    $ k4 R5 m" L% r2 Q- i' W
  77.   */
    " Q( n8 x6 l# d8 F
  78. void BSP_AUDIO_IN_TransferComplete_CallBack(void)
    % q) `: d- L% r  z2 J3 g) S, [
  79. {
    ; ]+ Y& \+ ]8 O8 U
  80.   audio_rec_buffer_state = BUFFER_OFFSET_FULL; ! [  M5 z3 f  V7 e  R
  81.   return; 8 D& n% Z: c# n& l/ G6 J7 U" Y
  82. }
    ' L# u0 ^) ]2 ~3 S" ?

  83. + \/ _, e0 Y/ `  X* Q& K0 U( I7 Q9 T3 n
  84. /** ) _- j! t7 O6 T0 n+ z! `# T
  85.   * @brief  Manages the DMA Half Transfer complete interrupt.   x! q+ f) \5 ?
  86.   * @param  None
    8 X/ P* x3 I+ H3 c
  87.   * @retval None
    ! e. `* T8 j- e* ?* ]7 t! _
  88.   */
    ) T) @- v3 Z% H: E, `
  89. void BSP_AUDIO_IN_HalfTransfer_CallBack(void) , {, |, v, f4 W, O: V$ n
  90. {   f1 `$ i$ d8 Z/ X/ C- {
  91.   audio_rec_buffer_state = BUFFER_OFFSET_HALF; , ^4 l( a% K; @7 G5 f
  92.   return; : ~) F3 h: ^1 {' c
  93. }1 ~: Q: E  Q6 i1 x; k+ o, L
复制代码
6 S( l) I" ?6 l4 }
程序分析:
    " t: e: n8 h5 w5 K7 F$ m
  • 首先定义缓冲区大小和音频输入输出缓冲区
    / Q; }7 i1 c/ z5 ]1 g7 {; i1 e* L4 t: b* _* c( P) }
    #define AUDIO_BLOCK_SIZE   ((uint32_t)512)
    & q+ J4 P- k9 ~7 D7 u9 m' |#define AUDIO_BUFFER_IN     SDRAM_DEVICE_ADDR     /* In SDRAM */
    1 I! @0 t2 c. s5 h! j7 I" J#define AUDIO_BUFFER_OUT   (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */
  • 然后进行初始化,初始化部分完成下面几个功能:
    % [# s- Y7 n- u- B$ p8 b
    • 分配缓冲区
      " r/ n+ W+ K' H    /* Initialize SDRAM buffers */# P; ~1 ^# k$ ~. S' G
          memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);# |  v$ n" M9 P! y' @1 i
          memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
    • 启用录音功能,将音频输入保存到输入缓冲区3 s) E/ H3 U% d2 @/ A8 C$ H, I
          /* Start Recording */
      4 `: C+ |% n) w+ |, X* n4 s    audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE);
    • 设置音频回放( O: R; X7 i/ A* _1 Q
          audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
      " Q1 u1 k5 T4 \) D- N5 y* u& d    audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);) _$ Z+ ~. _' s& P
  • 在主循环中,等待音频输入完成,然后将输入缓冲区(AUDIO_BUFFER_IN)的数据复制到输出(AUDIO_BUFFER_OUT)缓冲区。音频输入的录音和回放,都是使用DMA方式自动完成的,所以无需CPU处理。4 o: ^" q3 q2 c; g! f

4 {  D' Y/ l% v3 G# K& d4 M完整参考程序:
9 H4 j$ W- M3 K2 h: d0 B) W DISCO-F746NG_AUDIO_demo_uvision_disco_f746ng.zip (1.47 MB, 下载次数: 72)

评分

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

查看全部评分

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

举报

27个回答
shaoziyang 回答时间:2016-3-28 15:51:39
沐紫 发表于 2016-3-28 15:33  p3 b) a5 B& f' S! ^) A8 c
谢谢楼主,有实物图或者视频演示就更好啦
0 u. t2 t+ L  W) Q- s2 I
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
liangwei 回答时间:2016-6-30 09:06:23
shaoziyang 发表于 2016-6-23 09:44
1 k( Z) o- Q; G6 O  K. v2 `2 H6 E需要有源音箱吧,不然带不动

# @/ h$ z6 w# C+ [7 |; l2 o不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
shaoziyang 回答时间:2016-6-23 09:44:08
weiyuliang 发表于 2016-6-22 16:54' m9 {, D8 G$ T! W; }# v- O
牛,我外接喇叭为啥木声音那
2 L/ O) W' f" }7 x0 P
需要有源音箱吧,不然带不动
沐紫 回答时间: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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版