📄 sd.c
字号:
#include "sd.h"
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 = (0x01 << 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;
while( (SSPSR & 0x01) == 0 ); // 等待TFE置位,即发送FIFO空
return(SSPDR);
}
/**************************************************************************************************
**Name:
**Function:
**Input:
**Output:
**************************************************************************************************/
INT8U SD_WriteCom(uint8 cmd,uint32 arg)
{
uint8 temp=20;
uint8 retry=0;
SPI1_SrByte(0xff);
SPI1_CS_CLR(); //SD卡使能
while(temp--);
SPI1_SrByte((cmd & 0x3f) | 0x40); //送头命令
SPI1_SrByte(arg>>24);
SPI1_SrByte(arg>>16); //send 6 Byte Command to MMC/SD-Card
SPI1_SrByte(arg>>8);
SPI1_SrByte(arg);
SPI1_SrByte(0x95); //仅仅对RESET有效的CRC效验码
SPI1_SrByte(0xff);
while((temp = SPI1_SrByte(0xff)) == 0xff) /* wait response */
if(retry++ > 0xfe) break; /* time out error */
SPI1_CS_SET();
SPI1_SrByte(0xff);
return(temp);
}
/**************************************************************************************************
**Name:
**Function:
**Input:
**Output:
**************************************************************************************************/
INT8U SD_ReadBlock(INT32U sector,INT8U *buffer)
{
INT16U i,retry=0;
INT8U temp=0;
SPI1_Init(2);
temp = SD_WriteCom(17,sector<<9); //读出RESPONSE
if(temp != 0x00)
return temp;
SPI1_CS_CLR();
//等数据的开始 //wait to start recieve data
while(SPI1_SrByte(0xff) != 0xfe)
{
if(retry++ > 0xfffe)
{
SPI1_CS_SET();
return 1;
}
}
for(i=0; i<512; i++)
{
*buffer++ = SPI1_SrByte(0xff);
}
SPI1_SrByte(0xff); //CRC - Byte
SPI1_SrByte(0xff); //CRC - Byte
SPI1_CS_SET();
SPI1_SrByte(0xff);
return 0;
}
/*******************************************************************************************************************
** 函数名称: 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 sector, INT8U *buffer)
{
INT16U i,retry;
INT8U temp;
temp = SD_WriteCom(24, sector<<9); //写命令 //send command
if(temp != 0x00)
return temp;
SPI1_CS_CLR();
SPI1_SrByte(0xff);
SPI1_SrByte(0xff);
SPI1_SrByte(0xff);
SPI1_SrByte(0xfe); //发开始符 //send start byte "token"
for(i=0; i<512; i++) //送512字节数据 //send 512 bytes data
{
SPI1_SrByte(buffer[i]);
}
SPI1_SrByte(0xff); //dummy crc
SPI1_SrByte(0xff);
temp = SPI1_SrByte(0xff);
if( (temp & 0x1f) != 0x05) //等待是否成功 //judge if it successful
{
SPI1_CS_SET();
return temp;
}
//等待操作完 //wait no busy
while(!SPI1_SrByte(0xff))
if(retry++ > 0xfffe)
{
SPI1_CS_SET();
return 1;
}
SPI1_CS_SET();
SPI1_SrByte(0xff);// extra 8 CLK
return 0;
}
/**************************************************************************************************
**Name:
**Function:
**Input:
**Output:
**************************************************************************************************/
INT8U SD_Init(void)
{
uint8 retry=0;
uint8 temp=0;
uint8 i;
SPI1_Init(120);
do
{
for(i=0;i<10;i++) SPI1_SrByte(0xff);
temp = SD_WriteCom(0, 0);//发idle命令 //send idle command
retry++;
if(retry>0xfe) return 1;//超时退出 //time out
} while(temp != 0x01);
retry=0;
do
{
temp = SD_WriteCom(1, 0);//发active命令 //send active command
retry++;
if(retry>0xfe) return 1;//超时退出 //time out
} while(temp);
SPI1_Init(2); /* Use High Speed SPI*/
temp = SD_WriteCom(59, 0);//关crc //disable CRC
temp = SD_WriteCom(16, 512);//设扇区大小512 //set sector size to 512
return 0;//正常返回 //normal return
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -