⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sd.c

📁 用串口来显示和操作的基于ucos的以sd卡为存储介质的mp3源码
💻 C
字号:
#define IN_SD
#include "User.h"
 
 
INT8U sectorBuffer_data[16];

typedef struct
{
    INT8U       Drive;          // 驱动器号
    INT16U		Len;			//长度
    INT32U      SectorIndex;    // 操作的扇区
    INT8U       *Buf;           // 数据存储位置
} Disk_RW_Parameter;


void MSPI_Init(INT8U mode)
{
	INT8U CPSDVSR,SCR;
	INT16U temp;
	
	if(mode == 0)
	{
	    IO0DIR |= SD_Chip_Select;
	    PINSEL1 = (PINSEL1 & 0xFFFFF303) | 0xA8;
	    temp =  Fpclk/100000; // CLOCK<=100K
	    SCR = temp / 255;
	    CPSDVSR = temp / (SCR + 1);
	    if(CPSDVSR % 2)
	    {
	    	CPSDVSR += 1;
	    }
	    SSPCR0 = (SCR << 8)  |			// SPI 时钟设置 
 		         (0x00 << 7) |			// CPHA = 0, 
 		         (0x00 << 6) |			// CPOL = 0, 
 		         (0x00 << 4) |			// FRF 帧格式=SPI,
 	             (0x07 << 0);			// DDS 数据长度 = 8, 
 	         
        SSPCR1 = (0x00 << 3) |			// SOD 从机输出禁能
 		         (0x00 << 2) |			// MS 主从选择 = 0,
 		         (0x01 << 1) |			// SSE SSP 使能允许与其它设备通信
 		         (0x00 << 0) ;			// LBM 回写模式, 
 		SSPCPSR = CPSDVSR;	//SSP 时钟预分频(PCLK/16) 
 	    SSPICR = 0x03;		//中断清除寄存器
	}
	else if(mode == 1)
	{
		temp =  Fpclk/10000000; // CLOCK<=10M
	    SCR = temp / 255;
	    CPSDVSR = temp / (SCR + 1); 
	    if(CPSDVSR % 2)
	    {
	    	CPSDVSR += 1;
	    }
	    SSPCR0 &= 0x00FF | (SCR << 8); 
	    SSPCPSR = CPSDVSR;
	    SSPICR = 0x03;		//中断清除寄存器
	}
}

 
INT8U SPI_RW(INT8U data) 
{ 
	SSPDR = data;
	while((SSPSR & 0x01) == 0);	 //等待SPI将数据发送完毕
	return(SSPDR);
}
 
INT8U Write_Command_SD(INT8U *CMD) 
{
    INT8U i = 0, tmep = 0, retry = 0;
 
    SD_Disable();
    SPI_RW(0xff); //发送8个时钟
    SD_Enable();
    
    //发送6比特的命令到SD/SD卡
    CMD[0] = (CMD[0] & 0x3f) | 0x40;
    for(i = 0; i < 0x06; i++) 
    { 
    	SPI_RW(*CMD++);
    } 
    
    //获得16比特的响应
    SPI_RW(0xff); //读取并放弃第一个比特,只有最后一个比特是需要的.
    
    do 
    {
    	tmep = SPI_RW(0xff);
        retry++;
    }
    while((tmep == 0xff) && (retry < 100)); 
    return(tmep);
}

 
INT8U SD_Init(void) 
{ 
  INT8U retry, temp;
  INT8U i = 0;
  INT8U CMD[] = {CMD0, 0x00, 0x00, 0x00, 0x00, 0x95};
    
  MSPI_Init(0);
  SD_Enable();
  for(i=0;i<250;i++) 
  __asm
  {
  	NOP
  }
  for(i = 0; i < 0x0f; i++)
  { 
  	SPI_RW(0xff); //发送至少74个时钟
  }       
  //Send Command CMD0 to SD/SD Card
  retry = 0;
  do 
  { //retry 200 times to send CMD0 command 
    
    temp = Write_Command_SD(CMD);
    retry++;
    if(retry >= 200) 
    { //time out
       return(INIT_CMD0_ERROR); //CMD0 Error!
    }
  } 
  while(temp != 1);
       
  //Send Command CMD1 to SD/SD-Card
  CMD[0] = CMD1; //Command 1
  CMD[5] = 0xFF;
  retry = 0;
  do 
  { //retry 100 times to send CMD1 command 
     temp=Write_Command_SD(CMD);
     retry++;
     if(retry>=100) 
     { //time out
        return(INIT_CMD1_ERROR);//CMD1 Error!
     }
  } 
  while(temp != 0);
    
  MSPI_Init(1);              
  SD_Disable();
  return(0);
} 
 
void SD_get_volume_info(VOLUME_INFO_TYPE* vinf)
{   
   // read the CSD register
   Read_CSD_SD(sectorBuffer_data);
 
   vinf->sector_count = sectorBuffer_data[6] & 0x03;
   vinf->sector_count <<= 8;
   vinf->sector_count += sectorBuffer_data[7];
   vinf->sector_count <<= 2;
   vinf->sector_count += (sectorBuffer_data[8] & 0xc0) >> 6;
         
   vinf->sector_multiply = sectorBuffer_data[9] & 0x03;
   vinf->sector_multiply <<= 1;
   vinf->sector_multiply += (sectorBuffer_data[10] & 0x80) >> 7;
 
   vinf->size_MB = vinf->sector_count >> (9-vinf->sector_multiply);
         
   // get the name of the card
   Read_CID_SD(sectorBuffer_data);
   vinf->name[0] = sectorBuffer_data[3];
   vinf->name[1] = sectorBuffer_data[4];
   vinf->name[2] = sectorBuffer_data[5];
   vinf->name[3] = sectorBuffer_data[6];
   vinf->name[4] = sectorBuffer_data[7];
   vinf->name[5] = 0x00;
}
 
INT8U SD_write_sector(INT32U Number_Sector, INT8U* Buffer) 
{  
    INT8U tmp,retry;
    INT16U i;
    //Command 24 is a writing blocks command for SD/SD-Card.
    INT8U CMD[] = {0x58, 0x00, 0x00, 0x00, 0x00, 0xFF}; 
    
    //asm("cli"); //clear all interrupt.
    Number_Sector  <<= 9; //addr = addr * 512
         
    CMD[1] = ((Number_Sector & 0xFF000000) >> 24 );
    CMD[2] = ((Number_Sector & 0x00FF0000) >> 16 );
    CMD[3] = ((Number_Sector & 0x0000FF00) >> 8 );
    //CMD[4] = (INT8U)((Number_Sector & 0x000000FF) >> 0 );
    //Send Command CMD24 to SD/SD-Card (Write 1 Block/512 Bytes)
    retry = 0;
    do 
    {  //Retry 100 times to send command.
       tmp = Write_Command_SD(CMD);
       if(++retry >= 100) 
       { 
           return(tmp); //send commamd Error!
       }
    }
    while(tmp != 0); 
    
    //发送至少100个时钟到SD/SD卡
    for(i = 0; i < 100; i++)
       SPI_RW(0xff);
         
    //Send Start Byte to SD/SD-Card
    SPI_RW(0xFE);   
         
    //Now send real data Bolck (512Bytes) to SD/SD-Card
    for(i = 0; i < 512; i++)
       SPI_RW(*Buffer++); //send 512 bytes to Card
 
    //CRC-Byte 
    SPI_RW(0xFF); //Dummy CRC
    SPI_RW(0xFF); //CRC Code
    
    
    tmp = SPI_RW(0xff);   // read response
    if((tmp & 0x1F) != 0x05) 
    {// data block accepted ?
       SD_Disable();
       return(WRITE_BLOCK_ERROR); //Error!
    }
    //Wait till SD/SD-Card is not busy
    while(SPI_RW(0xff) != 0xff);
       
    //set SD_Chip_Select to high (SD/SD-Card Invalid)
    SD_Disable();
    return(0);
} 
 
INT8U SD_Read_Block(INT8U *CMD, INT8U *Buffer, INT16U Bytes) 
{  
    INT16U i; 
    INT8U retry,temp;
    static INT16U Block_Len;
    INT8U CMD_SET_BLOCKLEN[]={CMD16,0x00,0x00,0x00,0x00,0xFF};
    //INT8U CMD_Read_Block[]={CMD17,0x00,0x00,0x00,0x00,0xFF};
     
    if(Bytes != Block_Len)  
    { //Reset Block Length
 
    	CMD_SET_BLOCKLEN[3] = (INT8U)((Bytes & 0x0000FF00) >> 8 );
    	CMD_SET_BLOCKLEN[4] = (INT8U)((Bytes & 0x000000FF) >> 0 );
    
    	retry = 0;	
    	do 
    	{  //Retry 100 times to send command.
    		temp = Write_Command_SD(CMD_SET_BLOCKLEN);
        	if(++retry >= 100)
        		return(READ_BLOCK_ERROR); //block read Error!
    	}
    	while(temp != 0);
    	Block_Len = Bytes;
    }
    //Send reads a block Command CMD to SD/SD-Card
    retry = 0;	
    /*if(CMD == (void *)0)
    	CMD = CMD_Read_Block;*/
    do 
    {  //Retry 100 times to send command.
    	temp = Write_Command_SD(CMD);
        if(++retry >= 100)
        	return(READ_BLOCK_ERROR); //block read Error!
    }
    while(temp != 0);
                         
    //Read Start Byte form SD/SD-Card (FEh/Start Byte)
    while(SPI_RW(0xff) != 0xfe);
         
    //Write blocks(normal 512Bytes) to SD/SD-Card
    for(i = 0; i < Bytes; i++)
    	*Buffer++ = SPI_RW(0xff);
    
    //CRC-Byte
    SPI_RW(0xff);//CRC - Byte 
    SPI_RW(0xff);//CRC - Byte
         
    SD_Disable();
    return(0);
}
 
INT8U SD_read_sector(INT32U Number_Sector,INT8U *Buffer) 
{       
	//Command 17 is reading Blocks from SD/SD-Card
    INT8U CMD_Read_Block[]={CMD17,0x00,0x00,0x00,0x00,0xFF};
     
    INT8U temp;
    
    //Address conversation(logic block address-->byte address)  
    Number_Sector  <<= 9; //addr = addr * 512
    CMD_Read_Block[1] = (INT8U)((Number_Sector & 0xFF000000) >> 24 );
    CMD_Read_Block[2] = (INT8U)((Number_Sector & 0x00FF0000) >> 16 );
    CMD_Read_Block[3] = (INT8U)((Number_Sector & 0x0000FF00) >> 8 );
    
    temp = SD_Read_Block(CMD_Read_Block, Buffer, 512);
    
    return(temp);
}
 
INT8U Read_CID_SD(INT8U *Buffer) 
{
    //Command for reading CID Registers
    INT8U CMD[] = {0x4A,0x00,0x00,0x00,0x00,0xFF}; 
    INT8U temp;
    temp = SD_Read_Block(CMD, Buffer, 16); //read 16 bytes
    return(temp);
}
 
INT8U Read_CSD_SD(INT8U *Buffer) 
{     
    //Command for reading CSD Registers
    INT8U CMD[] = {0x49,0x00,0x00,0x00,0x00,0xFF};
    INT8U temp;
    temp = SD_Read_Block(CMD, Buffer, 16); //read 16 bytes
    return(temp);
}

INT8U SDKardCMD(INT8U Cammand, void *Parameter)
{
	INT8U CMD_Read_Block[]={CMD17,0x00,0x00,0x00,0x00,0xFF};
	Disk_RW_Parameter *pDP;
	
	pDP = (Disk_RW_Parameter *)Parameter;
	
	switch(Cammand)
	{
		case ReadSec:
			SD_read_sector(pDP->SectorIndex,pDP->Buf);
			break;
		case ReadBlock:
			CMD_Read_Block[1] = (INT8U)((pDP->SectorIndex & 0xFF000000) >> 24 );
    		CMD_Read_Block[2] = (INT8U)((pDP->SectorIndex & 0x00FF0000) >> 16 );
    		CMD_Read_Block[3] = (INT8U)((pDP->SectorIndex & 0x0000FF00) >> 8 );
    		CMD_Read_Block[4] = (INT8U)((pDP->SectorIndex & 0x000000FF) >> 0 );
			SD_Read_Block(CMD_Read_Block, pDP->Buf, pDP->Len);
			break;
		case WriteSec:
			SD_write_sector(pDP->SectorIndex, pDP->Buf);
			break;
	}
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -