📄 sdcard.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 + -