TMS320F28335 和 VS1003B 之间的通信

小白之前学习过一段时间dsp,想用tms320f28335这款芯片来做一个mp3播放器,先用普中的一个f28335开发板做实验,历经了一些磨难终于做出来了一个mp3播放器,回头总结一下解码芯片和dsp芯片的通信,考虑到f28335和tf卡之间通信用的是硬件的spi模块,那么f28335和解码芯片vs1003b之间就需要用软件来模拟时序,网上有51和vs1003b之间通信的代码,在此基础上,我稍微做了修改,加了很多注释,变成f28335和vs1003b之间的通信代码:

/*
 * smg.c
 *
 *  Created on: 2019-05-02
 *    
 */

#include "smg.h"
unsigned char vol=0x10;

void Port_Init(void){
		EALLOW;
		SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟
		//DREQ
		GpioCtrlRegs.GPCMUX1.bit.GPIO76=0;
		GpioCtrlRegs.GPCDIR.bit.GPIO76=0;
		GpioCtrlRegs.GPCPUD.bit.GPIO76=0;
		//MISO
		GpioCtrlRegs.GPCMUX1.bit.GPIO75=0;
		GpioCtrlRegs.GPCDIR.bit.GPIO75=0;
		GpioCtrlRegs.GPCPUD.bit.GPIO75=0;//上面这两个是输入,其中MISO悬空用不到
		//XRST
		GpioCtrlRegs.GPCMUX1.bit.GPIO70=0;
		GpioCtrlRegs.GPCDIR.bit.GPIO70=1;
		GpioCtrlRegs.GPCPUD.bit.GPIO70=0;
		//MOSI
		GpioCtrlRegs.GPCMUX1.bit.GPIO71=0;
		GpioCtrlRegs.GPCDIR.bit.GPIO71=1;
		GpioCtrlRegs.GPCPUD.bit.GPIO71=0;
		//SCLK
		GpioCtrlRegs.GPCMUX1.bit.GPIO72=0;
		GpioCtrlRegs.GPCDIR.bit.GPIO72=1;
		GpioCtrlRegs.GPCPUD.bit.GPIO72=0;
		//XCS
		GpioCtrlRegs.GPCMUX1.bit.GPIO73=0;
		GpioCtrlRegs.GPCDIR.bit.GPIO73=1;
		GpioCtrlRegs.GPCPUD.bit.GPIO73=0;
		//XDCS
		//这个引脚给我的感觉好像没有用到
		//其实是用到的,SCI_MODE初始化为0x0804(默认是0x0800)
		//默认SDI in VS1002 Native Modes (New Mode) (就是上面那个8)
//		In VS1002 native modes(SM NEWMODE is 1), byte synchronization is achieved by XDCS. The state of
//		XDCS may not change while a data byte transfer is in progress.

		//SM SDISHARE 为0,XDCS和XCS 是分开的,具体用法如下:
//		XDCS XCS Active low chip select input. A high level forces the serial interface into
//		standby mode, ending the current operation. A high level also forces serial
//		output (SO) to high impedance state. If SM SDISHARE is 1, pin
//		XDCS is not used, but the signal is generated internally by inverting
//		XCS.高电平迫使进入备用状态,ending the current operation,低电平有效(选中,具体看时序图)
		GpioCtrlRegs.GPCMUX1.bit.GPIO74=0;
		GpioCtrlRegs.GPCDIR.bit.GPIO74=1;
		GpioCtrlRegs.GPCPUD.bit.GPIO74=0;

		EDIS;
}

//SCLK上升沿,从机读取数据(采样)
//spi 通信方式给VS1003b发送数据
//这里让我担心的是,F28335时钟太快了,VS1003b识别不了上升沿,下降沿,后来发现没问题

//XCS和写入数据之间的关系:
//Serial clock input. The serial clock is also used internally as the master
//clock for the register interface.
//SCK can be gated or continuous. In either case, the first rising clock edge
//after XCS has gone low marks the first bit to be written.//重点
//SI Serial input. If a chip select is active, SI is sampled on the rising CLK edge.

//读写频率要求(一开始有点担心,实践中没出现问题):
//Note: As tWL and tWH, as well as tH require at least 2 clock cycles, the maximum speed for the SPI
//bus that can easily be used is 1/6 of VS1003’s internal clock speed CLKI. Slightly higher speed can be
//achieved with very careful timing tuning. For details, see Application Notes for VS10XX.
//Note: Although the timing is derived from the internal clock CLKI, the system always starts up in 1.0×
//mode, thus CLKI=XTALI./

//SPI Input Clock Frequency  CLKI/6 MHz
//CLKI Value for SCI reads. SCI and SDI writes allow CLK1/4.

//一个xCS上升沿之后就可以一直SDI了,而每个wr_command()都会有一个上升沿:
//SDI data is synchronized with a raising edge of xCS as shown in Figure 10. However, every byte doesn’t
//need separate synchronization.
void spi_write(unsigned char dat){//软件模拟spi通信时序
		char i=0;
		for(i=0;i<8;i++)
		{
			SCLK_SETL;
			if(dat&0x80)//从最高位(MSB)开始
				MOSI_SETH;
			else
				MOSI_SETL;
			SCLK_SETH;	//时钟上升沿,从机读取数据
			dat<<=1;
		}
}

//VS1003内部寄存器写入指令(先送MSB):
//The serial bus protocol for the Serial Command Interface SCI (Chapter 8.5) consists of an instruction
//byte, address byte and one 16-bit data word. Each read or write operation can read or write a single
//register. Data bits are read at the rising edge, so the user should update data at the falling edge. Bytes are
//always send MSb first.

//DREQ(data request)引脚的功能:
//The DREQ pin/signal is used to signal if VS1003’s FIFO is capable of receiving data. If DREQ is high,
//VS1003 can take at least 32 bytes of SDI data or one SCI command. When these criteria are not met,
//DREQ is turned low, and the sender should stop transferring new data.
void wr_command(unsigned char addr,unsigned char hdat,unsigned char ldat ){
	//51单片机在检测输入之前要先拉高电位,但是dsp没有必要
	while (!DREQ);	//等待到VS1003可以接受数据
	XCS_SETL;		//片选,见数据手册7.7.3
	spi_write(0x02);//写操作码,以下是操作码opcode
//	READ  0b0000 0011 Read data
//	WRITE 0b0000 0010 Write data
	spi_write(addr);//寄存器地址
	spi_write(hdat);//data高8位
	spi_write(ldat);//data低8位
	XCS_SETH;		//XCS先低后高,一个命令写完。高电平关片选
}


void Mp3Reset(void){
	XRST_SETL;//硬件复位
//  XRESET的用法:
//	When the XRESET -signal is driven low, VS1003 is reset and all the control registers and internal states
//	are set to the initial values

	DELAY_US(100);
	XCS_SETH;
	XDCS_SETH;//先进入备用状态,ending the current operation.
	XRST_SETH;//硬件复位结束
//XCS 和 XDCS的用法:
//	After a hardware reset (or at power-up) DREQ will stay down for at least 16600 clock cycles, which
//	means an approximate 1.35 ms delay if VS1003 is run at 12.288 MHz. After this the user should set
//	such basic software registers as SCI MODE, SCI BASS, SCI CLOCKF, and SCI VOL before starting
//	decoding. See section 8.6 for details

	wr_command(0x00,0x08,0x04);
	//SCI_MODE调节0000 1000 0000 0100,(默认0x0800)
	//第11位是1,调节成VS1002 native SPI modes
	DELAY_US(10);
//	第2位是1,代表将进行软件复位:
//	Software reset is initiated by setting SM RESET to 1. This bit is cleared automatically
//	In some cases the decoder software has to be reset. This is done by activating bit 2 in SCI MODE register
//	(Chapter 8.6.1). Then wait for at least 2 us, then look at DREQ. DREQ will stay down for at least 16600
//	clock cycles, which means an approximate 1.35 ms delay if VS1003 is run at 12.288 MHz. After DREQ
//	is up, you may continue playback as usual.

	while (!DREQ);//软件复位结束,开始写寄存器
	wr_command(0x02,0x00,0x55);
//设置重低音提升:SPI_BASS = 0x0055;表示50Hz以下低音获得5db提升,高音不提升。
//	0x2 rw 0 2100 CLKI BASS Built-in bass/treble enhancer
	DELAY_US(10);
//有时候不要延时:
//This is the worst-case time that DREQ stays low after writing to this register. The user may choose to
//skip the DREQ check for those register writes that take less than 100 clock cycles to execute.
	wr_command(0x03,0x98,0x00);
//设置VS1003的时钟:SCI_CLOCKF = 0x9800;表示3倍频,倍频增量1.5x,时钟频率12.288MHZ
//	0x3 rw 0 11000 XTALI5 CLOCKF Clock freq + multiplier
	DELAY_US(10);
	wr_command(0x05,0xbb,0x81);
//设置VS1003的采样率:SPI_AUDATA = 0xBB81,采样率48khz,立体声
//采样率常见44.1khz和48khz,采样率在这之上的,人耳几乎听不出区别了
//vs1003b几乎支持所有位率的mp3格式,位率和采样率不一样
//0x5 rw 0 3200 CLKI AUDATA Misc. audio data
	DELAY_US(10);
	wr_command(0x0b,vol,vol);
//音量左声道-17*0.5db,右声道-17*0.5db。
//0xB rw 0 2100 CLKI VOL Volume control
//关于音量调节我一直很糊涂,不晓得啥意思,手册上这么写:
//	SCI VOL is a volume control for the player hardware. For each channel, a value in the range of 0..254
//	may be defined to set its attenuation from the maximum volume level (in 0.5 dB steps). The left channel
//	value is then multiplied by 256 and the values are added. Thus, maximum volume is 0 and total silence
//	is 0xFEFE.
//	Example: for a volume of -2.0 dB for the left channel and -3.5 dB for the right channel: (4*256) + 7
//	= 0x407. Note, that at startup volume is set to full volume. Resetting the software does not reset the
//	volume setting.
//Note: Setting SCI VOL to 0xFFFF will activate analog powerdown mode
//我对它的example这么理解,最高0dB,0x0407,代表左声道-4*0.5=-2.0,右声道-7*0.5=-3.5
	DELAY_US(10);
	spi_write(0);
	spi_write(0);
	spi_write(0);
	spi_write(0);//向vs1003发送4个字节无效数据,用以启动SPI发送
//虽然和手册上面推荐的寄存器不一样,但是都是先初始化四个寄存器再写四个0。
//其实是初始化了5个寄存器,可能重要的是后面的写0操作
//数据手册推荐的步骤:
//	All tests are started in a similar way: VS1003 is hardware reset, SM TESTS is set, and then a test
//	command is sent to the SDI bus. Each test is started by sending a 4-byte special command sequence,
//	followed by 4 zeros. The sequences are described below.
}

void send_dat(unsigned char dat){
	while (!DREQ);//VS1003的DREQ为高,缓冲池数据少于32B
	spi_write(dat);
}

代码的文件名之所以是smg.c,是因为这段代码在普中的tms320f28335开发板的数码管实验的程序上面改编的,他们两是有相似之处的,而且两者共用一些引脚,能通过数码管是否闪烁来初步预判f28335和vs1003b之间是否通信正常。这段代码本身并不长,但是注释特别多,有的注释是原来的51代码里面的注释,但大部分注释(英文注释),是我从vs1003b数据手册上面找到的,对相应模块的规定,也就是这些函数要这么写的理由。这个对小白的价值可能更大。

在main.c里面先#include “smg.h”,在调用这些函数即可,主函数里面还牵涉到tf卡的读写,就不列出了,主函数里面和vs1003b有关的函数有:Port_Init(); Mp3Reset(); XDCS_SETL;和send_dat();,顶层51单片机代码和dsp代码差别不大,不做赘述。

非科班dsp小白,如有错误虚心接受。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值