STM32F746G-Disco开发板上带有数字麦克风和音频输出,它们组合起来就可以实现助听器的功能。只要把麦克风的输入信号进行放大,然后在通过音频接口输出。; J" g8 ~' W U% Q$ y% o
6 {: @: J) z, A& h. \
下面程序演示了助听器的功能,它来自Mbed例程。首先它通过数字麦克风(U21、U22)获取环境声音,将数据保存到接收缓冲区,然后将数字音频发送到音频输出(U11)。如果我们在CN10(音频输出)上接一个耳机或者扬声器,就可以清楚的听到放大后的环境声音,效果非常不错。在连接耳机时,需要注意保护耳朵,因为开发板上没有音量控制的旋钮,不能调节音量。$ E1 \6 t+ e2 J- ~# q* ?6 q
2 q- v# c }9 a1 R( y, D& D& y( m- 0 G; q3 y) h f, m9 {4 l. ~
' c) g& n. n+ H" \9 k: q- #include "mbed.h"
% S. ^- \+ v$ S$ T. E. z - #include "AUDIO_DISCO_F746NG.h"
, e! b$ ], r1 ^7 K2 ?8 {/ r5 j6 L - #include "SDRAM_DISCO_F746NG.h" : e3 S# I$ O5 H$ R( W- D$ U/ O k
- $ O" {( n5 G1 o
- AUDIO_DISCO_F746NG audio;
. ]+ y9 r4 w% f% T+ |; Z - // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized + k' r3 [, {2 h. e0 y/ `
- // and FMC enabled ! i8 b- u- m, o9 ? v2 {8 K
- SDRAM_DISCO_F746NG sdram;
9 f+ J4 H, U% `3 w, E% p2 C! Y! ] -
' p$ d6 A m( E- `, Z% T- q6 l. u - DigitalOut led_green(LED1);
5 \ N" B0 ]' U0 u - DigitalOut led_red(LED2);
$ c5 f4 u& O1 V - Serial pc(USBTX, USBRX);
% C2 Z. w! P( ?5 R4 V. v$ V -
5 d2 }( |& q. V \8 i3 i0 E' T - typedef enum 7 e1 N' C% }4 \8 v* f
- { 5 C4 o0 A8 B5 D" t! w, |
- BUFFER_OFFSET_NONE = 0,
" S2 ~; A' |2 S, t - BUFFER_OFFSET_HALF = 1, 7 f7 j6 O& W8 w0 _
- BUFFER_OFFSET_FULL = 2, 9 _0 \% l: g: K9 q! M
- }BUFFER_StateTypeDef;
6 H: g( @! Y6 f! u9 k -
L/ F/ a7 c* e0 w( D - #define AUDIO_BLOCK_SIZE ((uint32_t)512)
, `+ ]$ v6 Z* K- P5 \2 C - #define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */
4 h# e) k3 n% h( R% L - #define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ $ d/ g& a7 L- H/ r
- __IO uint32_t audio_rec_buffer_state = BUFFER_OFFSET_NONE;
) z3 G- D( h5 l& |; f - static uint8_t SetSysClock_PLL_HSE_200MHz(); " }# o0 ]5 A/ c- b; L" [$ Q4 P
- int main() 8 P8 f- c% f8 p q
- {
& F6 r, Z8 ?7 K4 f - SetSysClock_PLL_HSE_200MHz(); ! d6 U1 T! a R! ?; m
- pc.baud(9600);
& ]+ D! p* Z; z6 u! N7 T -
$ y7 ?2 K! X# _. u0 H: K - pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n");
: k( i/ x. b `# {- g8 s - led_red = 0; 9 |6 e- P6 C7 M s
- ' z, |; H6 M% `" u( f
- pc.printf("\nAUDIO RECORD INIT OK\n");
7 m9 N! k. L7 P3 C) f* c - pc.printf("Microphones sound streamed to headphones\n");
; t Y6 a$ I+ n - - G2 u& c6 u1 M9 l- [: C6 ~! E
- /* Initialize SDRAM buffers */
2 q; P- l; X1 w8 m# h. N - memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2); ) S" h# i( ~$ m# E
- memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2); 4 X) p3 n$ m" M9 B7 ^6 V
- audio_rec_buffer_state = BUFFER_OFFSET_NONE;
& z- [3 n6 F9 P3 a, p -
$ A' h; x* H- D# D- o3 ~) ~ - /* Start Recording */ ' ~( I5 L$ U. J9 w# C. A+ J N4 L
- audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); 2 s, D& q: I9 {' o0 n. r
-
0 R$ q) H9 e% x! Q - /* Start Playback */ 8 U" K, P( t& @2 k
- audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
( ~% @! b1 A9 v, E1 g - audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
5 {2 M5 w o# m -
6 Q8 {4 _$ R1 O - while (1) { 4 f2 f5 h- e. A5 s4 h5 Q
- /* Wait end of half block recording */ - e7 J$ \3 _; a& O4 r
- while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) {
1 a: E" c+ Q9 E! J# c% X. k& ` - } ! `! n J. h P. N; l
- audio_rec_buffer_state = BUFFER_OFFSET_NONE;
3 t; H2 y: m P; L" W - /* Copy recorded 1st half block */
3 Y3 V. F f/ s% \. c8 L - memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE); & O# _8 Y/ h9 Y d6 F+ g/ B
- /* Wait end of one block recording */ , F% C: v& q) n4 Q
- while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) {
{' n/ P# @# z# V/ ] - } j4 Y6 y$ H( f6 B8 ?: w) b
- audio_rec_buffer_state = BUFFER_OFFSET_NONE;
+ _$ v& [, f0 J# a8 W+ n. E - /* Copy recorded 2nd half block */
9 C- D8 d/ I9 d" I% ~0 N# p7 J - memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN 4 o) @! e3 s' l) f6 s/ H
- + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE);
9 E+ J2 _3 z4 C - }
; g# |& Z1 F3 N' d# y3 ^ - }
o, H* n m4 q$ u4 P0 r; O. D - /*------------------------------------------------------------------------------------- , w0 a# A8 w3 @" U3 `3 l7 f4 r
- Callbacks implementation: - d: M+ q5 L6 l# b
- the callbacks API are defined __weak in the stm32746g_discovery_audio.c file
; c- Y$ T- Y D, A2 F7 J - and their implementation should be done in the user code if they are needed. / K. ^! z% U6 S# L
- Below some examples of callback implementations.
# A4 E$ L8 }, y# e - -------------------------------------------------------------------------------------*/
2 C" e' s0 f9 X" p# A - /** ' W9 x& [+ }! C" c7 t) D; C
- * @brief Manages the DMA Transfer complete interrupt.
; M$ b+ G' L+ @. ?7 W# E5 d3 ? - * @param None 8 u7 @6 @2 W1 Y1 S
- * @retval None
3 e# A7 v+ `/ ^4 \ E - */
- |( ~4 Q0 p6 P9 G& A( q - void BSP_AUDIO_IN_TransferComplete_CallBack(void) ; d) d0 R) B* e1 a& K' _5 f
- { - `0 Q' C" U: f/ c! h
- audio_rec_buffer_state = BUFFER_OFFSET_FULL;
; s2 ^: v9 s; q3 i a - return;
% Q$ Y* a! L; g4 n0 f7 _' M5 n! z/ I - }
4 ?% a* I% S6 S: Q$ ^ - % D* v7 t& ?. u% ]( L; c; k6 r2 Y0 ~
- /** 2 n# T0 s2 Z# l" r2 c1 S0 k
- * @brief Manages the DMA Half Transfer complete interrupt. 1 l; {* v/ D! I
- * @param None 7 h. Q) |; z! F2 _( h
- * @retval None ' S; w) J- w% `
- */
# D- r$ ^, z& H% b1 T - void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
u" F* R: x5 z E" o8 e, e2 m5 l - {
! W0 w6 f2 p9 w0 o. M - audio_rec_buffer_state = BUFFER_OFFSET_HALF; , o+ P3 i% {+ k! m, E* s
- return; ) s; N1 ]& Q# x& c
- }
, C1 e9 @5 I, L3 m
复制代码 ; J _/ h" o8 P/ ~0 L$ i# O0 I
程序分析:4 ?0 u2 ]9 W' [! N3 R) r8 d& T/ r% q
- 首先定义缓冲区大小和音频输入输出缓冲区
; g6 l" n1 d5 A( D K3 x
, m# i9 C+ u& L& _" F# s3 e! Y#define AUDIO_BLOCK_SIZE ((uint32_t)512)
, _* W$ U2 x V( S: d3 _& u. K#define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */
7 s/ e' b3 `( _9 @+ W#define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ - 然后进行初始化,初始化部分完成下面几个功能:
# Y% \, | Y! m1 d0 m h: d5 B- 分配缓冲区
1 |9 v$ c6 p/ m) c- P; e /* Initialize SDRAM buffers */7 x0 B4 P# P8 v4 e; y& t2 c
memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);/ k! t: Z* ]5 y6 x
memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2); - 启用录音功能,将音频输入保存到输入缓冲区- m" i# d& b3 F; d. e) S+ o9 h; S6 G7 k
/* Start Recording */6 _- i- H' T4 K. F; y, q
audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); - 设置音频回放6 y/ c* R+ ]0 @( e" l7 X
audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
6 w4 K" O0 ~/ s( {. A3 Y* B: e/ t audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
5 d- x: T @+ G0 L5 d$ T1 ?
- 在主循环中,等待音频输入完成,然后将输入缓冲区(AUDIO_BUFFER_IN)的数据复制到输出(AUDIO_BUFFER_OUT)缓冲区。音频输入的录音和回放,都是使用DMA方式自动完成的,所以无需CPU处理。
" }0 Z& A6 O5 {* l' O6 l. q$ o 9 j0 n. d$ ]7 l+ Q) D/ i7 D9 _( X
完整参考程序:9 v4 y* b- h# v1 N$ k6 e
DISCO-F746NG_AUDIO_demo_uvision_disco_f746ng.zip
(1.47 MB, 下载次数: 73)
|
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
需要有源音箱吧,不然带不动