CH376S和VS1003均采用SPI
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) { SPI1_SetSpeed(SPI_SPEED_16); // //高速,对VS1003B,最大值不能超过36.864/6Mhz,这里设置为4.5M if(CH376DiskConnect()==USB_INT_SUCCESS) /* 检查U盘是否连接,不支持SD卡 */ { // LED2 = 0; USART1_SendByte(0xe3); if(CH376DiskMount()==USB_INT_SUCCESS) /* 初始化磁盘并测试磁盘是否就绪 */ { USART1_SendByte(0xe4); // LED2 = 1; // delay_ms(1000); // LED2 = 0; // delay_ms(1000); // LED2 = 1; // delay_ms(1000); // LED2 = 0; u8Length = CH376ReadBlock(pu8Temp); /*从当前主机端点的接收缓冲区读取数据块,返回长度*/ if (u8Length != 0) { CH376DiskQuery((u32 *)pu8Temp); /*查询磁盘剩余空间信息,扇区数*/ strcpy((char*)pu8Temp, "\\风.MP3"); u8Result = CH376FileOpen(pu8Temp); // 打开文件
if (u8Result == USB_INT_SUCCESS) { USART1_SendByte(0xe5); //LED2 = 1; u32FileLen = CH376GetFileSize(); /* 获取文件大小 */ while (u32DataCnt < u32FileLen) { pu8Temp = u8SectorBuf; CH376SecRead(pu8Temp, 1, 0); /*以扇区为单位从当前位置读取数据块,不支持SD卡*/ u32DataCnt += 512; // SPI1_SetSpeed(SPI_SPEED_8);
// VS_XDCS = 0; /*VS_XDCS = 0,选择vs1003的数据接口 */ i = 0; while (i < 512) //循环发送512个字节 { while (VS_DREQ == 0); //等待DREQ为高 VS_XDCS = 0; for (j=0; j<32; j++) { SPI1_ReadWriteByte(*pu8Temp++); } i += 32; VS_XDCS = 1; } // VS_XDCS = 1; /*VS_XDCS = 1*/ } } } } } }
}
u8 mWaitInterrupt( void ) { /* 等待CH376中断并获取状态,主机端等待操作完成,返回操作状态 */ while ( Query376Interrupt( ) == FALSE ); /* 一直等中断 */ xWriteCH376Cmd( CMD_GET_STATUS ); /* 产生操作完成中断,获取中断状态 */ return( xReadCH376Data( ) ); }
/*****************************************************
* Name: xWriteCH376Cmd
* Function: 写命令到CH376去
* Input: no
* Output: no
* Author: PowerAVR / 2009-12-19
* Update:
*****************************************************/ void xWriteCH376Cmd( u8 mCmd ) /* 向CH376写命令 */ { xEndCH376Cmd = 1;; /* 防止之前未通过xEndCH376Cmd禁止SPI片选 */ delay_us(1); /* 对于双向I/O引脚模拟SPI接口,那么必须确保已经设置SPI_SCS,SPI_SCK,SPI_SDI为输出方向,SPI_SDO为输入方向 */ xEndCH376Cmd = 0; /* SPI片选有效 */ SPI2_ReadWriteByte( mCmd ); /* 发出命令码 */
// DelayXms(1);; /* 延时1.5uS确保读写周期大于1.5uS,或者用上面一行的状态查询代替 */
} /*****************************************************
* Name: xWriteCH376Data
* Function: 写1字节数据到CH376
* Input: no
* Output: no
* Author: PowerAVR / 2009-12-19
* Update:
*****************************************************/ void xWriteCH376Data( u8 mData ) /* 向CH376写数据 */ { SPI2_ReadWriteByte( mData ); // delay_us(1); /* 确保读写周期大于0.6uS */ }
/*****************************************************
* Name: xReadCH376Data
* Function: 从CH376读取1字节数据
* Input: no
* Output: no
* Author: PowerAVR / 2009-12-19
* Update:
*****************************************************/ u8 xReadCH376Data( void ) /* 从CH376读数据 */ { // delay_us(1); /* 确保读写周期大于0.6uS */ return( SPI2_ReadWriteByte( 0xff) ); }
/*****************************************************
* Name: Query376Interrupt
* Function: 查询CH376中断(INT#低电平)
* Input: no
* Output: no
* Author: PowerAVR / 2009-12-19
* Update:
*****************************************************/ u8 Query376Interrupt( void ) { // return( GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)? FALSE : TRUE ); /* 如果未连接CH376的中断引脚则查询兼做中断输出的SDO引脚状态 */
return( (PBin(14)) ? FALSE : TRUE ); }
/******************************SPI1及VS1003端口初始化*******************************/ void SPI1_Init(void) { RCC->APB2ENR|=1<<2; //PORTA时钟使能 RCC->APB2ENR|=1<<12; //SPI1时钟使能 //这里只针对SPI口初始化 GPIOA->CRL&=0X000FFFFF; GPIOA->CRL|=0XBBB00000;//PA5.6.7复用 GPIOA->ODR|=0X7<<5; //PA5.6.7上拉 SPI1->CR1|=0<<10;//全双工模式 SPI1->CR1|=1<<9; //软件nss管理 SPI1->CR1|=1<<8;
SPI1->CR1|=1<<2; //SPI主机 SPI1->CR1|=0<<11;//8bit数据格式 SPI1->CR1|=1<<1; //空闲模式下SCK为1 CPOL=1 SPI1->CR1|=1<<0; //数据采样从第二个时间边沿开始,CPHA=1 SPI1->CR1|=5<<3; //Fsck=Fcpu/64
// SPI1->CR1|=0<<7; //MSBfirst SPI1->CR1 &= ~(1<<7); //MSBfirst SPI1->CR1|=1<<13; //CRC 计算多项式 SPI1->CR1|=1<<6; //SPI设备使能 // SPI1_ReadWriteByte(0xff);//启动传输 }
//SPI 速度设置函数 //SpeedSet: //SPI_SPEED_2 2分频 (SPI 36M@sys 72M) //SPI_SPEED_4 4分频 (SPI 18M@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 switch(SpeedSet) { case SPI_SPEED_2://二分频 SPI1->CR1|=0<<3;//Fsck=Fpclk/2=36Mhz break; case SPI_SPEED_4://四分频 SPI1->CR1|=1<<3;//Fsck=Fpclk/4=18Mhz break; case SPI_SPEED_8://八分频 SPI1->CR1|=2<<3;//Fsck=Fpclk/8=9Mhz break; case SPI_SPEED_16://十六分频 SPI1->CR1|=3<<3;//Fsck=Fpclk/16=4.5Mhz break; case SPI_SPEED_32: //32分频 SPI1->CR1|=4<<3;//Fsck=Fpclk/32=2.25Mhz break; case SPI_SPEED_64: //64分频 SPI1->CR1|=5<<3;//Fsck=Fpclk/64=1.125Mhz break; case SPI_SPEED_128: //128分频 SPI1->CR1|=6<<3;//Fsck=Fpclk/128=562.5Khz break; case SPI_SPEED_256: //256分频 SPI1->CR1|=7<<3;//Fsck=Fpclk/16=281.25Khz break; } SPI1->CR1|=1<<6; //SPI设备使能 } //SPIx 读写一个字节 //TxData:要写入的字节 //返回值:读取到的字节 u8 SPI1_ReadWriteByte(u8 TxData) { // u8 retry=0; // while((SPI1->SR&1<<1)==0)//等待发送区空 // { // retry++; // if(retry>200)return 0; // } // SPI1->DR=TxData; //发送一个byte // retry=0; // while((SPI1->SR&1<<0)==0) //等待接收完一个byte // { // retry++; // if(retry>200)return 0; // } // return SPI1->DR; //返回收到的数据 while((SPI1->SR&1<<1)==0);//等待发送区空 SPI1->DR=TxData; //发送一个byte
while((SPI1->SR&1<<0)==0); //等待接收完一个byte return SPI1->DR; //返回收到的数据 }
/*****************************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; GPIOD->ODR|=1<<12;
//这里只针对