从昨天下午一直弄到早上,耳机里面终于传来的久违的调子。正弦测试通过了。
vs1003芯片集成得相当好,据说支持双通道,不过要高保真音效的话还要其他芯片支持。
首先,检查硬件和接线是必须的。接线最好一个一个的测试联通性,能够测出高低电平的就先测高低电平。
开始的调试时候,连gpio都有问题,和爽哥一起调了几个小时,被一顿数落。神马PORTxSET和PORTxCLR寄存器都没搞清楚就一下子正弦测试。。。囧
之后需要检查spi收发数据是否正常,由于没有示波器(我只好说SoftwareAcademy太小气...),便使用这个spi驱动Pmodcls LCD模块,lcd正常显示字符,spi也就可以用了。
gpio接口io和spi没有问题后,开始读寄存器。后来发现至少有两点没有注意:一是spi的速率和模式控制,datasheet要求时钟在SCLK/6以下,模式肯定暂时只能用8位传输。第二、关于Mode和Status寄存器的值。这个Status寄存器会在100ms后自动变为0x30,这也就是为什么一直测到的是30的原因。
接下来写寄存器。没有读写寄存器的测试,给VS1003发送命令和数据无从谈起。
一切完毕后,可以进行正弦测试了。
开始时,一点声音都没有,没辙。www上搜了一下,发现VOL音量寄存器的设置太小,而且每次正弦测试的间隔太小以至于无法听出声音来。
现在做音频播放器的门槛越来越低了,好多电子友都自己动手制作。我运气还不错,仅用了一天时间,而且寄送过来的芯片也没bug。总的说来从硬件到软件的测试过程是:连线-->GPIO-->SPI--->Read Registers--->Write Registers-->Sine Test
下面贴一下初始化和读写寄存器的代码:
1 #include " vs1003.h "
2 #include " player.h "
3 #include " spi.h "
4 // -----------------------------------------------------------------
5 // transport driver for vs1003 on PIC32
6 // xiaoyang yi
7 // -----------------------------------------------------------------
8 #define VS1003_DEBUG 1
9
10 // VS1003 config data [0,henh.1,hfreq.2,lenh.3,lfreq 5,volumn]
11 int8u_t vs1003ram[ 5 ] = { 0 , 0 , 0 , 0 , 250 };
12
13 void delay_ms(unsigned int num)
14 {
15 unsigned int i = num * 1024 ;
16 while ( (i -- ) > 0 ){
17 ;
18 }
19 }
20 //
21 // 保存VS1003的设置
22 // EEPROM地址:486~490 共五个
23 //
24 void Save_VS_Set( void )
25 {
26 int8u_t t;
27 for (t = 0 ;t < 5 ;t ++ )
28 ; // save data to pic32
29 // FM24C16_WriteOneByte(488+t,vs1003ram[t]); // vs1003ram保存
30 }
31
32 //
33 // 读取VS1003的设置
34 // EEPROM地址:486~490 共五个
35 //
36 void Read_VS_Set( void )
37 {
38 int8u_t t;
39 for (t = 0 ;t < 5 ;t ++ )
40 ;
41 // vs1003ram[t]=FM24C16_ReadOneByte(488+t); // vs1003ram调用
42 //
43 }
44
45 // ------------------------------------------------------------------------------
46 // write cmd to vs1003
47 // address,data
48 // ------------------------------------------------------------------------------
49 // write cmd as following:
50 // 1.等待DREQ为高(当DREQ为低时,说明芯片还没有就绪)
51 // 2.将XCS(命令片选)拉低
52 // 3.写入0x02
53 // 4.写入寄存器地址
54 // 5.分别写入数据的高字节与低字节
55 // 6.将XCS置高
56 // ------------------------------------------------------------------------------
57 void Vs1003_CMD_Write(int8u_t address,int16u_t data)
58 {
59 unsigned char high = data >> 8 ;
60 unsigned char low = data;
61 printf( " Write_cmd:%2x,%2x\n " ,high, low);
62
63 // wait for free
64 while ((PORTE & MP3_DREQ ) == 0 )
65 ;
66 // MP3_DCS_DES(); // MP3_DATA_CS=1;
67
68 MP3_CCS_DES();
69 delay_ms( 1 );
70 MP3_CCS_SEL(); // MP3_CMD_CS=0;pull down XCS
71
72 spi2_8TxRx(VS_WRITE_COMMAND); // send write command
73 spi2_8TxRx(address); // send addr
74 // spi2_16TxRx(data);
75 spi2_8TxRx(high); // 8bits high of data
76 spi2_8TxRx(low); // 8bits low of data
77
78 MP3_CCS_DES(); // MP3_CMD_CS=1;
79 }
80
81 int16u_t Vs1003_CMD_Read(int8u_t address)
82 {
83 int16u_t data;
84
85 // wait for free
86 while ((PORTE & MP3_DREQ ) == 0 )
87 ;
88 // pull down XCS
89 MP3_CCS_SEL();
90
91 // send cmd:VS_READ_COMMAND
92 spi2_8TxRx(VS_READ_COMMAND);
93 // senb addr
94 spi2_8TxRx(address);
95
96 // get the uint16 data
97 data = spi2_8TxRx( 0X00 );
98 data <<= 8 ;
99 data += spi2_8TxRx( 0X00 );
100
101 MP3_CCS_DES();
102 return data;
103 }
104 // ------------------------------------------------------------------------------
105 // configure vs1003
106 // address,data
107 // ------------------------------------------------------------------------------
108 // 1.硬件复位:接XRESET拉低
109 // 2.延时,将XDCS、XCS、XRESET置高
110 // 3.向MODE中写入0X0804
111 // 4.等待DREQ为高
112 // 5.设置VS1003的时钟:SCI_CLOCKF=0x9800,3倍频
113 // 6.设置VS1003的采样率:SPI_AUDATA=0xbb81,采样率48k,立体声
114 // 7.设置重音:SPI_BASS=0x0055
115 // 8.设置音量:SCI_VOL=0x2020
116 // 9.这一步被很多人忽视,向VS1003发送4个字节的无效数据,用以启动SPI发送
117 // ---------------------------------------------------------------------------
118 void Vs1003_Init( void )
119 {
120 char i = 0 ;
121 int16u_t data = 0x0 ;
122
123 SPI2_SELECT();
124 TRISECLR |= ( 1 << 0 ) | ( 1 << 1 ) | ( 0 << 2 ) | ( 1 << 3 ); // set pins
125
126 MP3_RST_SET( 0 );
127 delay_ms( 100 );
128
129 MP3_CCS_DES(); // set cs pin high/low
130 MP3_RST_SET( 1 ); // reset
131 MP3_DCS_DES(); // xcs = 0;
132
133
134 #if VS1003_DEBUG
135 Vs1003_CMD_Write(SPI_MODE, 0xeeee );
136 printf( " vs1003 init:begin\n " );
137 data = Vs1003_CMD_Read(SPI_MODE);
138 printf( " Read REGS, SPI_MODE=%x\nWrite SPI_MODE...\n " ,data);
139 Vs1003_CMD_Write(SPI_MODE, 0x0804 );
140 data = Vs1003_CMD_Read(SPI_MODE);
141 printf( " Read REGS agin, SPI_MODE=%x\n " ,data);
142 #endif
143
144 Vs1003_CMD_Write(SPI_MODE, 0x0804 );
145 // wait for DREQ==1
146 while ( (PORTE & MP3_DREQ ) == 0 )
147 ;
148
149 // step 6-9
150 Vs1003_CMD_Write(SPI_CLOCKF, 0x9800 );
151 delay_ms( 1 );
152 Vs1003_CMD_Write(SPI_AUDATA, 0XBB81 );
153 delay_ms( 1 );
154 Vs1003_CMD_Write(SPI_BASS, 0x0055 );
155 delay_ms( 1 );
156 Vs1003_CMD_Write(SPI_VOL, 0x2020 );
157 delay_ms( 1 );
158
159 // 向vs1003发送4个字节无效数据,用以启动SPI发送
160 MP3_DCS_SEL(); // 选中数据传输
161 spi2_8TxRx( 0XFF );
162 spi2_8TxRx( 0XFF );
163 spi2_8TxRx( 0XFF );
164 spi2_8TxRx( 0XFF );
165 MP3_DCS_DES(); // 取消数据传输
166 delay_ms( 200 );
167 #if VS1003_DEBUG
168 printf( " vs1003 init:init over\n " );
169 #endif
170 }
171
172 // -------------------------------------------------------------------------
173 // 正弦测试
174 // 1.进入VS1003的测试模式:SPI_MODE=0X0820
175 // 2.等待DREQ为高
176 // 3.将XDCS接低,而XCS要置高,选择VS1003的数据接口
177 // 4.向VS1003发送正弦测试命令:0X53 0XEF 0X6E 0X30 0X00 0X00 0X00 0X00
178 // 其中0X30为频率,用户可以修改为其它值
179 // 5.延时一段时间
180 // 6.退出正弦测试,发送命令:0X45 0X78 0X69 0X74 0X00 0X00 0X00 0X00
181 // 7.延时一段时间
182 // 8.循环以上流程
183 // -------------------------------------------------------------------------
184 void Vs1003_Sine_Test(unsigned char x)
185 {
186 #if VS1003_DEBUG
187 int16u_t data = 0x0 ;;
188 printf( " Vs1003_Sine_Test:begin\nGet in SinTest Mode\n " );
189 #endif
190 Vs1003_CMD_Write(SPI_MODE, 0x0820 ); // 进入vs1003的测试模式
191
192 #if VS1003_DEBUG
193 data = Vs1003_CMD_Read(SPI_MODE);
194 printf( " Read REGS-SIN, SPI_MODE=%x\n " ,data);
195 #endif
196 while ((PORTE & MP3_DREQ ) == 0 )
197 ; // 等待DREQ为高
198
199 // 向vs1003发送正弦测试命令:0x53 0xef 0x6e n 0x00 0x00 0x00 0x00
200 // 其中n = 0x24, 设定vs1003所产生的正弦波的频率值,具体计算方法见vs1003的datasheet
201 SPI2_SELECT();
202 MP3_CCS_DES();
203 MP3_DCS_SEL(); // 选中数据传输
204
205 spi2_8TxRx( 0x53 );
206 spi2_8TxRx( 0xef );
207 spi2_8TxRx( 0x6e );
208 spi2_8TxRx(x);
209 spi2_8TxRx( 0x00 );
210 spi2_8TxRx( 0x00 );
211 spi2_8TxRx( 0x00 );
212 spi2_8TxRx( 0x00 );
213 delay_ms( 100 );
214
215 spi2_8TxRx( 0x45 );
216 spi2_8TxRx( 0x78 );
217 spi2_8TxRx( 0x69 );
218 spi2_8TxRx( 0x74 );
219 spi2_8TxRx( 0x00 );
220 spi2_8TxRx( 0x00 );
221 spi2_8TxRx( 0x00 );
222 spi2_8TxRx( 0x00 );
223 MP3_DCS_DES();
224
225 #if VS1003_DEBUG
226 printf( " Vs1003_Sine_Test:end\n " );
227 #endif
228 }
229
230 // 用于测试vs1003的各个模块
231 void Vs1003_Test()
232 {
233 int i = 0 ;
234 int16u_t data;
235 spi2_init();
236 Vs1003_Init();
237 /*
238 给音量控制寄存器SCI_VOL循环写入最高值和最低值,正常情况下能从耳机听到滴滴
239 的声音,具体步骤如下:
240 ●拉低xCS;
241 ●设置音量最高:SCI_VOL = 0x0000;
242 ●拉高xCS;
243 ●等待500ms,这个时间控制在0.5到1s之间,太大太小可能都无法听到;
244 ●拉低xCS;
245 ●设置音量最低:SCI_VOL = 0xFFFF;
246 ●等待500ms,道理同上;
247 ●拉高xCS;
248 ●循环,否则以上步骤无法识别。
249 */
250
251 do {
252 data = 0x0 ;
253 printf( " Test Start,Reg Vol data=%d\n " ,data);
254 Vs1003_CMD_Write(SPI_VOL, 0x2020 );
255 data = Vs1003_CMD_Read(SPI_VOL);
256 printf( " Test end, Reg VOL data=%x\n " ,data);
257 delay_ms( 1000 );
258 } while ( 0 );
259
260 while ( 1 ){
261 for (i = 0 ;i < 15 ;i ++ )
262 {
263 Vs1003_Sine_Test(i); // 使正弦波的频率依次增加,适当延时,这样在耳机中就能听到音调越来越高的声音
264 }
265 for (i = 15 ; i > 0 ; i ++ )
266 {
267 Vs1003_Sine_Test(i);
268 }
269 }
270 }