}
/*****************************SPI2及CH376端口初始化*************************************/
void SPI2_Init(void)
{
RCC->APB2ENR|=1<<3; //PORTB时钟使能
RCC->APB2ENR|=1<<5; //PORTD时钟使能
RCC->APB1ENR|=1<<14; //SPI2时钟使能
/*CH376端口初始化*/
// GPIOD->CRL &= 0XF0FF0FFF; //(SCS)PD3推挽输出 (INT#)PD6输入
// GPIOD->CRL |= 0X08003000;
// GPIOD->ODR |= 1 << 6;
GPIOD->CRH &= 0XFF00FFFF; //(SCS)PD12推挽输出 (INT#)PD13输入
GPIOD->CRH |= 0X00430000;
//这里只针对SPI2口初始化
GPIOB->CRH&=0X000FFFFF;
GPIOB->CRH|=0XBBB00000;//PB.13,PB.14,PB.15复用
// GPIOB->ODR|=1<<14; //PB.14上拉
GPIOB->ODR|=0x7<<13; //PB.14上拉
SPI2->CR1|=0<<10;//全双工模式
SPI2->CR1|=1<<9; //软件nss管理
SPI2->CR1|=1<<8;
SPI2->CR1|=1<<2; //SPI主机
SPI2->CR1|=0<<11;//8bit数据格式
// SPI2->CR1|=0<<1; //空闲模式下SCK为0 CPOL=0
// SPI2->CR1|=0<<0; //数据采样从第1个时间边沿开始,CPHA=0
// SPI2->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
// SPI2->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1
SPI2->CR1 &= ~(1<<1); //空闲模式下SCK为0,所以此位CPOL=0
SPI2->CR1 |= 0<<0; //数据采样从第一个时间边沿开始,CPHA=0
// SPI2->CR1|=3<<3; //Fsck=Fcpu/16
SPI2->CR1|=1<<3; //Fsck=Fcpu/4
SPI2->CR1 &= ~(1<<7); //MSBfirst
// SPI2->CR1|=0<<7; //MSBfirst
// SPI2->CR1|=1<<13; //CRC 计算多项式
SPI2->CR1|=1<<6; //SPI设备使能
SPI2_ReadWriteByte(0xff);//启动传输
}
// SPI总线速度设置
#define SPI_SPEED_2 0
#define SPI_SPEED_4 1
#define SPI_SPEED_8 2
#define SPI_SPEED_16 3
#define SPI_SPEED_32 4
#define SPI_SPEED_256 5
//SPI 速度设置函数
//SpeedSet:
//SPI_SPEED_2 2分频 (SPI 36M@sys 72M)
//SPI_SPEED_8 8分频 (SPI 9M@sys 72M)
//SPI_SPEED_16 16分频 (SPI 4.5M@sys 72M)
//SPI_SPEED_256 256分频 (SPI 281.25K@sys 72M)
void SPI1_SetSpeed(u8 SpeedSet)
{
SPI1->CR1&=0XFFC7;//Fsck=Fcpu/256
if(SpeedSet==SPI_SPEED_2)//二分频
{
SPI1->CR1|=0<<3;//Fsck=Fpclk/2=36Mhz
}
else if(SpeedSet==SPI_SPEED_4)//4分频
{
SPI1->CR1|=1<<3;//Fsck=Fpclk/4=18Mhz
}
else if(SpeedSet==SPI_SPEED_8)//八分频
{
SPI1->CR1|=2<<3;//Fsck=Fpclk/8=9Mhz
}else if(SpeedSet==SPI_SPEED_16)//十六分频
{
SPI1->CR1|=3<<3;//Fsck=Fpclk/16=4.5Mhz
}else if(SpeedSet==SPI_SPEED_32)//32分频
{
SPI1->CR1|=1<<5;//Fsck=Fpclk/32=2.25Mhz
}else //256分频
{
SPI1->CR1|=7<<3; //Fsck=Fpclk/256=281.25Khz 低速模式
}
SPI1->CR1|=1<<6; //SPI设备使能
}
这是初始化程序~
还有
SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1
SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1
SPI2->CR1 &= ~(1<<1); //空闲模式下SCK为0,所以此位CPOL=0
SPI2->CR1 |= 0<<0; //数据采样从第一个时间边沿开始,CPHA=0
SPI1 和SPI2要设置成一样吗?我对SPI不是很了解?
以下为主函数
u8 u8SectorBuf[512];
int main(void)
{
u8 u8Result;
u8 u8Length;
u8 *pu8Temp = u8SectorBuf;
u32 u32FileLen = 0;
u32 u32DataCnt = 0;
u32 i,j;
Stm32_Clock_Init(9); //72M
delay_init(72); //延时初始化
uart_init(72, 9600); //设置串口1的波特率
// LED_Init();
// LED2 = 1;
Vs1003_Init(); //Vs1003的初始化
Vs1003SoftReset(); //软复位VS1003
VsRamTest(); //RAM测试
VsSineTest(); //VS1003正弦测试
CH376_Init();
while(1)
{
if(CH376DiskConnect()==USB_INT_SUCCESS) /* 检查U盘是否连接,不支持SD卡 */
{
USART1_SendByte(0xe3);
if(CH376DiskMount()==USB_INT_SUCCESS) /* 初始化磁盘并测试磁盘是否就绪 */
{
u8Length = CH376ReadBlock(pu8Temp); /*从当前主机端点的接收缓冲区读取数据块,返回长度*/
if (u8Length != 0)
{
CH376DiskQuery((u32 *)pu8Temp); /*查询磁盘剩余空间信息,扇区数*/
strcpy((char*)pu8Temp, "\\光辉岁月.MP3");
u8Result = CH376FileOpen(pu8Temp); // 打开文件
USART1_SendByte(0xe5);
if (u8Result == USB_INT_SUCCESS)
{
u32FileLen = CH376GetFileSize(); /* 获取文件大小 */
while (u32DataCnt < u32FileLen)
{
pu8Temp = u8SectorBuf;
CH376SecRead(pu8Temp, 1, 0); /*以扇区为单位从当前位置读取数据块,不支持SD卡*/
u32DataCnt += 512;
VS_XDCS_CLR(); /*VS_XDCS = 0,选择vs1003的数据接口 */
i = 0;
while (i < 512)
{
while(VS_DREQ==0); //等待DREQ为高
for (j=0; j<32; j++)
{
SPI1_ReadWriteByte(*pu8Temp++);
}
i += 32;
}
VS_XDCS_SET(); /*VS_XDCS = 1*/
}
}
}
}
}
}
/**************************************************************************************/
//软复位VS1003
void Vs1003SoftReset(void)
{
u8 retry;
while((VS_DREQ)==0);//等待软件复位结束
SPI1_ReadWriteByte(0X00);//启动传输
retry=0;
while(Vs1003_REG_Read(SPI_MODE)!=0x0804)// 软件复位,新模式
{
Vs1003_CMD_Write(SPI_MODE,0x0804);// 软件复位,新模式
delay_ms(2);//等待至少1.35ms
if(retry++>100)break;
}
while (VS_DREQ == 0);//等待软件复位结束
retry=0;
while(Vs1003_REG_Read(SPI_CLOCKF)!=0X9800)//设置vs1003的时钟,3倍频 ,1.5xADD
{
Vs1003_CMD_Write(SPI_CLOCKF,0X9800);//设置vs1003的时钟,3倍频 ,1.5xADD
if(retry++>100)break;
}
retry=0;
while(Vs1003_REG_Read(SPI_AUDATA)!=0XBB81)//设置vs1003的采样率,采样率48K,立体声
{
Vs1003_CMD_Write(SPI_AUDATA,0XBB81);//设置vs1003的采样率,采样率48K,立体声
if(retry++>100)break;
}
//Vs1003_CMD_Write(SPI_CLOCKF,0X9800);
//Vs1003_CMD_Write(SPI_AUDATA,0XBB81); //采样率48k,立体声
VS_SET_VOL(VS_VOLT,VS_BASS);
ResetDecodeTime();//复位解码时间
//向vs1003发送4个字节无效数据,用以启动SPI发送
VS_XDCS_CLR();//选中数据传输
SPI1_ReadWriteByte(0XFF);
SPI1_ReadWriteByte(0XFF);
SPI1_ReadWriteByte(0XFF);
SPI1_ReadWriteByte(0XFF);
VS_XDCS_SET();//取消数据传输
delay_ms(20);
}
//硬复位MP3
void Mp3Reset(void)
{
VS_XRESET_CLR();
delay_ms(20);
VS_XDCS_SET(); //取消数据传输
VS_XCS_SET();//取消数据传输
delay_ms(5);//!!!!自己加的
VS_XRESET_SET();
delay_ms(5);//!!!!自己加的
while(VS_DREQ==0); //等待DREQ为高
delay_ms(20);
}
//向VS1003写命令
//address:命令地址
//data:命令数据
void Vs1003_CMD_Write(u8 address,u16 data)
{
while(VS_DREQ==0);//等待空闲
SPI1_SetSpeed(SPI_SPEED_256);//低速
VS_XDCS_SET(); //MP3_DATA_CS=1;
VS_XCS_CLR(); //MP3_CMD_CS=0;
SPI1_ReadWriteByte(VS_WRITE_COMMAND);//发送VS1003的写命令
SPI1_ReadWriteByte(address); //地址
SPI1_ReadWriteByte(data>>8); //发送高八位
SPI1_ReadWriteByte(data); //第八位
VS_XCS_SET(); //MP3_CMD_CS=1;
SPI1_SetSpeed(SPI_SPEED_16);//高速
}
//向VS1003写数据
void Vs1003_DATA_Write(u8 data)
{
VS_XDCS_CLR(); //MP3_DATA_CS=0;
//while(VS_DREQ==0); //VS1003的DREQ为高才能写入数据????这句可以不要??
while(VS_DREQ==0); //此处为改动!!!!!!!!!
SPI1_ReadWriteByte(data);
VS_XDCS_SET(); //MP3_DATA_CS=1;
VS_XCS_SET(); //MP3_CMD_CS=1;
}
//读VS1003的寄存器
//读VS1003
//注意不要用倍速读取,会出错
u16 Vs1003_REG_Read(u8 address)
{
u16 temp=0;
while(VS_DREQ==0);//非等待空闲状态
SPI1_SetSpeed(SPI_SPEED_256);//低速
VS_XDCS_SET(); //MP3_DATA_CS=1;
VS_XCS_CLR(); //MP3_CMD_CS=0;
SPI1_ReadWriteByte(VS_READ_COMMAND);//发送VS1003的读命令
SPI1_ReadWriteByte(address); //地址
temp=SPI1_ReadWriteByte(0xff); //读取高字节
temp=temp<<8;
temp+=SPI1_ReadWriteByte(0xff); //读取低字节
VS_XCS_SET(); //MP3_CMD_CS=1;
SPI1_SetSpeed(SPI_SPEED_16);//高速
return temp;
}