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

📄 sdcard.c

📁 ARM7 lpc2132+vs1003+sdcard 制作的 MP3 此程序在ADS1.2环境下编译
💻 C
字号:
/****************************************Copyright (c)***********************************************
**                              		qsw
**                                      
**                                
**--------------File Info----------------------------------------------------------------------------
** File name:			sdhal.c
** Last modified Date:	2007.11.20
** Last Version:		V1.0
** Descriptions:		sd 卡驱动软件包: 硬件抽象层 ---- SPI1操作函数
**						Soft Packet of SD Card Driver: hard abstrast layer ---- function of SPI1 operation
**
**------------------------------------------------------------------------------------------------
** Created by:			qsw
** Created date:		2007.11.20
** Version:				V1.0
** Descriptions:		The original version
**
**------------------------------------------------------------------------------------------------
** Modified by:			
** Modified date:		
** Version:				
** Descriptions:		
**
**------------------------------------------------------------------------------------------------
** Modified by: 
** Modified date:
** Version:	
** Descriptions: 
**
**************************************************************************************************/
#include "main.h"


uint32  NextCluster;   		 	//指向当前正在读取文件的簇号
uint32  SectorIndex=0;   		//正在读扇区

uint8   reading;

////////////////////////////////////////////////////////////////////////////////
//磁盘分区信息
////////////////////////////////////////////////////////////////////////////////
INT8U	Partition_Active;				// 0x80代表该分区为缺省分区
INT8U	Partition_StartHead;			// 该分区入口的磁头地址
INT16U	Partition_StartCylSect;			// 该分区入口的扇区地址和柱面地址
INT8U	Partition_PartType;				// 该分区类型
INT8U	Partition_EndHead;				// 该分区结束的扇区地址
INT16U	Partition_EndCylSect;			// 该分区结束的柱面地址
INT32U	Partition_StartLBA;				// 该分区内第一个扇区地址
INT32U	Partition_Size;					// 该分区所包含的扇区总数

////////////////////////////////////////////////////////////////////////////////
//fat32 BPB结构,包括扩展BPB
////////////////////////////////////////////////////////////////////////////////
INT8U	BS_jmpBoot[3];					//jmp code
INT8U	BS_OEMName[8];					//oem and os like dos5.0

INT16U	BPB_BytesPerSec; 				//扇区字节数
INT8U	BPB_SecPerClus;					//每簇扇区数
INT16U	BPB_RsvdSecCnt; 				//保留扇区数
INT8U	BPB_NumFATs;					//FAT数目
INT16U	BPB_RootEntCnt; 				//根目录项数 0
INT16U	BPB_TotSec16; 					//小扇区总数 0
INT8U	BPB_Media;						//媒体描述符
INT16U	BPB_FATSz16; 					//每FAT扇区数fat32不用为0
INT16U	BPB_SecPerTrk; 					//每道扇区数
INT16U	BPB_NumHeads; 					//磁头数
INT32U	BPB_HiddSec; 					//隐藏扇区数
INT32U	BPB_TotSec32; 					//总扇区数   
INT32U	BPB_FATSz32;					//每FAT扇区数fat32
INT16U	BPB_ExtFlags;					//fat32扩展标志
INT16U  BPB_FSVer;						//fat32特有,高位为fat32的主版本号,底位为次版本号
INT32U	BPB_RootClus;					//根目录簇号
INT16U	BPB_FSInfo;						//文件系统信息扇区号
INT16U	BPB_BKBootSec;					//引导扇区备份号
INT8U	BPB_Reserved[12];				//保留空间

INT8U	BS_drvNum;					    //物理驱动器号
INT8U	BS_Reservd1;					//保留
INT8U	BS_BootSig;						//扩展引导标签
INT32U	BS_VolID;						//分区序号
INT8U	BS_VolLab[11];					//卷标
INT8U	BS_FilSysType[8];				//系统ID
////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
//文件信息
////////////////////////////////////////////////////////////////////////////////
INT8U	DIR_Name[11];					//文件名,没有.
INT8U	DIR_Attr;         				//文件属性,自低至高,只读、隐藏、系统、卷标、子目录、归档
INT8U	DIR_NTRes;        				//系统保留
INT8U	DIR_CrtTimeTenth;  				//创建时间的10毫秒位
INT16U	DIR_CrtTime;      				//创建时间
INT16U	DIR_CrtDate;      				//创建日期
INT16U	DIR_LastAccDate;  				//最后访问日期
INT16U	DIR_FstClusHI;    				//文件起始簇号高16位               
INT16U	DIR_WrtTime;      				//最近修改时间
INT16U	DIR_WrtDate;      				//最近修改日期
INT16U	DIR_FstClusLO;    				//文件起始簇号的低16位               
INT32U	DIR_FileSize;     				//文件长度
////////////////////////////////////////////////////////////////////////////////

INT32U  FAT1Sec;						//FAT1表的位置
INT32U  FAT2Sec;
INT32U  FirstDataSector;				//第一个根目录位置,区号为2
INT32U  FirstDirSector;
////////////////////////////////////////////////////////////////////////////////


uint32 address = 0x1049;
INT8U MP3_BUFFER[512];

extern uint8 DataFlag;

/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
void SD_Delay_Nmicrosecond(uint32 n)
{
	uint32 b;
	for (b = 1; b<n; b++);
}
/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
void SD_Power(void)
{
	SPI1_SCK_GPIO();	
	SPI1_SCK_OUT();
	SPI1_SCK_CLR();		
	
	SPI1_MOSI_GPIO();		
	SPI1_MOSI_OUT();
	SPI1_MOSI_CLR();		
	
    SPI1_CS_GPIO();	 		
	SPI1_CS_OUT();
	SPI1_CS_CLR();
}
/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
void SPI1_Init(INT8U speed)
{  
	SPI1_CS_GPIO();		
	SPI1_CS_OUT();
					
	PINSEL1 &= ~((0x03 << 2) + (0x03 << 4) + (0x03 << 6)); 
	PINSEL1 |=  (0x02 << 2) + (0x02 << 4) + (0x02 << 6);
	
	SSPCR0 = (0x00 << 8) |              			// SCR=0  
            (0x00 << 7) |             				// CPHA =0时钟输出相位,仅SPI模式有效 
            (0x00 << 6) |              				// CPOL =0时钟输出极性,仅SPI模式有效
            (0x00 << 4) |              				// FRF =00 帧格式 00=SPI,01=SSI,10=Microwire,11=保留
            (0x07 << 0);               				// DSS  数据长度,0000-0010=保留,0011=4位,0111=8位,1111=16位

    SSPCR1 = (0x00 << 3) |              			// SOD  从机输出禁能,1=禁止,0=允许
            (0x00 << 2) |              				// MS   主从选择,0=主机,1=从机
            (0x01 << 1) |              				// SSE  SSP使能,1=允许SSP与其它设备通信
            (0x00 << 0);               				// LBM  回写模式
             
    SSPCPSR	= speed; 								//2-254 偶数	
  	SSPIMSC	= 0x00;								    // 取消所有中断使能		
    SSPICR	= 0x00;                     			// 中断清除寄存器
}								
/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
INT8U SPI1_SrByte(INT8U byte)
{
	SSPDR = byte;

	OS_ENTER_CRITICAL();

	while( (SSPSR & 0x01) == 0 );	    			// 等待TFE置位,即发送FIFO空  										

	OS_EXIT_CRITICAL();

	return(SSPDR);
}
/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
INT8U SD_ChkCard(void)
{
	//if (SD_INSERT_STATUS() != 0)
	//	return 0;									/* 未完全插入 not insert entirely */
	//else
		return 1;									/* 完全插入 insert entirely */
}
/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
INT8U SD_WriteCom(uint8 cmd,uint32 arg)
{
	uint8 tmp;
   	uint8 retry=0;
	
  	SPI1_CS_CLR();      							//SD卡使能

   	SPI1_SrByte((INT8U)(cmd|0x40));   				//送头命令
   	SPI1_SrByte((INT8U)(arg>>24));
   	SPI1_SrByte((INT8U)(arg>>16));     				//send 6 Byte Command to MMC/SD-Card
   	SPI1_SrByte((INT8U)(arg>>8));
   	SPI1_SrByte((INT8U)(arg));
	SPI1_SrByte((INT8U)(0x95));       				//仅仅对RESET有效的CRC效验码

	do
   	{ 
    	tmp = SPI1_SrByte(0XFF); 					//Only last 8 bit is used here.Read it out.
      	retry++;
   	}
   	while((tmp==0xff)&&(retry<100));    			//当没有收到有效的命令的时候

	if(retry>=100)
	{
		return 0;
	}
	
	if(reading == 0)
    {
      	SPI1_CS_SET();          	  				//MMC_CS_PIN=1;
    }
    else 
    {
    	SPI1_CS_CLR();                 		    	// MMC_CS_PIN = 0;   
    }
	return(tmp);
}
/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
INT8U SD_ReadBlock(INT32U address,INT8U *SD_BUFFER)
{
	INT32U	addr;
	INT16U  i=0;
	INT8U   temp=0;
   	
	addr=address<<9;
	
	reading=1;
	
   	SPI1_CS_CLR();    			  				//MMC_CS_PIN=0;
   	
	temp=SD_WriteCom(CMD17,addr);     			//读出RESPONSE

	while( (SPI1_SrByte(0XFF)!= 0xFE)&&(i<400))
	{
		i++;
	}; 											//直到读取到了数据的开始头0XFE,才拿继续

   	for(i=0; i<512; i++)
	{
		*SD_BUFFER++=SPI1_SrByte(0XFF);
	}
	
   	SPI1_SrByte(0XFF);							//CRC - Byte
   	SPI1_SrByte(0XFF);							//CRC - Byte

	reading=0;

	SPI1_CS_SET(); 

	return(temp);
}
/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
INT8U SD_Init(void)
{
	uint8 retry;
   	uint8 temp;
   	uint8 i;
	
	SPI1_Init(4);
	
	SD_Delay_Nmicrosecond(0xffffff);

	SPI1_SrByte(0XFF);	

	SPI1_CS_CLR();      					//SD卡使能
   	
   	for (i=0;i<16;i++)
   	{
    	SPI1_SrByte(0XFF);					//send 74 clock at least!!!
   	}
	
   	retry=0;
   	do
   	{ 
    	temp=SD_WriteCom(CMD0,0);			//Send Command CMD0 to MMC/SD Card
     	retry++;
     	if(retry>=200)
     	{
      		return(0);
     	}
   	}
   	while(temp!=0x01);
	
   	retry=0;
   	do
   	{ 
   		temp=SD_WriteCom(CMD1,0);			//Send Command CMD1 to MMC/SD-Card
     	retry++;
    	if(retry>=200)
     	{
     		return(0);
     	}
   	}
   	while(temp!=0);

	retry=0;
	
	SPI1_SrByte(0XFF);
	
    SD_WriteCom(16,512);     				//设置一次读写BLOCK的长度为512个字节
    
   	SPI1_CS_SET();      					//MMC_CS_PIN=1;  //set MMC_Chip_Select to high

	SPI1_Init(2);
	
	return(1); 								//All commands have been taken.
}
/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
INT8U Fat_Init(void)
{   
	INT8U BUFFER[512];

	SD_Init();

	SD_ReadBlock(0,BUFFER);																	//read partion message																// 读MBR结构//struct bpb710 *bpb;
																							// 读取分区表信息// 读引导扇区// 引导扇区号在PartInfo.prStartLBA中
    Partition_PartType= BUFFER[450];														//分区信息 FAT32 0x0B				
	Partition_Size	= BUFFER[458]+(BUFFER[459]<<8)+(BUFFER[460]<<16)+(BUFFER[461]<<24);
    Partition_StartLBA = BUFFER[454]+(BUFFER[455]<<8)+(BUFFER[456]<<16)+(BUFFER[457]<<24);	//0xF9*512=127488		

	SD_ReadBlock(Partition_StartLBA,BUFFER);     				//FAT32 read BPB

	BS_OEMName[0]   = BUFFER[3];
	BS_OEMName[1]   = BUFFER[4];
	BS_OEMName[2]   = BUFFER[5];
	BS_OEMName[3]   = BUFFER[6];
	BS_OEMName[4]   = BUFFER[7];
	BS_OEMName[5]   = BUFFER[8];
	BS_OEMName[6]   = BUFFER[9];
	BS_OEMName[7]   = BUFFER[10];
	BPB_BytesPerSec	= BUFFER[11] |(BUFFER[12] << 8);			//0x0200			//每个扇区字节数
	BPB_SecPerClus	= BUFFER[13];								//0x08      		//每个簇的扇区数
	BPB_RsvdSecCnt  = BUFFER[14] |(BUFFER[15] << 8);			//0x20 				//保留扇区数
	BPB_NumFATs     = BUFFER[16];								//0x02 				//FAT 表数目
	BPB_RootEntCnt	= BUFFER[17] | (BUFFER[18] << 8);
	BPB_TotSec16    = BUFFER[19] | (BUFFER[20] << 8);
	BPB_Media		= BUFFER[21];
	BPB_FATSz16		= BUFFER[22] | (BUFFER[23] << 8); 
    BPB_SecPerTrk	= BUFFER[24] | (BUFFER[25] << 8);
    BPB_NumHeads	= BUFFER[26] | (BUFFER[27] << 8); 
    BPB_HiddSec 	= BUFFER[28] | (BUFFER[29] << 8) | (BUFFER[30] << 16) | (BUFFER[31] << 24);  
    BPB_TotSec32	= BUFFER[32] | (BUFFER[33] << 8) | (BUFFER[34] << 16) | (BUFFER[35] << 24);  
	BPB_FATSz32 	= BUFFER[36] | (BUFFER[37] << 8) | (BUFFER[38] << 16) | (BUFFER[39] << 24);
    BPB_ExtFlags	= BUFFER[40] | (BUFFER[41] << 8);  
    BPB_FSVer	    = BUFFER[42] | (BUFFER[43] << 8);
    BPB_RootClus	= BUFFER[44] | (BUFFER[45] << 8) | (BUFFER[46] << 16) | (BUFFER[47] << 24);
    BPB_FSInfo 	    = BUFFER[48] | (BUFFER[49] << 8); 
    BPB_BKBootSec   = BUFFER[50] | (BUFFER[51] << 8); 						
	//BPB_Reserved    = BUFFER[52]; 

	BS_drvNum		= BUFFER[64];
	BS_Reservd1		= BUFFER[65];
	BS_BootSig		= BUFFER[66];
	BS_VolID		= BUFFER[67] | (BUFFER[68] << 8) | (BUFFER[69] << 16) | (BUFFER[70] << 24);
	//BS_VolLab[0]	= BUFFER[71];
	//BS_FilSysType[0] = BUFFER[82];
	
	FAT1Sec			= BPB_RsvdSecCnt+Partition_StartLBA;
	
	FAT2Sec			= FAT1Sec+BPB_FATSz32;
	
	FirstDataSector	= FAT2Sec+BPB_FATSz32;

	//address = FirstDataSector;
	
	return 1;	
}
/**************************************************************************************************
**Name: 	  
**Function:   
**Input:	  
**Output:	  
**************************************************************************************************/
INT8U Fat_ReadFileData()
{
	if(DataFlag==0x00)
	{
		
		SD_ReadBlock(address, MP3_BUFFER);
	
		address=address+1;
			
		return(1);
	}
	return 0;
}


⌨️ 快捷键说明

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