STM32F746G-Disco开发板上带有数字麦克风和音频输出,它们组合起来就可以实现助听器的功能。只要把麦克风的输入信号进行放大,然后在通过音频接口输出。$ f$ X9 v* p$ G
5 V1 J# ]( y, L+ m# V. n下面程序演示了助听器的功能,它来自Mbed例程。首先它通过数字麦克风(U21、U22)获取环境声音,将数据保存到接收缓冲区,然后将数字音频发送到音频输出(U11)。如果我们在CN10(音频输出)上接一个耳机或者扬声器,就可以清楚的听到放大后的环境声音,效果非常不错。在连接耳机时,需要注意保护耳朵,因为开发板上没有音量控制的旋钮,不能调节音量。4 `/ N- `1 m: ]6 ?8 S
' f, ] N1 g; a0 ?
- . A/ G$ E% R, w: A! ]7 d& g8 S# S
) b& K- N) A5 j' J; o- #include "mbed.h" 8 R9 h2 V& X Z/ g5 x7 ?. a% z
- #include "AUDIO_DISCO_F746NG.h" 2 g5 q6 w I: _; {. s; D j
- #include "SDRAM_DISCO_F746NG.h"
. H$ K; _& o7 T/ I+ X% U+ \' ^ -
5 E- F$ B( y) C3 Y - AUDIO_DISCO_F746NG audio;
; q1 z- y& P" R; { - // audio IN_OUT buffer is stored in the SDRAM, SDRAM needs to be initialized
, `! g# l, |( g. g' T% W! P/ ? - // and FMC enabled
( }& ~7 N' t3 ]$ b9 L9 Z - SDRAM_DISCO_F746NG sdram;
$ m! \) K3 I- |6 |& U - * x+ \' d( W$ R8 y, ~9 c
- DigitalOut led_green(LED1); @/ X6 V7 T: C9 v1 `) N1 }- B9 E( S
- DigitalOut led_red(LED2); 3 S, R3 h) {+ i6 C- C/ o
- Serial pc(USBTX, USBRX);
7 L& V1 O) O8 U$ i - 2 p& t6 @( c O+ u( q# c G
- typedef enum 8 Q+ E& a, R7 I. a0 f
- { 3 }& L& r8 t$ I0 c; D
- BUFFER_OFFSET_NONE = 0, 9 @4 m2 N6 @5 c: t
- BUFFER_OFFSET_HALF = 1, $ `9 W3 T8 _' h8 |( U
- BUFFER_OFFSET_FULL = 2, 1 r: |0 I. t/ o
- }BUFFER_StateTypeDef; % f5 n* w- K1 J1 m" ?- |8 n
-
5 N& Z# j9 @5 B9 R - #define AUDIO_BLOCK_SIZE ((uint32_t)512) : j9 }6 G3 w9 t" h( M' d
- #define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */
: Q" v8 D8 K$ n: m& k( q# N - #define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ 3 O2 K- y \- _2 {- L: l3 o
- __IO uint32_t audio_rec_buffer_state = BUFFER_OFFSET_NONE; 9 Y7 U" o. a* }# S* u: A7 e5 v
- static uint8_t SetSysClock_PLL_HSE_200MHz();
" V( `( r; j3 x5 _6 s2 [ - int main() ' y6 A$ p5 e3 h `( `, B+ u
- {
) V7 _6 ]/ d/ H - SetSysClock_PLL_HSE_200MHz();
( u9 t5 Q+ I, {4 T" C5 p% @3 ` - pc.baud(9600); 7 U8 ~2 D7 ]5 K$ x7 E# P$ ~9 E
-
% o- r! j8 e$ z5 r - pc.printf("\n\nAUDIO LOOPBACK EXAMPLE START:\n"); $ @ Q8 Z+ P9 u; M: [( N
- led_red = 0;
2 F# M6 |4 d2 n8 u; ^ - # L3 g( v, A8 v
- pc.printf("\nAUDIO RECORD INIT OK\n"); " p# g9 O a) h7 _1 [& h) e
- pc.printf("Microphones sound streamed to headphones\n");
. \: G( g, |& K# \# f4 |% ? -
/ S7 e/ D4 _# J: U5 o - /* Initialize SDRAM buffers */
- M) g& H: j. k6 H2 {& k - memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2); 3 r2 n. H, c9 |# g
- memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2); 7 y5 }. v, f; [6 |) Q/ N
- audio_rec_buffer_state = BUFFER_OFFSET_NONE;
3 G2 v% k$ q0 Z: F2 T/ E- R - ' d! j! t/ s( ]: h
- /* Start Recording */ / F! q3 {) v: c: Y
- audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); , [! r& N& w* a+ x$ B6 Y+ b6 z
- 2 E. m6 c4 X7 L# R# [
- /* Start Playback */ 7 ~" |" K; |" u% _; _2 ^- A% g
- audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);
3 a% w) L; X6 H! k$ R. J) e, s - audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
5 e( q' [ G; T9 z8 [$ Z- I - 1 C+ t" D8 C/ K" M+ L4 Z# `3 U J
- while (1) {
+ z0 A; `& h6 ?% `. C8 d - /* Wait end of half block recording */ / C6 Z7 z( Z x5 E( b& S S/ S2 b
- while(audio_rec_buffer_state == BUFFER_OFFSET_HALF) { % Q5 o; Y' x/ g% l9 S3 \$ N! Q
- } 2 v. g4 K1 c! S/ N
- audio_rec_buffer_state = BUFFER_OFFSET_NONE; 8 Q* Q/ `% m# Q2 ~- Q( S
- /* Copy recorded 1st half block */ / [% l0 l1 g+ |* H
- memcpy((uint16_t *)(AUDIO_BUFFER_OUT), (uint16_t *)(AUDIO_BUFFER_IN), AUDIO_BLOCK_SIZE); / g, B5 m! y6 T2 k$ D
- /* Wait end of one block recording */ # L8 G5 e: O9 N. `2 N9 b+ @4 `
- while(audio_rec_buffer_state == BUFFER_OFFSET_FULL) { ; Q. ^9 K: S/ U( M# v0 L) y
- }
: L' T2 v; G' K( |$ W - audio_rec_buffer_state = BUFFER_OFFSET_NONE; 6 E8 W3 r% j- V, D. Z2 `1 r
- /* Copy recorded 2nd half block */
$ |% t; g1 O1 e$ L, M - memcpy((uint16_t *)(AUDIO_BUFFER_OUT + (AUDIO_BLOCK_SIZE)), (uint16_t *)(AUDIO_BUFFER_IN % h2 W8 E+ G$ d3 U
- + (AUDIO_BLOCK_SIZE)), AUDIO_BLOCK_SIZE);
$ n9 e( r5 t+ G# f, e, C1 ]! F - }
4 u8 R& i! F1 _$ [# M- j- E! z - }
. a2 b7 Z" `: d$ S- A2 f$ r - /*------------------------------------------------------------------------------------- - @: m l) }: W/ L6 W4 b- j. s% h
- Callbacks implementation:
/ D% W5 Z2 S ~( |1 c8 L6 [/ n - the callbacks API are defined __weak in the stm32746g_discovery_audio.c file + n7 S+ x1 L4 D; R! b5 l2 t( }
- and their implementation should be done in the user code if they are needed. ' t: |7 M9 j) f+ A8 v- Z
- Below some examples of callback implementations. 5 O5 h6 Z% S% C
- -------------------------------------------------------------------------------------*/ 7 v/ b1 f/ y) ^" B
- /** ) Q/ B$ m7 E5 h4 \7 e
- * @brief Manages the DMA Transfer complete interrupt. 4 Z/ f5 g6 V Z
- * @param None ) b: Y2 Q2 j. S. W' b$ S5 I
- * @retval None ! W3 k* J2 b' \& d
- */ * H2 @- H N( V! P F$ u
- void BSP_AUDIO_IN_TransferComplete_CallBack(void)
. I/ k- e4 H1 S# } ^8 j - {
, z7 k' G0 @8 K9 m4 b' F - audio_rec_buffer_state = BUFFER_OFFSET_FULL;
# @. x+ f6 u) g J - return; ! J R% D! W; E! t0 K
- }
/ B/ J1 m3 a1 I: `1 ~4 y - : d# U& ?7 j7 s5 s
- /** $ f' f" l1 z& D/ t1 A# h
- * @brief Manages the DMA Half Transfer complete interrupt.
, B* w1 @; E. @ - * @param None ' M; N2 w: R- {1 h7 t
- * @retval None 1 c5 k+ T$ Y* M( F; q ~- W
- */
0 I- O5 r2 W% I/ [ - void BSP_AUDIO_IN_HalfTransfer_CallBack(void) R' j3 B! n" _7 t$ v1 Q4 G
- {
9 o6 I! D! l: f$ g' `* Z- ~* U - audio_rec_buffer_state = BUFFER_OFFSET_HALF; - d; V+ Q2 v# v5 Z( C
- return; " t& [; g0 |* t# h( j
- }- H8 p3 q; Q& K; G0 |2 [6 C$ ]7 }
复制代码
9 b) f8 b, | ^( G程序分析:6 a3 v) C1 Y; X9 f1 C7 Q" Y8 @& x
- 首先定义缓冲区大小和音频输入输出缓冲区8 P, c% e1 i" z# h- V) v5 P
' y# i" S( {: c2 G# O' V4 ^) N
#define AUDIO_BLOCK_SIZE ((uint32_t)512)
4 |% q* }: D( L0 {" S( M" ?6 u#define AUDIO_BUFFER_IN SDRAM_DEVICE_ADDR /* In SDRAM */
0 M& a$ R8 c. u) K$ p. B#define AUDIO_BUFFER_OUT (SDRAM_DEVICE_ADDR + (AUDIO_BLOCK_SIZE * 2)) /* In SDRAM */ - 然后进行初始化,初始化部分完成下面几个功能:
6 z7 p$ j! A: j) T: X! L# s% g- 分配缓冲区& _+ P5 ~, V3 o% ~2 Q* W v
/* Initialize SDRAM buffers */8 Y# K0 B v5 \/ v7 \4 q" j
memset((uint16_t*)AUDIO_BUFFER_IN, 0, AUDIO_BLOCK_SIZE*2);' w" s6 L% U8 Q8 H
memset((uint16_t*)AUDIO_BUFFER_OUT, 0, AUDIO_BLOCK_SIZE*2); - 启用录音功能,将音频输入保存到输入缓冲区0 S7 e$ y# s& }, p+ D+ d
/* Start Recording */
3 m1 u+ c, N" Z: g" T" [ audio.IN_Record((uint16_t*)AUDIO_BUFFER_IN, AUDIO_BLOCK_SIZE); - 设置音频回放
' Q5 d$ Q' U* r* f) H; y audio.OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02);6 c" y1 M0 s5 U+ y8 z3 n
audio.OUT_Play((uint16_t*)AUDIO_BUFFER_OUT, AUDIO_BLOCK_SIZE * 2);
2 f4 y+ q X1 N0 G
- 在主循环中,等待音频输入完成,然后将输入缓冲区(AUDIO_BUFFER_IN)的数据复制到输出(AUDIO_BUFFER_OUT)缓冲区。音频输入的录音和回放,都是使用DMA方式自动完成的,所以无需CPU处理。
% N' g4 ~; Y0 @) }$ k. l. C5 s
3 {# ] K9 G7 M d1 p: t Z完整参考程序:
: `0 H2 M$ D" p+ D, g
DISCO-F746NG_AUDIO_demo_uvision_disco_f746ng.zip
(1.47 MB, 下载次数: 69)
|
这个例子主要是通过音频进行测试,不方便视频。有板子的网友试试就知道了,效果很棒。
不是的,那个芯片支持2w的喇叭,是软件里面设置了静音
需要有源音箱吧,不然带不动