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
+ m: M0 X3 }) Q/ G+ N: S
# I+ _8 _$ \) p0 Q- #include "mbed.h"
: W% v( e% p# M - #include "AUDIO_DISCO_F746NG.h" N+ M: q6 e/ T1 w6 t/ M6 |
- #include "SDRAM_DISCO_F746NG.h" / z7 }" l" w2 X4 k t6 o
- ) a0 k5 O3 Z, [3 C. z
- AUDIO_DISCO_F746NG audio;
3 I3 e+ P% `6 f! q; d1 V - // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized * c& A" C- Y# [% X7 f. O# |
- // and FMC enabled
; H6 z- k! u* Q3 s3 S" s' e1 Y - SDRAM_DISCO_F746NG sdram; : O( E$ x0 S2 |3 H& @$ w' K
-
! @. V9 `) C" V1 q7 v6 {! | - DigitalOut led_green(LED1);
) e* |2 u! N- j% ]$ p# d, ^ - DigitalOut led_red(LED2);
% k5 W' U. {! N, k7 C - Serial pc(USBTX, USBRX);
* b1 K/ {8 D R* E8 j - 1 `) R' S# t) E1 ?) T2 g- }) X
- typedef enum
?) s4 ~( F' ?- l6 e; M6 i6 G - {
+ R6 [' W* }" c$ i* X& F7 T/ u - BUFFER_OFFSET_NONE = 0,
" E/ e6 ^) O, R% P& d# B% s) ] - BUFFER_OFFSET_HALF = 1, $ r% z: v# c, r% ?( h
- BUFFER_OFFSET_FULL = 2, / B9 A, C8 q; U R
- }BUFFER_StateTypeDef;
V1 C4 u) k! F W# W! d8 j; C -
; ~+ N" N6 i6 {+ S - #define AUDIO_BLOCK_SIZE ((uint32_t)512) % b/ e: V: J& S3 M7 p
- #define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */ , q8 U7 K% ~8 g
- #define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ $ T4 Y% [! J* t+ t! L
- __IO uint32_t audio_rec_buffer_state = BUFFER_OFFSET_NONE; % t' r1 c1 m; B5 s9 c
- static uint8_t SetSysClock_PLL_HSE_200MHz();
* J6 v) Y9 \0 W7 ?% N - int main()
( z: t! Q7 b5 w5 N& ^* o - {
. k/ ^- H% K( y0 Q3 _2 p - SetSysClock_PLL_HSE_200MHz();
) ?6 p/ f" Y" _7 V; W( m - pc.baud(9600); . X: g4 T6 t, \( w
-
2 y9 K. G! {, C( X4 l/ E$ M - pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n");
7 Q. y% L* O+ J - led_red = 0; , c% i8 q7 Q& E$ e
-
( f6 B( @ F( |0 q4 O7 J - pc.printf("\nAUDIO RECORD INIT OK\n"); ! U* t7 w1 r- N5 e& U- q& C/ B
- pc.printf("Microphones sound streamed to headphones\n"); - n, @( m {% u( j+ G! [- x6 | B
- ; P/ k6 W5 i# S9 s0 ^6 Y
- /* Initialize SDRAM buffers */ # f; R$ O0 c8 y! `3 {' p6 r
- memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);
1 c6 P% L# E$ _1 ]- q - memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2);
; L, }( x+ g! ?( _ - audio_rec_buffer_state = BUFFER_OFFSET_NONE; 6 O" \2 _* X& N9 @1 n9 A
-
4 L6 J, [3 Q. J* B8 W. Y - /* Start Recording */ & C4 G1 }5 |4 \" s7 b& ?
- audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); & e; |/ R: S6 K( X% {- l7 E
-
1 u# e7 j. `6 Y3 K( n5 B - /* Start Playback */ 0 P& x0 @% v6 C( E2 r' C7 B+ L
- audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
# g: ~8 z6 c9 c. [ - audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2); " q7 Q" F4 _2 E2 }0 A G: M
- # R1 ]& d) g. I0 b% Z7 ]
- while (1) { ! h( ] z/ M* d# j& e* t2 Q# {$ e
- /* Wait end of half block recording */ - r* t, i5 J8 u" A& o: U( p J
- while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) {
. o% k* M% p, n" v - } / d- x! S( f6 v" G+ @3 a/ r
- audio_rec_buffer_state = BUFFER_OFFSET_NONE; " P# o% T3 Z; I
- /* Copy recorded 1st half block */ ! V: I% C& h8 I
- memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE); , J) @% q* j. r4 U' z9 B1 y$ q4 ^& F
- /* Wait end of one block recording */
0 |6 j- E7 }' M4 f W; X+ O6 d - while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { 3 I' B& `" R, d, h6 w
- } 2 ~- m5 s% O! b0 I) @6 j+ x1 e% T# k
- audio_rec_buffer_state = BUFFER_OFFSET_NONE; [( D" Y, Y3 b4 c3 }1 _+ |
- /* Copy recorded 2nd half block */ 4 x4 E' y* M% {' J
- memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN ( F% T% n6 o/ @
- + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE);
1 `$ I1 I% {* f0 Z! |. W - }
L3 t* S- z) M) P6 N - } ( _' u+ k' v- h0 p( t3 w
- /*-------------------------------------------------------------------------------------
D. P1 k* N' y. d+ ]; m# h - Callbacks implementation:
6 V' r, B0 m* L* J, _ - the callbacks API are defined __weak in the stm32746g_discovery_audio.c file
& P) y9 z# ?( e) j - and their implementation should be done in the user code if they are needed. 6 I" P: z6 R9 H, s
- Below some examples of callback implementations. 7 d6 G6 n+ ?3 \0 u* C) }- S
- -------------------------------------------------------------------------------------*/
& B$ D1 {4 B( [6 {% W2 a! W# H - /**
: x+ T9 b; ?8 c M - * @brief Manages the DMA Transfer complete interrupt.
. K$ W$ v( `& N1 ^# p* w) x - * @param None & @& ?9 M) v7 Y5 Q
- * @retval None ( n* w& z4 [4 s0 n% J) I9 b% p
- */
E" {4 g' Z8 M* w& T - void BSP_AUDIO_IN_TransferComplete_CallBack(void)
3 a: ?# [% v7 g' V/ a, ]2 h$ j - {
- A% z2 b5 Y$ T; d - audio_rec_buffer_state = BUFFER_OFFSET_FULL;
* K6 ~, d/ j' {* S' b4 H# ` - return; / s9 v( h2 v& O7 {. l6 C( \' O
- } " ]! U4 N3 X) x. g
- 1 U- R- b) _; U) ]" C
- /**
+ |& C- f6 D! b# Q - * @brief Manages the DMA Half Transfer complete interrupt.
: d& I0 r) w6 R! ] - * @param None ) Y, P$ ^' Y( ^2 a5 |
- * @retval None
1 U/ I5 l) i4 [6 _8 h' U5 l( K - */ ' D9 ^* B7 t; W$ }; {
- void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
4 X: m" F6 P" F/ R8 Y6 V: z2 b - { , T% B: ^& b2 Q: w$ c; E$ ]5 \) O( Q
- audio_rec_buffer_state = BUFFER_OFFSET_HALF;
& B9 q. h* E$ } w3 Z# G - return;
% l- W1 x+ Y4 @. p' h - }. 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)
|
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
需要有源音箱吧,不然带不动