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

将STM32F746G-Disco开发板做助听器  

[复制链接]
shaoziyang 发布时间:2016-3-28 15:27
STM32F746G-Disco开发板上带有数字麦克风和音频输出,它们组合起来就可以实现助听器的功能。只要把麦克风的输入信号进行放大,然后在通过音频接口输出。
6 V5 |* e1 B, m, y. s( ?7 {, \& z$ ~* @  Y* V; [( m: h
下面程序演示了助听器的功能,它来自Mbed例程。首先它通过数字麦克风(U21、U22)获取环境声音,将数据保存到接收缓冲区,然后将数字音频发送到音频输出(U11)。如果我们在CN10(音频输出)上接一个耳机或者扬声器,就可以清楚的听到放大后的环境声音,效果非常不错。在连接耳机时,需要注意保护耳朵,因为开发板上没有音量控制的旋钮,不能调节音量。
, O) }% u: J% `# l. B
4 M8 o( f5 a3 R& U9 S: O; J

  1. + m: M0 X3 }) Q/ G+ N: S

  2. # I+ _8 _$ \) p0 Q
  3. #include "mbed.h"
    : W% v( e% p# M
  4. #include "AUDIO_DISCO_F746NG.h"   N+ M: q6 e/ T1 w6 t/ M6 |
  5. #include "SDRAM_DISCO_F746NG.h" / z7 }" l" w2 X4 k  t6 o
  6. ) a0 k5 O3 Z, [3 C. z
  7. AUDIO_DISCO_F746NG audio;
    3 I3 e+ P% `6 f! q; d1 V
  8. // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized * c& A" C- Y# [% X7 f. O# |
  9. // and FMC enabled
    ; H6 z- k! u* Q3 s3 S" s' e1 Y
  10. SDRAM_DISCO_F746NG sdram; : O( E$ x0 S2 |3 H& @$ w' K

  11. ! @. V9 `) C" V1 q7 v6 {! |
  12. DigitalOut led_green(LED1);
    ) e* |2 u! N- j% ]$ p# d, ^
  13. DigitalOut led_red(LED2);
    % k5 W' U. {! N, k7 C
  14. Serial pc(USBTX, USBRX);
    * b1 K/ {8 D  R* E8 j
  15. 1 `) R' S# t) E1 ?) T2 g- }) X
  16. typedef enum
      ?) s4 ~( F' ?- l6 e; M6 i6 G
  17. {
    + R6 [' W* }" c$ i* X& F7 T/ u
  18.     BUFFER_OFFSET_NONE = 0,
    " E/ e6 ^) O, R% P& d# B% s) ]
  19.     BUFFER_OFFSET_HALF = 1, $ r% z: v# c, r% ?( h
  20.     BUFFER_OFFSET_FULL = 2, / B9 A, C8 q; U  R
  21. }BUFFER_StateTypeDef;
      V1 C4 u) k! F  W# W! d8 j; C

  22. ; ~+ N" N6 i6 {+ S
  23. #define AUDIO_BLOCK_SIZE   ((uint32_t)512) % b/ e: V: J& S3 M7 p
  24. #define AUDIO_BUFFER_IN     SDRAM_DEVICE_ADDR     /* In SDRAM */ , q8 U7 K% ~8 g
  25. #define AUDIO_BUFFER_OUT   (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ $ T4 Y% [! J* t+ t! L
  26. __IO uint32_t  audio_rec_buffer_state = BUFFER_OFFSET_NONE; % t' r1 c1 m; B5 s9 c
  27. static uint8_t SetSysClock_PLL_HSE_200MHz();
    * J6 v) Y9 \0 W7 ?% N
  28. int main()
    ( z: t! Q7 b5 w5 N& ^* o
  29. {
    . k/ ^- H% K( y0 Q3 _2 p
  30.     SetSysClock_PLL_HSE_200MHz();
    ) ?6 p/ f" Y" _7 V; W( m
  31.     pc.baud(9600); . X: g4 T6 t, \( w

  32. 2 y9 K. G! {, C( X4 l/ E$ M
  33.     pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n");
    7 Q. y% L* O+ J
  34.     led_red = 0; , c% i8 q7 Q& E$ e
  35.    
    ( f6 B( @  F( |0 q4 O7 J
  36.     pc.printf("\nAUDIO RECORD INIT OK\n"); ! U* t7 w1 r- N5 e& U- q& C/ B
  37.     pc.printf("Microphones sound streamed to headphones\n"); - n, @( m  {% u( j+ G! [- x6 |  B
  38.      ; P/ k6 W5 i# S9 s0 ^6 Y
  39.     /* Initialize SDRAM buffers */ # f; R$ O0 c8 y! `3 {' p6 r
  40.     memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
    1 c6 P% L# E$ _1 ]- q
  41.     memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
    ; L, }( x+ g! ?( _
  42.     audio_rec_buffer_state = BUFFER_OFFSET_NONE; 6 O" \2 _* X& N9 @1 n9 A

  43. 4 L6 J, [3 Q. J* B8 W. Y
  44.     /* Start Recording */ & C4 G1 }5 |4 \" s7 b& ?
  45.     audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); & e; |/ R: S6 K( X% {- l7 E

  46. 1 u# e7 j. `6 Y3 K( n5 B
  47.     /* Start Playback */ 0 P& x0 @% v6 C( E2 r' C7 B+ L
  48.     audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
    # g: ~8 z6 c9 c. [
  49.     audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2); " q7 Q" F4 _2 E2 }0 A  G: M
  50. # R1 ]& d) g. I0 b% Z7 ]
  51.     while (1) { ! h( ]  z/ M* d# j& e* t2 Q# {$ e
  52.         /* Wait end of half block recording */ - r* t, i5 J8 u" A& o: U( p  J
  53.         while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) {
    . o% k* M% p, n" v
  54.         } / d- x! S( f6 v" G+ @3 a/ r
  55.         audio_rec_buffer_state = BUFFER_OFFSET_NONE; " P# o% T3 Z; I
  56.         /* Copy recorded 1st half block */ ! V: I% C& h8 I
  57.         memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE); , J) @% q* j. r4 U' z9 B1 y$ q4 ^& F
  58.         /* Wait end of one block recording */
    0 |6 j- E7 }' M4 f  W; X+ O6 d
  59.         while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { 3 I' B& `" R, d, h6 w
  60.         } 2 ~- m5 s% O! b0 I) @6 j+ x1 e% T# k
  61.         audio_rec_buffer_state = BUFFER_OFFSET_NONE;   [( D" Y, Y3 b4 c3 }1 _+ |
  62.         /* Copy recorded 2nd half block */ 4 x4 E' y* M% {' J
  63.         memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN  ( F% T% n6 o/ @
  64. + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE);
    1 `$ I1 I% {* f0 Z! |. W
  65.     }
      L3 t* S- z) M) P6 N
  66. } ( _' u+ k' v- h0 p( t3 w
  67. /*-------------------------------------------------------------------------------------
      D. P1 k* N' y. d+ ]; m# h
  68.        Callbacks implementation:
    6 V' r, B0 m* L* J, _
  69.            the callbacks API are defined __weak in the stm32746g_discovery_audio.c file
    & P) y9 z# ?( e) j
  70.            and their implementation should be done in the user code if they are needed. 6 I" P: z6 R9 H, s
  71.            Below some examples of callback implementations. 7 d6 G6 n+ ?3 \0 u* C) }- S
  72.   -------------------------------------------------------------------------------------*/
    & B$ D1 {4 B( [6 {% W2 a! W# H
  73. /**
    : x+ T9 b; ?8 c  M
  74.   * @brief Manages the DMA Transfer complete interrupt.
    . K$ W$ v( `& N1 ^# p* w) x
  75.   * @param None & @& ?9 M) v7 Y5 Q
  76.   * @retval None ( n* w& z4 [4 s0 n% J) I9 b% p
  77.   */
      E" {4 g' Z8 M* w& T
  78. void BSP_AUDIO_IN_TransferComplete_CallBack(void)
    3 a: ?# [% v7 g' V/ a, ]2 h$ j
  79. {
    - A% z2 b5 Y$ T; d
  80.   audio_rec_buffer_state = BUFFER_OFFSET_FULL;
    * K6 ~, d/ j' {* S' b4 H# `
  81.   return; / s9 v( h2 v& O7 {. l6 C( \' O
  82. } " ]! U4 N3 X) x. g
  83. 1 U- R- b) _; U) ]" C
  84. /**
    + |& C- f6 D! b# Q
  85.   * @brief  Manages the DMA Half Transfer complete interrupt.
    : d& I0 r) w6 R! ]
  86.   * @param  None ) Y, P$ ^' Y( ^2 a5 |
  87.   * @retval None
    1 U/ I5 l) i4 [6 _8 h' U5 l( K
  88.   */ ' D9 ^* B7 t; W$ }; {
  89. void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
    4 X: m" F6 P" F/ R8 Y6 V: z2 b
  90. { , T% B: ^& b2 Q: w$ c; E$ ]5 \) O( Q
  91.   audio_rec_buffer_state = BUFFER_OFFSET_HALF;
    & B9 q. h* E$ }  w3 Z# G
  92.   return;
    % l- W1 x+ Y4 @. p' h
  93. }. v1 ^6 p: Q9 C* m
复制代码

; w" Z" k9 r* [% K程序分析:
    9 z& O3 V/ S- \& M1 N6 N8 f- [
  • 首先定义缓冲区大小和音频输入输出缓冲区
    # B6 A. Z6 M, O1 o( @) J$ W# ~7 f
    , i- q1 f2 |' O7 Z2 ~#define AUDIO_BLOCK_SIZE   ((uint32_t)512)
    9 ]8 R/ {5 h/ r( P) B#define AUDIO_BUFFER_IN     SDRAM_DEVICE_ADDR     /* In SDRAM */+ \3 k. E. ?! K$ L5 x) N
    #define AUDIO_BUFFER_OUT   (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */
  • 然后进行初始化,初始化部分完成下面几个功能:
    8 V, b0 W$ i! K, x
    • 分配缓冲区9 }7 d! H  R3 |# g
          /* Initialize SDRAM buffers */
      " e* z9 D- w" g# y" x& I7 J    memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
        H2 X1 R/ a6 h/ L    memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
    • 启用录音功能,将音频输入保存到输入缓冲区  m3 ^. F& N+ S4 R/ P  R; e  V
          /* Start Recording */
      . P0 C+ `) p' u: J/ [    audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE);
    • 设置音频回放
      - I- I+ e7 b( ]; D- V    audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);% r4 B- a3 Q8 }
          audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
      - m" F. k& w- w% C5 Q& B) e! J
  • 在主循环中,等待音频输入完成,然后将输入缓冲区(AUDIO_BUFFER_IN)的数据复制到输出(AUDIO_BUFFER_OUT)缓冲区。音频输入的录音和回放,都是使用DMA方式自动完成的,所以无需CPU处理。
    $ L+ v6 a% \  Q% T) `
. H# R, G- ?+ b+ D, P6 V
完整参考程序:: t1 ^  o  X* M4 T
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
# q  e( o. |; E4 E1 I7 k( v0 |谢谢楼主,有实物图或者视频演示就更好啦
  F  h. P- P& f. G2 [  F1 n
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
liangwei 回答时间:2016-6-30 09:06:23
shaoziyang 发表于 2016-6-23 09:44
4 u! |5 t( n7 S' ~9 T0 R! O( r需要有源音箱吧,不然带不动

  w: v; B) H0 C不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
shaoziyang 回答时间:2016-6-23 09:44:08
weiyuliang 发表于 2016-6-22 16:54# I8 @' G& ]/ B. |) B
牛,我外接喇叭为啥木声音那

- r1 i  x# }+ K5 o需要有源音箱吧,不然带不动
沐紫 回答时间: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 手机版