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 {; |
9 K2 x" @* s) \, r5 z9 j0 X- / n* P4 A2 a' h2 z+ j
- #include "mbed.h"
% b- p2 R! b) c( q/ ]. D( y5 c - #include "AUDIO_DISCO_F746NG.h"
: l. C! S2 L- f+ i) Y: e" Q# E - #include "SDRAM_DISCO_F746NG.h" 4 f! f4 ?! t( W8 g- d$ m% u1 |
-
1 i: e% m6 P% d+ y - AUDIO_DISCO_F746NG audio; 8 e3 L8 b# W. T7 _/ ?6 ?) V9 T
- // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized
7 N/ U+ s* { n6 ^7 {6 K - // and FMC enabled
a4 C9 |6 @/ ~# } - SDRAM_DISCO_F746NG sdram; ! A' W# v1 G) f- R {: K% z
- ' G, h/ j) L7 J' n
- DigitalOut led_green(LED1);
7 I, E: E7 A* E4 _3 F - DigitalOut led_red(LED2);
4 \- Z: a& [* n" H& q" H/ i$ ` - Serial pc(USBTX, USBRX);
% ~6 `# m5 X+ e" s1 \ -
1 q- c ~1 F9 v: y7 Y5 ]* Q - typedef enum
, o% F* J1 ~& O) ]0 ~% @$ O9 U* J - {
7 h) x: |5 O6 M6 S/ K6 A# F - BUFFER_OFFSET_NONE = 0,
) V" w& D; N% q; `) o, j& d" D. ^ - BUFFER_OFFSET_HALF = 1, 9 k3 c& o/ b5 n7 S- `
- BUFFER_OFFSET_FULL = 2,
" J& M( l B' ?: J5 ~ - }BUFFER_StateTypeDef; 0 Q" R% s! t: ?
-
3 B: ]) @8 ?: z& d- b; @" H - #define AUDIO_BLOCK_SIZE ((uint32_t)512) ( k; J( t7 i0 b
- #define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */
! z" S3 K5 n' F; d) ]& u* V - #define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ + m# V. J2 m5 ^
- __IO uint32_t audio_rec_buffer_state = BUFFER_OFFSET_NONE; 1 P- g/ ^ S- }. p& i
- static uint8_t SetSysClock_PLL_HSE_200MHz(); * F; x. _, M9 j4 l
- int main() % G' S5 v( X. _' C
- { H0 M, R5 E& c9 r
- SetSysClock_PLL_HSE_200MHz();
1 `# X. A2 ]; w1 e& a - pc.baud(9600);
) {8 d5 {. U G: Q+ H c7 W* w -
7 n M1 P$ j5 G/ H8 k - pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n"); `. T* Q5 g' F7 u
- led_red = 0; 3 }/ A* R' K; `# u
- 0 D2 g* a6 J+ C# |$ K
- pc.printf("\nAUDIO RECORD INIT OK\n");
% c* a, j7 U: I/ a2 E - pc.printf("Microphones sound streamed to headphones\n");
' A# T& A$ D2 @9 K9 I Y - 2 a0 o# o/ H% O
- /* Initialize SDRAM buffers */ 2 b( ?2 P4 y7 V6 O: C1 a* y" n
- memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
, O1 F( L" j. y& }# N. | - memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
* Y) @. a/ _" x8 ]! h' o+ z - audio_rec_buffer_state = BUFFER_OFFSET_NONE;
" M: X4 z$ q6 s7 K! K -
0 D0 J: `+ v. s2 G( e - /* Start Recording */
3 ?" ]3 D) Y% K0 }$ d, r - audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE);
" G7 ^- q+ u# }; a' K) m, U -
1 M8 g) u2 z2 V* j# P! V - /* Start Playback */
9 i, f8 i. X$ d9 i - audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); $ `- `4 [+ f, M
- audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
8 ]+ _3 _5 b. b C -
5 n; N$ @- A6 B) H* _% @* X - while (1) {
* F1 W( j3 A4 v0 U- K: N - /* Wait end of half block recording */
4 P) X3 N/ {) F4 x* m) w; }7 c( C4 g - while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) { $ \9 \4 K$ ~/ Q% r) H' X
- }
* U9 y# U' u* s W5 V- W$ r( R - audio_rec_buffer_state = BUFFER_OFFSET_NONE;
* K' q, s. n9 X6 y- o - /* Copy recorded 1st half block */ ' R Y" A# Z6 }1 s. T7 T
- memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE);
) c7 d4 a3 q" q7 Z& u" Q8 j- S - /* Wait end of one block recording */ 3 }: v+ x6 D `. D" B i
- while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { 9 ~1 |) u- d4 L. B) W
- } 9 {& c: v% z3 l
- audio_rec_buffer_state = BUFFER_OFFSET_NONE;
4 |1 Z" _) ~0 J5 |- q5 ? - /* Copy recorded 2nd half block */
) X2 j$ | ]4 k. q* H9 T' l - 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
- + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE);
1 c [1 m0 f9 n" L - } ! S p7 w7 F! j! F
- } , ?8 j. K+ x& L- }: T# I9 O
- /*-------------------------------------------------------------------------------------
" A- K+ x/ K# p' m9 @2 T - Callbacks implementation:
2 X! `5 A% s, Y' p. c; F - the callbacks API are defined __weak in the stm32746g_discovery_audio.c file + j# P9 M$ m) t# J5 H8 U6 Z! k7 r
- and their implementation should be done in the user code if they are needed.
; n" a% [* x* ]2 G, k1 P - Below some examples of callback implementations. ( L/ X2 l" c& i( r8 N3 F7 \
- -------------------------------------------------------------------------------------*/ - X! f. M" F0 Y9 ^
- /**
6 q/ L7 I4 A2 a( j - * @brief Manages the DMA Transfer complete interrupt. : s* i- w% e; F) ^. ]
- * @param None
0 _$ c0 M/ s4 N$ a# U, F - * @retval None # C, B S7 C3 L, O4 p9 R
- */
* M2 l4 T& Q* ~& o* w) R6 C0 c - void BSP_AUDIO_IN_TransferComplete_CallBack(void)
% \9 g x2 c( s0 g" i# w - { / W: B, j. J8 Q( U2 o5 M
- audio_rec_buffer_state = BUFFER_OFFSET_FULL; - e; j4 L* T% W; W7 N
- return;
; P2 E2 b9 I8 `8 @+ } - } " ^: p& w3 T5 Z; @
- + m' {& |; s+ _# J1 T
- /** , P3 I1 x. P2 t1 _- O5 T) R
- * @brief Manages the DMA Half Transfer complete interrupt. $ k; C; H: W5 U+ @
- * @param None
7 N7 ~5 u8 z& S6 W% K+ F+ ^* V" } - * @retval None 4 n% d% o: R: ~ ?) A( k
- */
" D$ N7 F- {; }% M - void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
* P# R; a( @/ `! d% a - { ; P- ]) y& ]& H# j7 F, g& ^# s% M
- audio_rec_buffer_state = BUFFER_OFFSET_HALF;
I4 {& f6 g; j& p3 A3 B5 Y - return;
1 s' t0 N2 U0 i- R- w - }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)
|
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
需要有源音箱吧,不然带不动