STM32F746G-Disco开发板上带有数字麦克风和音频输出,它们组合起来就可以实现助听器的功能。只要把麦克风的输入信号进行放大,然后在通过音频接口输出。3 Z3 j( P2 g" {/ g
9 [! J8 Q' g% e2 z4 A4 m' Z下面程序演示了助听器的功能,它来自Mbed例程。首先它通过数字麦克风(U21、U22)获取环境声音,将数据保存到接收缓冲区,然后将数字音频发送到音频输出(U11)。如果我们在CN10(音频输出)上接一个耳机或者扬声器,就可以清楚的听到放大后的环境声音,效果非常不错。在连接耳机时,需要注意保护耳朵,因为开发板上没有音量控制的旋钮,不能调节音量。) n; P% I7 p/ }; E0 N/ v, f+ [
# Y7 d+ A+ H& {
% `* m! L) S( s. `& Z1 L. `' b6 M0 }9 j- / A$ m( Z+ B: ~- ]
- #include "mbed.h" : a4 p9 l% H8 O$ I6 c
- #include "AUDIO_DISCO_F746NG.h" 7 R) Y+ Y1 R/ K$ v- K
- #include "SDRAM_DISCO_F746NG.h"
& ?) l* _! P+ M( ^$ m% m( T% l -
$ a1 k3 T' n8 }/ g" h. I - AUDIO_DISCO_F746NG audio; $ b) | _$ ]+ I" I/ u
- // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized
/ M6 C7 a& B7 F7 i; q6 d c6 U - // and FMC enabled
- ]2 {3 k& B i; G0 W. x! t - SDRAM_DISCO_F746NG sdram;
* Z* y- l, r9 R; e- f0 N! ] -
5 q0 V8 E8 v! k/ Y" t. N - DigitalOut led_green(LED1);
' M3 E2 y( e0 u( P; N - DigitalOut led_red(LED2);
2 L3 _4 r* B" o2 D" f3 e- ]' v' @# K - Serial pc(USBTX, USBRX);
# A. C& t4 l* ]1 g) d& t- O - 5 C I0 b- B( X0 u/ Y* L
- typedef enum % w" f$ w i! C: M* T7 K5 M' [
- {
) I' ^2 ?6 Q, x p" M - BUFFER_OFFSET_NONE = 0,
: l) T: i" Q: L) K: ?" x) Y \! p - BUFFER_OFFSET_HALF = 1, 1 B1 ~( D# B/ U+ J; b
- BUFFER_OFFSET_FULL = 2,
! _7 y% r" z* D" K) b2 o - }BUFFER_StateTypeDef;
6 [3 Z9 }3 [& f( x/ }1 \ - $ b9 h6 S% A! C+ e
- #define AUDIO_BLOCK_SIZE ((uint32_t)512) i. U8 j, u9 r& m a+ v
- #define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */
, g8 S& C4 U2 r5 j# E7 k1 {- K - #define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ % I1 w8 k3 f' y6 ]! B, B( z& y/ h6 `4 C
- __IO uint32_t audio_rec_buffer_state = BUFFER_OFFSET_NONE;
- |' |( k* H0 A1 O, B* l4 |. f - static uint8_t SetSysClock_PLL_HSE_200MHz();
3 {" X7 F3 k6 J - int main()
$ C1 _7 T+ r) m8 X }2 r1 y - { # a$ i/ y: H: o% E
- SetSysClock_PLL_HSE_200MHz();
! a0 \- r- ?; z. u# h% o - pc.baud(9600);
2 w6 s2 P& Y# a' i6 L -
/ P4 H. D1 K/ `) Z/ N, G/ q1 \" W \ - pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n"); 7 C0 G$ X! Z5 I
- led_red = 0; 5 ~+ a: g! `' E. k9 `
- - _8 ]- Y! l) D% Q
- pc.printf("\nAUDIO RECORD INIT OK\n");
: v$ A; p1 Z0 c' { - pc.printf("Microphones sound streamed to headphones\n"); " e+ P* z7 m' F1 U, s6 L- L
-
% n9 p0 t- d, q5 D* o - /* Initialize SDRAM buffers */
9 C5 l# ~5 h1 P& C- N3 V& ^4 a - memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
" G; ~ o1 ~3 }# p' y% W, h - memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
& _. T0 b3 e' ?" V2 F - audio_rec_buffer_state = BUFFER_OFFSET_NONE; 0 @1 T+ I7 k5 M8 X( a$ W
-
, g/ l. `- I' q+ G6 U - /* Start Recording */ ; V0 t7 A2 I8 U' _7 B
- audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE);
! M8 N* Z9 a# j( f1 ~* m% ?# _' ]- z -
( y; J0 k. m$ M7 A# ^: R - /* Start Playback */
4 n& V1 S1 p$ |7 @ I& g7 n. F - audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); 0 L# O8 v1 r% J+ l! g& O
- audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2); 8 c; V2 C+ p: I. b2 [( d7 `* x( A
-
/ b0 ^1 k% D7 k/ l+ F9 ? G# H - while (1) { 3 _% N4 B8 _$ `9 f4 @" H
- /* Wait end of half block recording */
# z' Q/ ~4 @ l# O) O - while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) { ' E# {3 C: _, D+ C; z
- } 6 u H. t/ \ P; n4 y3 f R! @
- audio_rec_buffer_state = BUFFER_OFFSET_NONE; + X3 {1 k* v3 `* F% I+ S: K
- /* Copy recorded 1st half block */ - A7 K% i/ n2 ~/ W+ A8 P- J( a
- memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE);
! J$ ^" l( r2 r0 M1 t0 p" H - /* Wait end of one block recording */ / W/ W8 ~2 u2 k+ W2 F [9 m
- while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { ! e h) [# l) r9 Q0 @
- }
' ^& H: K4 T+ \" m - audio_rec_buffer_state = BUFFER_OFFSET_NONE;
! G4 N7 W: h9 l+ Z. } - /* Copy recorded 2nd half block */
; q' h; A s% R- l" Z& | - memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN ; P0 G( C! M7 x# G1 J" G
- + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE);
6 i9 F* p, L ?% x3 v - }
' E1 p, `( T# `9 {; P4 K - }
D2 [$ w. O- H, z% \2 H p - /*-------------------------------------------------------------------------------------
% J$ {6 n1 m" f6 y' e3 U, q' p - Callbacks implementation: , G$ v7 S A6 k/ D! k3 \
- the callbacks API are defined __weak in the stm32746g_discovery_audio.c file 0 M! \; ?: p" {5 Y Z' \
- and their implementation should be done in the user code if they are needed.
. K! n p( w3 X! R - Below some examples of callback implementations. % d. l8 ^- n" c' e. w# N% T
- -------------------------------------------------------------------------------------*/ 0 k: j i& A3 l: v
- /**
" C4 V1 U H; J: n - * @brief Manages the DMA Transfer complete interrupt.
/ H4 H! ~; f, d - * @param None
* W0 p: ^9 J5 [0 l - * @retval None 2 H1 Z- E; Z$ h$ x; B, n' e
- */ ) X9 ^- G1 j/ s# f4 Z
- void BSP_AUDIO_IN_TransferComplete_CallBack(void)
6 B. {1 |: M. h3 G - {
$ d2 }; A2 m: y) A. t/ [ - audio_rec_buffer_state = BUFFER_OFFSET_FULL;
; e1 _4 v9 p, P" n9 }( `! E - return;
3 ^( F; M! r8 j& E" K# ]' f( Y' M - }
, C4 c% N3 Z) t- l$ ~ -
4 N' ?4 t, j2 E6 f( q$ E - /** 2 P; L: ]& r, V8 h( |/ p, R% P
- * @brief Manages the DMA Half Transfer complete interrupt. ) _+ X3 q/ l1 v
- * @param None
2 w/ z6 E$ `& i7 j3 _" w7 p6 T% @$ A8 Z - * @retval None 3 T7 E- L! Y; c! J# U* r& A. J
- */ ; r9 X% f9 `% \. T, n* d
- void BSP_AUDIO_IN_HalfTransfer_CallBack(void) ) y! g/ u8 q# i! h% ?2 q& c- S
- { 1 W8 r' _' O1 _( y E- z
- audio_rec_buffer_state = BUFFER_OFFSET_HALF; 2 O# d7 e& a% u2 f8 `; p# _3 L1 b4 Y
- return; . w% l) G. P/ M$ E
- }( A) ^4 a4 P* k$ x1 n
复制代码
7 N: f, @/ k) B9 ^! @' u程序分析:% I, K* o% ], B0 E" H% b: \
- 首先定义缓冲区大小和音频输入输出缓冲区( J2 o4 Z) D0 a# f' |
: P$ g: j2 c; i. M
#define AUDIO_BLOCK_SIZE ((uint32_t)512)( L* B( g) Z, ?3 `
#define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */1 a4 `! ~/ Y m0 ?3 N
#define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ - 然后进行初始化,初始化部分完成下面几个功能:4 G0 w P; T( q; u! l8 I
- 分配缓冲区! P! B. P' Y6 S7 O6 n: E$ V
/* Initialize SDRAM buffers */* N+ _/ F, h+ G3 N1 h( N
memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
: h8 s9 I3 D" I0 W& w- G3 Y3 E memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2); - 启用录音功能,将音频输入保存到输入缓冲区
2 Q+ R+ A2 E! w3 |- r5 p+ |3 ], h /* Start Recording */1 B. C: T7 d9 x: Z; ?- N- K- e" X
audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); - 设置音频回放, p. a5 U1 e! |
audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);) M, j. B- ?3 e1 g2 U
audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);5 P r& {2 \6 y: o
- 在主循环中,等待音频输入完成,然后将输入缓冲区(AUDIO_BUFFER_IN)的数据复制到输出(AUDIO_BUFFER_OUT)缓冲区。音频输入的录音和回放,都是使用DMA方式自动完成的,所以无需CPU处理。* M8 O- d1 V8 L" W, z
2 B! I/ m0 F$ t t
完整参考程序:! N6 T$ d8 f0 }: Q
DISCO-F746NG_AUDIO_demo_uvision_disco_f746ng.zip
(1.47 MB, 下载次数: 69)
|
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
需要有源音箱吧,不然带不动