主要内容:
! \- A" }2 y) W t1) 硬件连接; n! C2 E. k3 t/ Y# f5 ~& h
2) VS1053简介;
( ~9 D/ _3 R- h- s$ m+ D- P3) 相关实验及其代码解读。
% N) U0 j7 ~9 M! n7 d2 E3 ?5 Z实验功能:程序开启后,系统先进行RAM测试,再进行正弦测试,可以接耳机听到所设的单频声音。备注:音乐播放实验还未深入研究,本章内容不涉及。+ ]7 l" J5 Y0 b4 j6 d
. X, C8 g/ g$ I3 P. k: w" {% b2 L硬件连接:如下图所示:
% Z! v7 C. P F1 A! \0 m: q
" D; E$ g+ a7 {0 h
5 x8 M7 R9 }" |* ]$ V: i# S, |
6 B. `) B2 {' h% v: z
VS1053与STM32F103ZET6芯片的连接关系如下: g* R3 _ X- @* Y! w0 y
1) VS_MISO→PA6;
4 S# ~, S( R; g1 b- A! T2) VS_MOSI→PA7;5 x# w k" S2 L) T4 p& [ U& t2 u- O
3) VS_SCK→PA5;) L1 _: i- s$ ~. l5 l! W7 o
4) VS_XCS→PF7;1 c( F) [( p* s% o3 d; N b8 c
5) VS_XDCS→PF6;
. C" V$ I/ {0 D1 a B- i" k# s6) VS_DREQ→PC13;
8 _5 i2 N5 C" M" \7) VS_RST→PE6。' X: h; R; T7 B/ f. [. |
备注:PA5/PA6/PA7,即:STM32的SPI1;SPK_CTRL,控制板载喇叭(输入到HT6872)!由程序控制。
" K( x: L6 \% P
! c( B/ _/ R2 s% l1. VS1053简介# n( X" F* t4 P" G2 {6 m+ ^% ?1 `
1.1 VS1053是继VS1003后荷兰VLSI公司推出的又一款高性能编解码芯片。该芯片可对MP3/OGG/WMA/FLAC/WAV/AAC/MIDI等音频格式解码,同时还支持ADPCM/OGG等格式的编码,性能相对VS1003提升不少。
: m( b: s) I0 p% d% b u: _0 Q* GVS1053拥有一个高性能的DSP处理器核VS_DSP,16K的指令RAM,0.5K的数据RAM,通过SPI控制,具有8个可用的通用IO口和一个串口,芯片内部还带了一个可变采样率的立体声ADC(支持咪头或线路输入)、一个高性能立体声DAC及音频耳机放大器。
9 _3 B. a3 s5 A/ n3 J; p t
# r5 ^/ H& {# J1.2 特点
: e7 i( ]5 J3 ?" b( w7 f8 K2 l1) 支持OGG/MP3/WMA/WAV/FLAC(需加载patch)/MIDI/AAC等格式解码;$ ?' I" o1 X. |8 N$ ~; y
2) 支持OGG(需加载patch)/IMA ADPCM编码;
* K( f1 W+ @) n- G4 B6 g7 E3) 支持音量调节、高低音控制和EarSpeaker空间效果;
" @- G' @$ A" E0 Y4) 自带高性能立体声ADC和DAC,音质比VS 1003好很多;
t8 `' M g% j. d5 Q- |5) 自带耳机驱动器,可驱动30欧负载的耳机;$ z3 y4 r" |9 S8 z8 O2 u7 m
6) 自带8个GPIO,可用于控制外设/作为I2S接口(外接DAC );, I8 \, c/ m0 N
7) 通过SPI接口控制/传输数据,接口简单;
& ?0 m4 Q$ F. x8) 可通过加载patch,实现新功能添加;' j" a5 X) B- R' d9 t; A" [6 ~# w
9) 低功耗 。
3 K! w) l8 I' r7 I# K+ S9 Z9 m. A# S V" R
1.3 接口介绍: E* H5 W5 I/ Q7 o$ c
VS1053通过SPI接口来接受输入的音频数据流,它可以是一个系统的从机,也可以作为独立的主机。本例程,我们把它当成从机使用。我们通过SPI口向VS1053不停的输入音频数据,它就会自动帮我们解码了,然后从输出通道输出音乐,这时我们接上耳机就能听到所播放的歌曲了。
7 ?' G7 _% \" l* ^VS1053通过7根线同MCU连接,如下:
1 A3 a# C( J, B QVS_RST:VS1053的复位信号线,低电平有效;
; y3 Y0 k( ~. r1 E+ pVS_DREQ:数据请求信号(高电平有效),用来通知主机,VS1053是否可以接收数据;! x k9 [) s. W
VS_XCS:命令片选(低电平有效);
1 p, n& T0 z5 Q' TVS_XDCS:数据片选(低电平有效);$ n$ M7 q8 [ }$ D
VS_MISO、VS_MOSI和VS_SCK:SPI信号线。
& l5 r b6 J+ J3 ?1 Q/ L% g/ O4 Z8 r' A% `, R9 W1 b; i2 _& ]
1.4 VS1053工作模式 [. X5 _$ K2 q! x J$ z
VS1053的SPI支持两种工作模式:
9 }! o4 h8 e0 a7 {' A7 q1,VS1002有效模式(即新模式);
) L) _" H! y0 p$ p6 E2,VS1001兼容模式。
3 p' s& f9 k. f5 e" E$ F. n8 Z: W- t这里仅介绍VS1002有效模式(此模式也是VS1053的默认模式)。在新模式下VS1053的SPI信号线功能描述如下表所示:) R/ h+ ~. Z+ r# I& [7 a' d( o
) X3 c5 `, A6 w8 m- s! C
4 ?: ]% E1 _& K0 W- e- D4 `! `
8 X6 S/ x/ @/ T8 v! c8 K' A
VS1053的SPI数据传送,分为SDI和SCI,分别用来传输数据/命令。SDI采用SPI协议,不过,数据传输受DREQ控制,主机在判断DREQ有效(高电平)之后,直接发送数据即可(一次可以发送32个字节)。
# G( F% q; r4 |& c# I/ e) C2 t# X; r' v, ]8 z! A
1.5 VS1053之SCI命令传输介绍2 x3 C2 T7 m+ U9 j T- A
SCI串行总线命令接口包含了一个指令字节、一个地址字节和一个16位的数据字。读写操作可以读写单个寄存器,在SCK的上升沿读出数据位,所以主机必须在下降沿刷新数据。SCI的字节数据总是高位在前低位在后的。第一个字节指令字节,只有2个指令,也就是读和写,读为0X03,写为0X02。
- q$ |% k+ Q' P- ^7 ESCI读时序如下图所示:
0 V. r$ k& E+ o2 B1 ]6 d
1 G! X1 ]9 L: Z6 b3 j) Y4 w
+ k8 w; \' a8 b% H
v, y' E% V% m, J USCI写时序如下图所示:
2 J! D" E0 P, O4 u9 u2 c7 n2 F+ b, h
# C! R' A$ a' H# f' i1 l7 y& v8 T
: n' N; b, k4 f5 O# S1 ~
) B0 k4 _$ V9 ^9 H5 \
写指令为:0X02,数据通过SI写入VS1053, SO则一直维持低电平。
+ ~; G+ H9 U" b$ X* H$ U注意:在读和写时序图中,DREQ信号上都产生了一个短暂的低脉冲,也就是执行时间,在写入和读出VS1053的数据之后,它需要一些时间来处理内部的事情,这段时间,是不允许外部打断的。所以,在SCI操作之前,最好判断一下DREQ是否为高电平,如果不是,则等待DREQ变为高。
3 U9 \+ F: U* [3 t& K. M' y" v/ o" ~7 t5 J( F
2. VS1053寄存器介绍/ R6 B# ^ d7 @4 ]' V& I q( L
2.1 VS1053的所有的SCI寄存器,如下表:) `$ J8 w" z* k4 k* y
0 l! `- S d" L" G2 A
; M9 S7 U+ t' c; Y
+ H& c/ V% `) a2.2 MODE寄存器(0X00)
/ Y# q# G) S& G$ }, ~% m
9 Z( U9 W. v1 M2 h, l3 E5 n
! m5 I' O! U! b! q7 K3 H
& K$ b( |( }! X4 J
SM_RESET:软件复位,建议在每播放一首歌曲之后,软复位一次。
4 g) e3 Y; m1 s* }% o% OSM_SDINEW:模式设置位,设置为1,选择VS1002新模式(本地模式)。
# T* l# w5 I& |其他位的详细介绍,请参考:VS1053_cn.pdf。
$ Z2 x' {' n" p1 | |4 x, F3 H
2.3 BASS寄存器(0X02)+ W8 e/ m8 Y% v+ b* R7 \
7 l; Y/ J! ]( H) r- G. @$ N7 B
1 s2 h. V( g$ N. M. L S! ]5 N4 u0 }% U/ _ Y1 q$ R0 U
该寄存器可以用于设置VS1053的高低音效,通过这个寄存器以上位的一些设置,我们可以随意配置自己喜欢的音效(其实就是高低音的调节)。& d }$ ~; e( ` e7 x
注意:EarSpeaker效果由MODE寄存器控制。& M/ M2 q9 S* M* _4 x N$ m3 Q
2 z- v$ O& _- J' U4 m: |& {" C8 f
2.4 CLOCKF寄存器(0X03)) W! O0 _( j( {, s
2 N0 g6 v) @+ K& h; p7 |
: S; i( @/ l n" a, P+ I- ^
: k' [( z9 p" _3 t+ \
该寄存器用来设置时钟频率、倍频等相关信息。其中:SC_FREQ是以4Khz为步进的一个时钟寄存器,当外部时钟是12.288M的时候,设置为0即可。) E" p# j3 F: F- r* M% c) q
XTALI是外部晶振的时钟频率(单位为:Hz )。CLKI是内部时钟频率。由于我们使用的是12.288M的晶振,在这里设置此寄存器的值为0X9800,也就是设置内部时钟频率为输入时钟频率的3倍,倍频增量为1.5倍(0X9800=1001 1000 0000 0000)。
9 e3 b; N" T/ a" R% C ?: X9 N$ M- {% x6 `
2.5 DECODE_TIME寄存器(0X04)
1 U3 S2 i, A0 s该寄存器是一个存放解码时间的寄存器,以秒钟为单位,我们通过读取该寄存器的值,就可以得到解码时间。不过,它是一个累计时间,在每首歌播放之前,需要把它清空一下,以得到这首歌的准确解码时间。
4 ~ \$ h; F5 K' v
& M7 t3 Q& g1 n" [0 A2.6 HDAT0&HDAT1寄存器(0X08&0X09)7 u3 p- e- F- N' F
这两个寄存器,是数据流头寄存器,不同的音频文件,读出来的值意义不一样,我们可以通过这两个寄存器来获取音频文件的码率,从而可以计算音频文件的总长度。这两个寄存器的详细介绍,请参考:VS1053的数据手册(VS1053_cn.pdf)。8 J1 f% L) [9 }/ U
/ g: ]) `2 n0 U
2.7 VOL寄存器(0X0B)
# h0 n" u+ {+ Q* D5 }4 c5 O1 Q该寄存器用于控制VS1053的输出音量,该寄存器可以分别控制左右声道的音量,每个声道的控制范围为0~254,每个增量代表0.5db的衰减,所以该值越小,代表音量越大。比如设置为0X0000则音量最大,而设置为0XFEFE则音量最小。
( x V0 F. H* ~1 Q' y注意:如果设置VOL的值为0XFFFF,将使芯片进入掉电模式!
" C. U- L8 a/ g" N: ?* b' o3 h. y+ N& A5 Y- K0 W+ `9 n
3 VS1053初始化步骤
( w) A. P, x# e. b1) 复位VS1053
. V8 O2 E% r! o包括硬复位和软复位,让VS1053恢复初始状态,准备解码下一首歌曲。在每首歌曲播放之前都可以执行一次硬件复位和软件复位,以便更好的播放音乐。
# l# U& u( P, [7 z! G4 z, V2) 配置VS1053的相关寄存器3 {0 J- M1 c7 N; W6 c
这里配置的寄存器包括VS1053的模式寄存器(MODE)、时钟寄存器(CLOCKF)、音调寄存器(BASS)、音量寄存器(VOL)等。/ o( C7 p2 ]: \2 t9 ~
9 n1 o* X7 }! U3 y v9 [3 _3) 发送音频数据! Y& z) e1 b1 l0 \# h
经过以上①、②配置以后,剩下来要做的事情,就是往VS1053里面发送音频数据,只要是VS1053支持的音频格式,直接往里面丢就可以了,VS1053会自动识别,并进行播放。不过,发送数据要在DREQ信号的控制下有序的进行,不能乱发。这个规则很简单:只要DREQ变高,就向VS1053发送32个字节。然后继续等待DREQ变高,直到音频数据发送完。/ Z* f+ ^- h. J: f; G
. {5 F) Y8 K" z6 ^/ I( X5 D- |4. 部分源码讲解& d& c# h v$ {
4.1 VS1053低速2.25MHz,高速9MHz。9 f/ w* i/ o E6 Y. T
5 K, ~$ e: M5 n% K5 ~4 ~* v/ S
- /*******************************************************************************
, r% X$ }. N2 q- Q - 函数名称:u8 VS_SPI_ReadWriteByte(u8 data)
, W1 j- h& F& m G1 W6 p - 函数功能:读写数据,移植用 , |) s1 Q Y" A: E i4 I
- 入口参数:u8 data:要写入的数据% @6 D: c& m7 E& r
- 返回参数:u8 读到的数据
- m4 Q. g* X3 S4 s - 解读作者:Aaron
# O# A) z& w; H$ h - ********************************************************************************/2 [% i6 c' n& i! J# B
- u8 VS_SPI_ReadWriteByte(u8 data)
0 `$ z3 S( w& r' b% X: e s - { * Z' T: P8 t% _
- return SPI1_ReadWriteByte(data); " b. V; l4 V1 q% C
- }3 F, W1 t( k+ w( R) I: K
- /* VS1053初始化时,需要低速 */+ V* ?$ G$ }: m) |2 K N# w6 I
- void VS_SPI_SpeedLow(void)9 J4 H; R; S' U. y8 V( ^
- {
) d7 h3 i# r' W& g - SPI1_SetSpeed(SPI_BaudRatePrescaler_32); /* 设置低速模式,72/32≈2.25MHz */ * Z( R3 n2 H9 C5 O
- }
$ t% B& F3 K7 h5 l2 ^ - /* VS1053正常工作时,可以高速 */1 r5 w( ~9 |5 u9 }- V; I& W
- void VS_SPI_SpeedHigh(void), T0 v3 h% Q* h' ~
- {
! U5 F! [9 J+ e0 l9 f - SPI1_SetSpeed(SPI_BaudRatePrescaler_8); /* 设置高速模式,72/8=9MHz */ 9 ]" E) m7 R" p! ]
- }
复制代码 : |9 M( @9 w. w" F$ N3 p. f4 l$ t
这么设置的原因如下表(VS1053芯片手册):
6 K6 D$ P: A ] R
; E! q. A- V) b' m
7 Y0 Q# \. o9 |- I$ ^* f9 u K* S. \
SPI读取操作时,速率为CLKI/7 MHz,在SCI和SDI写入操作时允许为CLKI/4MHz。CLKI值为3倍(本项目要求设置的)的晶振频率,即12.288×3=36.864MHz,那么CLKI/7<5MHz,CLKI/4<9.2MHz。因此低速时,2.25MHz满足5MHz要求,高速时,9MHz满足9.2MHz。9 t$ j8 |/ ] [# [- U
1 O+ Y% L% L' q Q0 K" P8 B
5 相关实验代码解读: ?7 g% O) l3 K( v
5.1 vs10xx.c部分代码(我修改了下)
) ~$ ~9 R6 F( J: [ z+ m) _4 ]2 C; o. u
- /**********************************************************************, }8 x/ d) W$ X& i6 m
- 函数名称:VS_Init()
q P8 _3 [: R5 p! M0 h - 函数功能:初始化VS10XX的IO口
$ B$ y0 X! _; l( ~3 C. y: Z9 Z - 入口参数:无8 B$ n* j1 N6 g* l/ r M; z
- 返回参数:无: }. b, l3 C/ l; e7 i% T+ e
- 解读作者:Aaron/ S/ m1 l) A U$ p4 d J
- ***********************************************************************/
/ E1 f7 t+ Y" S) Z - void VS_Init(void)
4 j# c4 _$ c8 R( ?* q. J - {
! |* E& D4 F6 x* ` n - GPIO_InitTypeDef GPIO_InitStructure;* ?$ z( s+ f8 T U
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOF, ENABLE); /* 使能PC,PE,PF端口时钟 */
, r0 |" K" T! ^: f' p0 }% x - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13; 9 F! J U* W: d+ c) j
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; /* 上拉输入 */9 w# ]/ }1 Y! L7 [' y7 M) O N
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;8 Q1 ]1 p& E% [' }- a( Y3 \
- GPIO_Init(GPIOC, &GPIO_InitStructure); /* 初始化PC13,对应VS_DREQ(数据请求信号) */
' c# Z7 i' H, x - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
2 ^8 P a& K! O+ c. [, x' E4 ` - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* 推挽输出 */4 T2 l! C3 [! G- h
- GPIO_Init(GPIOE, &GPIO_InitStructure); /* 初始化PE6,对应复位信号线 */
: _1 y9 r- N0 \ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
/ l& v1 K4 `5 q! w" ]$ Z7 z) W - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* 推挽输出 */
, x9 F1 O( B0 G% v3 L6 V- E( E - GPIO_Init(GPIOF, &GPIO_InitStructure); /* 初始化PF6和PF7,对应VS_XDCS(数据片选)和VS_XCS(命令片选) */8 w1 I# x, b$ U9 A: A. d- H7 G# w5 ]8 j
- SPI1_Init(); /* 初始化SPI */
/ E4 S# r4 C L% | - } * r( l9 S* u8 q
+ j( b; R0 h1 n O0 t: X: a: I- /**********************************************************************% b' [, Z! ^$ [' \$ J8 ^! `' c+ ~
- 函数名称:VS_Sine_Test()
/ K% t( R! e9 e - 函数功能:正弦测试 ! g/ K# U. p& C( e; S& x# w6 g
- 入口参数:无
! ~# _% O. J9 M3 } - 返回参数:无
6 b' f" n4 V5 \" g$ r7 J# B - 解读作者:Aaron) ^+ o( }8 A# a
- ***********************************************************************/0 q9 T* E# v# ?
- void VS_Sine_Test(void)7 R0 }+ c3 Z/ M$ Z- {9 H$ g
- { 5 A5 b, [: W! q y y
- VS_HD_Reset(); /* 硬件复位 */
' C! v% H9 \2 M8 ` - VS_WR_Cmd(0x0b,0X5050); /* 设置音量,值越小声音越大 */ 0 C# Y f9 S) ^' X& v- }" ~- h9 J1 } r
- VS_WR_Cmd(SPI_MODE,0x0820); /* 进入VS10XX的测试模式,MODE寄存器,[位5]SM_TEST允许SDI测试,[位11]SM_SDINEW本地模式 */ : A3 D5 Q" v' q" p) i
- while(VS_DQ==0); /* 等待DREQ为高 */
8 |% c& b' @3 L4 u" h% U - printf("mode sin:%x\n",VS_RD_Reg(SPI_MODE));) O& V( ~3 }% w' j
- /* 向VS10XX发送正弦测试命令:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00 其中n = 0x28=0b00101000, 即FS=48000Hz,频率=48000*8/128=3000Hz */% V5 ?- b; n( p/ s
- VS_SPI_SpeedLow(); /* 低速模式 */
- u7 G( }* d) V8 p2 z# c4 T4 [* X5 n4 _ - VS_XDCS=0; /* 选中数据传输 */
6 l) b; ]7 X) W" [7 l$ Z - VS_SPI_ReadWriteByte(0x53);( p0 W& s) A2 m- L& w/ s2 L) }' j
- VS_SPI_ReadWriteByte(0xef);2 i& a ~1 U ]& L9 K) e. ~
- VS_SPI_ReadWriteByte(0x6e);
( Z, i8 o. J# B: s5 Y% H - VS_SPI_ReadWriteByte(0x28);6 b" C" ?5 B6 X% ^
- VS_SPI_ReadWriteByte(0x00);$ z4 O- W4 R7 K" K5 Y' K
- VS_SPI_ReadWriteByte(0x00);
" ]5 C [1 r$ {: i" |4 v - VS_SPI_ReadWriteByte(0x00);6 p; `( L* j& k9 r; S! M
- VS_SPI_ReadWriteByte(0x00);
9 a7 W+ k5 |+ ]3 ~1 f - delay_ms(200); /* 测试经验告诉我,延迟时间不能超过1s */
5 t! D: }1 m/ {( F+ W - VS_XDCS=1; 9 G* X# I- G' s: x
- /* 退出正弦测试 */
A: E1 S2 {% j4 i1 L) U4 Z) J, b: Y- e - VS_XDCS=0; /* 选中数据传输 */
$ ]0 ]% F J. r+ R - VS_SPI_ReadWriteByte(0x45);
3 j7 z4 O+ o0 h' R! g) Z' Y - VS_SPI_ReadWriteByte(0x78);, q, k" J0 L" b6 t: E9 E; W0 t
- VS_SPI_ReadWriteByte(0x69);4 C5 n4 w2 I' i, F7 e4 C
- VS_SPI_ReadWriteByte(0x74);5 }+ S ]& m3 N& W7 e3 P5 F' a
- VS_SPI_ReadWriteByte(0x00);6 X# W B: c9 D( u/ G
- VS_SPI_ReadWriteByte(0x00);
6 V$ p, p1 y" i; h, r - VS_SPI_ReadWriteByte(0x00);5 R W% M r; P- i/ _, B6 b
- VS_SPI_ReadWriteByte(0x00);
4 [8 h" W/ K- p# p _ - delay_ms(100);
/ | `' S( g/ | - VS_XDCS=1; 8 w' D V6 s. d( b
- /* 向VS10XX发送正弦测试命令:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00其 中n = 0x22=0b001 00010, 即FS=48000Hz,频率=48000*2/128=750Hz */7 A. f0 A0 {1 ^9 u( }; a% |
- VS_HD_Reset(); /* 硬件复位 */
9 e8 _# C1 `: b - VS_WR_Cmd(0x0b,0X5050); /* 设置音量,值越小声音越大 */
' K# K+ X% q' v - VS_WR_Cmd(SPI_MODE,0x0820); /* 进入VS10XX的测试模式,MODE寄存器,[位5]SM_TEST允许SDI测试,[位11]SM_SDINEW本地模式 */
& I- T$ t4 \' S$ b3 G - while(VS_DQ==0); /* 等待DREQ为高 */
* f& F% X8 O, R3 c$ t) Y - VS_SPI_SpeedLow(); /* 低速模式 */
5 d' G, n+ F+ v/ v6 b - VS_XDCS=0; /* 选中数据传输 */
1 ~* y# r* [1 E - VS_SPI_ReadWriteByte(0x53);) Y& y* k: ]$ z6 ~/ O9 }$ {: f$ ^. R
- VS_SPI_ReadWriteByte(0xef);2 ]' U) r1 ]( J. X7 H6 O" L: h' J1 Y: Y
- VS_SPI_ReadWriteByte(0x6e);
0 O) W: I4 f, _) b4 j1 b - VS_SPI_ReadWriteByte(0x22);9 _ ]3 E* ^) T* w1 H5 k3 {
- VS_SPI_ReadWriteByte(0x00);
. L1 F* s h1 r/ F! A3 B - VS_SPI_ReadWriteByte(0x00);! N; C, _, U: ~! Q3 p
- VS_SPI_ReadWriteByte(0x00);9 M8 V' S. s( J3 h
- VS_SPI_ReadWriteByte(0x00);
3 z) \, u; C$ |8 P% | - delay_ms(400);
% W4 `+ [& c- A; h - VS_XDCS=1;
9 I! r/ x# M2 b - /* 退出正弦测试 */
, }6 v, ^' n* o: {! ^; D B* J4 b - VS_XDCS=0; /* 选中数据传输 */
: }4 Y7 e- d: [7 W4 v6 m$ c - VS_SPI_ReadWriteByte(0x45);
+ w" g0 W8 m0 S - VS_SPI_ReadWriteByte(0x78);; n7 a, O7 Z% ~% f
- VS_SPI_ReadWriteByte(0x69);
$ O- W; s% m( i" |1 M3 H" B - VS_SPI_ReadWriteByte(0x74);! w4 ~% P* N6 G! `6 F9 G) `
- VS_SPI_ReadWriteByte(0x00);$ L& f# y* c; @1 n5 Q- A @
- VS_SPI_ReadWriteByte(0x00);- B3 w# S! z/ h
- VS_SPI_ReadWriteByte(0x00);( T; ]" D d$ V) d
- VS_SPI_ReadWriteByte(0x00);. A) w2 n- w: b% d
- delay_ms(100);
" z: s9 m& n. q - VS_XDCS=1;
5 Q# X3 J( V! _1 ?' y - }
# {7 g( A; ]/ [, |! }$ Z
! e; V* q- k) q- /**********************************************************************
7 M& w! o& M# V6 a9 p, q+ U - 函数名称:u16 VS_Ram_Test()- F+ X3 Y/ `% M+ O! `' L$ I
- 函数功能:RAM测试 # H0 I/ _# i. Z6 R
- 入口参数:无
" u8 L# q! @" ~5 U - 返回参数:u16 RAM测试结果,VS1003若得到0x807F,则表明完好,VS1053则为0X83FF+ v2 @# ?! C1 g+ X3 N8 @( g
- 解读作者:Aaron
% ]: h& t, {& }- k) M - ***********************************************************************/
0 T. K- m8 H6 L' e' H: t8 L7 | - u16 VS_Ram_Test(void)
+ ~9 g& g' X3 X" i) o - {
1 s& ^) ?( C7 e5 n5 R9 b - VS_HD_Reset(); /* 硬件复位 */ : h& o1 \' V0 Z
- VS_WR_Cmd(SPI_MODE,0x0820); /* 进入VS10XX的测试模式 */; L. v+ K; S; M/ h* Y& G6 T
- while (VS_DQ==0); /* 等待DREQ为高 */ r1 E6 A: ~2 O6 b# d& I
- VS_SPI_SpeedLow(); /* 低速 */ # Z& O, U9 n* X; m, d
- VS_XDCS=0; /* xDCS = 1,选择VS10XX的数据接口 */
5 d! _, Q: T m! G& n0 E - VS_SPI_ReadWriteByte(0x4d);
1 |' k( q/ ?& q8 |2 w! L2 P - VS_SPI_ReadWriteByte(0xea);
# b2 s9 O' t3 x7 X - VS_SPI_ReadWriteByte(0x6d);( v. j9 m, c3 Z9 w( ^0 @, f
- VS_SPI_ReadWriteByte(0x54);# `9 O+ N( w# K Z
- VS_SPI_ReadWriteByte(0x00);
. ~" A/ s+ P- f - VS_SPI_ReadWriteByte(0x00);6 q* v4 N, c- }
- VS_SPI_ReadWriteByte(0x00);
) w7 h ^+ G6 v$ t$ v - VS_SPI_ReadWriteByte(0x00);
/ Q3 [+ G/ j2 ^8 K. h6 s - delay_ms(150); 9 s( N' f+ A$ L6 J1 Q' s( f
- VS_XDCS=1;
0 c% Y* d% `* `! l; _0 o% c7 A+ c - return VS_RD_Reg(SPI_HDAT0); /* VS1003如果得到的值为0x807F,则表明完好;VS1053为0X83FF */
0 `& u2 U. @4 m2 N - }
复制代码 u. B7 Y. q9 D/ {- P" S; h( ^
5.2 main.c主函数代码解读
4 D8 D# y& H: s0 f" G
+ J; }" w# s, t& e3 ~/ |& ?) i- /************************************************
2 A% l; o4 u' ], k4 s - 函数名称:int main()
. Y! C3 t! I: {# \$ a - 函数功能:主函数4 H# u! ~/ p! v0 c6 U
- 入口参数:无
. b/ }0 j- g* y- z: R - 返回参数:int
% S6 B! e/ x" t& r6 N1 d - 解读作者:Aaron
: A0 P; s" J6 i$ o - *************************************************/ |) o" F' H. s9 q3 [) a# W
- int main(void)( P- o& d+ y" Z3 G0 {3 c
- { . M0 ?& d$ A! T5 m' B
- delay_init(); 5 I* S$ @; F( T: x/ u i
- NVIC_Configuration();+ g, i- t' V* J: s8 @! u! m% Y/ a
- LED_Init(); ! M3 ~9 {1 ]# X* P/ u( D
- KEY_Init(); : C4 a' l/ t+ @( g' H
- My_USART1_Init(); ' o/ O. u* U; S3 W' x6 b* H
- VS_Init(); /* 包含对SPI1初始化 */ / @5 ]% W7 y, q( h* D
- printf("存储器测试:%d\r\n",VS_Ram_Test());) o4 T1 h) o; B g8 e4 {
- while(1), e7 P) i4 c p: Y# ^/ \3 n/ _7 y
- {. v/ R& p# o" }1 y, W' q& w
- DS0=0;
- A0 d& D O! e9 l - printf("开始播放单频信号\r\n");
! o+ | _9 v; G. m0 O- I7 `% F - VS_Sine_Test(); . c4 G( |9 f" O" N- O8 ~+ r7 l
- delay_ms(1000);
, d0 _9 }7 [: c1 l! _ - DS0=1;7 o, G, r d! T5 R
- delay_ms(1000);
) B4 \, C& Y) ? - }
8 l- T3 t. w8 z - }
- m% X- f' a8 k% ~/ Q" G7 R% t, H/ d
复制代码
1 t0 [4 o: [3 t: J/ w, I8 f实验结果9 q) G, f1 a7 ^$ I; Q
接上耳机,能听到200ms的3000Hz单频声,然后紧接着听到400ms的750Hz单频声。# _8 O6 _5 D, q G8 r# |
/ t' b0 _# D, Y( K8 J; v6 L
) N, ]( a7 |' T. y" e
7 h `& r* c, \( C7 h: G
————————————————- v9 D- M- g% j$ x- L
版权声明:天亮继续睡7 t6 N- J% T3 ]3 {7 o. i. v
9 B0 g' A0 u" P4 ^* }, |; ^9 _' L6 a, t
" T m! S4 P9 d' c& ` K) r
|