📄 blinky1.c
字号:
#define CMD33_R 1
/* 擦除所选择的块 Erase the selected write blocks */
#define CMD38 38
#define CMD38_R 2
/***************************** 锁卡命令 Lock Card commands ***************************/
/* 设置/复位密码或上锁/解锁卡 Set/reset the password or lock/unlock the card */
#define CMD42 42
#define CMD42_R 2
/* Commands from 42 to 54, not defined here */
/***************************** 应用命令 Application-specific commands ****************/
/* 禁止下一个命令为应用命令 Flag that the next command is application-specific */
#define CMD55 55
#define CMD55_R 1
/* 应用命令的通用I/O General purpose I/O for application-specific commands */
#define CMD56 56
#define CMD56_R 1
/* 读OCR寄存器 Read the OCR (SPI mode only) */
#define CMD58 58
#define CMD58_R 4
/* 使能或禁止 CRC Turn CRC on or off */
#define CMD59 59
#define CMD59_R 1
/***************************** 应用命令 Application-specific commands ***************/
/* 获取 SD Status寄存器 Get the SD card's status */
#define ACMD13 13
#define ACMD13_R 3
/* 得到已写入卡中的块的个数 Get the number of written write blocks (Minus errors ) */
#define ACMD22 22
#define ACMD22_R 1
/* 在写之前,设置预先擦除的块的个数 Set the number of write blocks to be pre-erased before writing */
#define ACMD23 23
#define ACMD23_R 1
/* 读取OCR寄存器 Get the card's OCR (SD mode) */
#define ACMD41 41
#define ACMD41_R 1
/* 连接/断开CD/DATA[3]引脚上的上拉电阻 Connect or disconnect the 50kOhm internal pull-up on CD/DAT[3] */
#define ACMD42 42
#define ACMD42_R 1
/* 读取SCR寄存器 Get the SD configuration register */
#define ACMD51 51
#define ACMD51_R 1
//簇定义
#define MSDOSFSROOT 0
#define CLUST_FREE 0
#define MSDOSFSFREE CLUST_FREE
#define CLUST_RSRVD 0xfffffff6 // 系统保留簇
#define CLUST_BAD 0xfffffff7 // 坏簇
#define CLUST_EOFS 0xfffffff8 // 第一个结束簇
#define CLUST_EOFE 0xffffffff // 最后一个结束簇
#define FAT12_MASK 0x00000fff // FAT12掩码
#define FAT16_MASK 0x0000ffff // FAT16掩码
#define FAT32_MASK 0x0fffffff // FAT32掩码
// 分区类型
#define PART_TYPE_UNKNOWN 0x00
#define PART_TYPE_FAT12 0x01
#define PART_TYPE_XENIX 0x02
#define PART_TYPE_DOSFAT16 0x04
#define PART_TYPE_EXTDOS 0x05
#define PART_TYPE_FAT16 0x06
#define PART_TYPE_NTFS 0x07
#define PART_TYPE_FAT32 0x0B
#define PART_TYPE_FAT32LBA 0x0C
#define PART_TYPE_FAT16LBA 0x0E
#define PART_TYPE_EXTDOSLBA 0x0F
#define PART_TYPE_ONTRACK 0x33
#define PART_TYPE_NOVELL 0x40
#define PART_TYPE_PCIX 0x4B
#define PART_TYPE_PHOENIXSAVE 0xA0
#define PART_TYPE_CPM 0xDB
#define PART_TYPE_DBFS 0xE0
#define PART_TYPE_BBT 0xFF
#define ATTR_NORMAL 0x00 // 读写
#define ATTR_READONLY 0x01 // 只读
#define ATTR_HIDDEN 0x02 // 隐藏
#define ATTR_SYSTEM 0x04 // 系统文件
#define ATTR_VOLUME 0x08 // 卷标文件
#define ATTR_LONG_FILENAME 0x0f // 长文件名文件
#define ATTR_DIRECTORY 0x10 // 子目录文件
#define ATTR_ARCHIVE 0x20 // 归档文件
#define SPI1_INIT() PINSEL1 &= ~((0x03 << 2) + (0x03 << 4) + (0x03 << 6)); \
PINSEL1 |= (0x01 << 2) + (0x01 << 4) + (0x01 << 6);
//power p0.09
//#define SD_POWER 0
//#define SD_POWER_GPIO() 0
//#define SD_POWER_OUT() 0
//#define SD_POWER_OFF() 0
//#define SD_POWER_ON() 0
//cs p0.21
#define SPI1_CS (0x01 << 21)
#define SPI1_CS_GPIO() PINSEL1 &= ~(0x03 << 10)
#define SPI1_CS_OUT() IO0DIR |= SPI1_CS
#define SPI1_CS_SET() IO0SET |= SPI1_CS
#define SPI1_CS_CLR() IO0CLR |= SPI1_CS
//sck p0.17
#define SPI1_SCK (0x01 << 17)
#define SPI1_SCK_GPIO() PINSEL1 &= ~(0x03 << 2)
#define SPI1_SCK_OUT() IO0DIR |= SPI1_SCK
#define SPI1_SCK_SET() IO0SET |= SPI1_SCK
#define SPI1_SCK_CLR() IO0CLR |= SPI1_SCK
//miso p0.18
#define SPI1_MISO (0x01 << 18)
#define SPI1_MISO_GPIO() PINSEL1 &= ~(0x03 << 4)
#define SPI1_MISO_OUT() IO0DIR &=~(SPI1_MISO)
#define SPI1_MISO_SET() IO0SET |= SPI1_MISO
#define SPI1_MISO_CLR() IO0CLR |= SPI1_MISO
//mosi p0.19
#define SPI1_MOSI (0x01 << 19)
#define SPI1_MOSI_GPIO() PINSEL1 &= ~(0x03 << 6)
#define SPI1_MOSI_OUT() IO0DIR |= SPI1_MOSI
#define SPI1_MOSI_SET() IO0SET |= SPI1_MOSI
#define SPI1_MOSI_CLR() IO0CLR |= SPI1_MOSI
//INT8U IsMusicFile();
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 deName[8];
INT8U deExtension[3];
INT32U Clust; //当前目录的簇号
INT16U Nums; //仅FAT12—FAT16中的根目录区有效
INT32U Index; //当前的BLOCK中目录项索引
INT32U FileSize; //文件长度
////////////////////////////////////////////////////////////////////////////////
//文件信息
////////////////////////////////////////////////////////////////////////////////
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;
////////////////////////////////////////////////////////////////////////////////
INT8U BUFFER[512];
INT8U MP3_BUFFER[512];
INT8U TEXT[512];
#define MP3_TYPE 0
#define WMA_TYPE 1
#define MID_TYPE 2
#define LRC_TYPE 3
INT8U filetype[][3] ={ {"MP3"},{"WMA"},{"MID"},{"LRC"}};
INT32U FAT_MASK;
INT16U RootDirEnts; // 根目录总的项数(FAT12&FAT16)
void UART0_SendByte(uint8 data);
void UART0_SendStr(uint8 const *str);
/**************************************************************************************************
**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();
}
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)
{
//OS_ENTER_CRITICAL();
SSPDR = byte;
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; SD卡使能
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);
}
/*******************************************************************************************************************
** 函数名称: INT8U SD_WriteBlockData() Name: INT8U SD_WriteBlockData()
** 功能描述: 向sd卡写数据块 Function: write block data to sd card
** 输 入: INT8U bmulti : 是否为多块操作1:是0:否 Input: INT8U bmulti : multi blocks operate 1:Y 0:N
INT32U len : 长度 INT32U len : length
INT8U *sendbuf: 发送缓冲区 INT8U *sendbuf : the buffer of send
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
********************************************************************************************************************/
INT8U SD_WriteBlock(INT32U len, INT8U *sendbuf)
{
INT16U i;
INT8U tmp;
SPI1_CS_CLR();
SPI1_SrByte(0xFF); /* 开始发送数据之前发送8个clock clock out 8 clk before start */
SPI1_SrByte(SD_TOK_WRITE_STARTBLOCK); /* 写单块开始令牌 start token of write single block */
for (i = 0; i < len; i++)
SPI1_SrByte(sendbuf[i]); /* 发送数据 send data */
SPI1_SrByte((i >> 8) & 0xFF);
SPI1_SrByte(i & 0xFF); /* 发送CRC16校验码 send CRC16 check code */
tmp = SPI1_SrByte(0xff);
if ((tmp & SD_RESP_DATA_MSK) != SD_RESP_DATA_ACCETPTED)
{
SPI1_SrByte(0xFF); /* 返回之前发送8个clock clock out 8 clk before return */
//SPI_CS_Deassert();
//return SD_ERR_DATA_RESP; /* 数据响应错误 data response error */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -