STM32F746G-Disco开发板上带有数字麦克风和音频输出,它们组合起来就可以实现助听器的功能。只要把麦克风的输入信号进行放大,然后在通过音频接口输出。9 X0 }; `' r ?8 M1 F. W5 S
+ I& h* ?/ k3 l; t下面程序演示了助听器的功能,它来自Mbed例程。首先它通过数字麦克风(U21、U22)获取环境声音,将数据保存到接收缓冲区,然后将数字音频发送到音频输出(U11)。如果我们在CN10(音频输出)上接一个耳机或者扬声器,就可以清楚的听到放大后的环境声音,效果非常不错。在连接耳机时,需要注意保护耳朵,因为开发板上没有音量控制的旋钮,不能调节音量。
2 B( |: C$ H, j: a, C. ]2 k3 X
0 L# D$ b) z! b% k$ |/ n- & P3 w7 u! ]$ V9 y" I
+ V8 [& {: \4 E; ~& t7 W* t# Y- Z- #include "mbed.h"
# ?* I" | c9 }3 _) |. Z; e - #include "AUDIO_DISCO_F746NG.h" / w- H; C3 w- I) b! M
- #include "SDRAM_DISCO_F746NG.h"
. ^* U4 V, p- w - 0 ^# v0 X( o' ^! f- [
- AUDIO_DISCO_F746NG audio; 3 d, F. H4 I, H! t/ x5 H; Z+ q3 `
- // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized
8 ^5 ]6 f2 T( p$ \8 V - // and FMC enabled & W& U4 n! o' r* x
- SDRAM_DISCO_F746NG sdram; 6 G- X& Z( C1 J
-
' [, R8 b. _8 x; [ - DigitalOut led_green(LED1);
/ f& C3 b. O7 o$ E1 P - DigitalOut led_red(LED2); - |1 j/ `/ S/ I4 C2 l
- Serial pc(USBTX, USBRX);
6 S6 F) X- D% k6 P) I - 1 V8 |, c' ~; ?, N
- typedef enum
9 g/ Q+ M# T8 Q4 @0 a. \6 h - { # f) e" Y& X) F6 ^) Y& O
- BUFFER_OFFSET_NONE = 0,
( F ]' H, V8 e. u- y# v. @. g; ` - BUFFER_OFFSET_HALF = 1, * L4 Q/ G T: _9 Q7 G/ H/ A
- BUFFER_OFFSET_FULL = 2, ^& ~0 f0 ~0 }6 u3 N* q7 y# ^: F
- }BUFFER_StateTypeDef; 5 N' E" O/ h/ `( e) ?8 X. t) M! G
- 5 o% i) f" P2 r* b9 c
- #define AUDIO_BLOCK_SIZE ((uint32_t)512) - | A0 ?9 L6 k R; N0 L
- #define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */
; L o$ F9 P8 |! u+ l: b - #define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ 4 s+ h- f) k: T- _' ~# [4 K
- __IO uint32_t audio_rec_buffer_state = BUFFER_OFFSET_NONE; 0 n2 `5 J8 H! D8 [
- static uint8_t SetSysClock_PLL_HSE_200MHz(); % \+ M* Q5 H0 p: i
- int main() ! z0 L( o( P0 l* ?9 r5 q
- { 9 D1 S1 C3 d7 |: P
- SetSysClock_PLL_HSE_200MHz(); 3 b/ ^3 ?% |- r5 c8 X' q; E
- pc.baud(9600);
+ Q# M. e Y& L4 @) B# y; j! B -
2 `7 T: u, u/ i4 h8 M( T5 z - pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n");
* @7 U1 @+ D8 D9 L - led_red = 0;
4 L" f h$ J! S3 ?% T; s9 ~4 _7 K# i -
' A6 ?* D& L: m" k+ j5 [% S - pc.printf("\nAUDIO RECORD INIT OK\n"); * `- j$ V2 d7 Z( b) ^: B
- pc.printf("Microphones sound streamed to headphones\n");
( R5 r* \1 }! O' K# |0 E% _* b -
+ S5 i' {5 n4 M) f, u - /* Initialize SDRAM buffers */
/ A+ o* I1 l: r+ S4 Z. l3 ?. { - memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
6 M/ p6 R9 t% l3 k0 {0 v# O9 P - memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
+ `; Q' @' j1 S- h& D - audio_rec_buffer_state = BUFFER_OFFSET_NONE;
2 s" w w g# C* @ -
/ \. s4 `3 L5 u - /* Start Recording */ / C+ [5 ]. Y: H
- audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); * [2 J2 ?# i/ |8 I* I9 W
-
x/ J5 N, C( H3 z, x: ]- v - /* Start Playback */
* g( x8 ^+ R9 H7 a t3 `" E [ - audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); / o, B- P; M# f& x7 J/ y+ f6 v
- audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
/ d) m3 @1 A: d- Q5 w -
0 F* y3 S9 i$ i v/ h0 U - while (1) {
& D T: [& [" c2 n/ A - /* Wait end of half block recording */ ) X" e$ y" f0 S; W' }0 E% ]+ l* e: F
- while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) {
* c2 W7 _) w8 P& B7 k9 g - } / H) k# J+ u4 ^+ m
- audio_rec_buffer_state = BUFFER_OFFSET_NONE; + ]! o/ o3 \4 ?2 T* g
- /* Copy recorded 1st half block */ 6 R3 \* @/ p2 ~* g6 X4 t. f
- memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE); 6 L0 ?5 J/ r) i% ]
- /* Wait end of one block recording */ / Q6 a' R3 Q& o
- while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { 7 i, R8 a8 e! D4 z- F+ G
- }
3 n8 x, L$ o) p' d0 p - audio_rec_buffer_state = BUFFER_OFFSET_NONE;
+ S3 S: C4 q3 \% v# R& c; h; D - /* Copy recorded 2nd half block */ ! @ d; L) F5 T t* g1 s6 m1 T
- memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN # ]/ P. s# V9 s0 j! v
- + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE); 8 [. P0 S7 `0 F* W0 ~ r2 z
- } i' _/ ]1 @! o- ^
- }
7 N3 o) `6 Y) | - /*-------------------------------------------------------------------------------------
' f( J @; j/ ^+ @ - Callbacks implementation:
9 d7 `3 m9 I9 p$ n/ ? - the callbacks API are defined __weak in the stm32746g_discovery_audio.c file
' ^8 z" t7 g% W) r7 |: [ - and their implementation should be done in the user code if they are needed.
, I3 o! E/ R) v - Below some examples of callback implementations. $ S% B# {6 C+ O0 w$ e$ K/ J
- -------------------------------------------------------------------------------------*/
) f4 n: R7 V# Z4 k; T: c8 k - /** 5 d7 u' ]: T8 v
- * @brief Manages the DMA Transfer complete interrupt. : m# _3 ]) c( M1 y0 u& G# f/ |
- * @param None
# k7 @ k9 b T8 U1 h - * @retval None
" S3 U% w5 k3 u& V6 h& z% S5 u$ m - */
+ I, w' s( n8 r* R0 ^4 U% Z - void BSP_AUDIO_IN_TransferComplete_CallBack(void) # t4 H5 ? t1 x! i' d
- { 4 [' K" B" o4 U3 ?8 i% |
- audio_rec_buffer_state = BUFFER_OFFSET_FULL; 7 h( ~) |% H9 `
- return;
! V9 A& ^, ?4 q8 X. k% b. H - }
) c r4 y) j( ^3 g/ t - ' S* }( P9 }+ O' }% W- g
- /**
! F6 }: O: j O* R, V: i( r - * @brief Manages the DMA Half Transfer complete interrupt.
8 J( G/ `7 Q7 a' s" j - * @param None
0 L. i# j" R- a! |( Z" I9 P - * @retval None # h2 z" U2 d1 z1 u* S1 g
- */
3 I+ {! I9 Y4 ^% ~ - void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 9 K' n: N$ }' |6 o4 L
- {
1 ]2 a7 @8 L# G$ X - audio_rec_buffer_state = BUFFER_OFFSET_HALF;
8 b1 V d' Z u, f& ^0 T" Z - return; / v$ u6 J6 N: ]. c' R3 a9 X) `
- }
5 x+ t$ A0 |3 \* R) }! Z
复制代码
& {7 _: \5 Z: J% F: u& i: c! \( U程序分析:. G V4 p3 s! _% `% N l
- 首先定义缓冲区大小和音频输入输出缓冲区
3 O" M1 q! i0 Y1 e+ ~; S$ f) j# u! U% O! ~, W- a' H+ r* O& ~
#define AUDIO_BLOCK_SIZE ((uint32_t)512); g: s- c: b: ]
#define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */$ Q5 c7 Z2 N* Z: ~$ g
#define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ - 然后进行初始化,初始化部分完成下面几个功能:
! r4 t( [' P$ U O' {8 y1 l! Z8 }- 分配缓冲区
7 x K& V5 T# e I* n9 z; H. s5 D /* Initialize SDRAM buffers */
# ^: N8 _% w) o memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
4 t o& @/ y: y# p memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2); - 启用录音功能,将音频输入保存到输入缓冲区 e% W5 x* U5 K5 [
/* Start Recording */8 U" y4 m# P8 ?! A1 t
audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); - 设置音频回放7 e; S* O) l6 w' n
audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);+ d3 T6 p' j1 Q7 e. w* _
audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
: L' w1 @. |2 p# a
- 在主循环中,等待音频输入完成,然后将输入缓冲区(AUDIO_BUFFER_IN)的数据复制到输出(AUDIO_BUFFER_OUT)缓冲区。音频输入的录音和回放,都是使用DMA方式自动完成的,所以无需CPU处理。+ @0 I( g: q' x: _$ I0 B* e5 R
1 S- j2 |) K$ h1 A
完整参考程序:3 q' ?# B$ U) X/ ]9 N& `. l" X
DISCO-F746NG_AUDIO_demo_uvision_disco_f746ng.zip
(1.47 MB, 下载次数: 69)
|
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
需要有源音箱吧,不然带不动