📄 cjsd.c
字号:
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
** 注 意: startaddr 和 blocknum 建议为sds.erase_uint的整数倍, 因为有的卡只能以sds.erase_uint为单位进行擦除
*********************************************************************************************************************/
#if SD_EraseBlock_EN
unsigned char SD_EraseBlock(unsigned long startaddr, unsigned long blocknum)
{
long tmp;
unsigned char ret;
if ((startaddr + blocknum) > sds.block_num)
return SD_ERR_OVER_CARDRANGE; /* 操作超出卡容量范围 operate over the card range */
if (SD_ChkCardWP() == 1)
return SD_ERR_WRITE_PROTECT; /* 卡有写保护 */
tmp = blocknum - sds.erase_unit;
while(tmp >= 0) /* 每次擦除扇区大小 once erase is sector size */
{
ret = SD_EraseEndBlock(startaddr + sds.erase_unit - 1); /* 选择终止块地址 select end address */
if (ret != SD_NO_ERR)
return ret;
ret = SD_EraseSelectedBlock(); /* 擦除所选的块 erase blocks selected */
if (ret != SD_NO_ERR)
return ret;
startaddr += sds.erase_unit; /* 起始地址递增 */
blocknum -= sds.erase_unit;
tmp = blocknum - sds.erase_unit;
};
if (blocknum > 0) /* 擦除不够擦除扇区大小的块 */
{ /* erase blocks that numbers is not enough a sector */
ret = SD_EraseStartBlock(startaddr);
if (ret != SD_NO_ERR)
return ret;
ret = SD_EraseEndBlock(startaddr + blocknum - 1);
if (ret != SD_NO_ERR)
return ret;
ret = SD_EraseSelectedBlock();
if (ret != SD_NO_ERR)
return ret;
}
return SD_NO_ERR; /* 返回擦除成功 return erase sucessfully */
}
#endif
/*******************************************************************************************************************
** 函数名称: unsigned char SD_GetCardInfo() Name: unsigned char SD_GetCardInfo()
** 功能描述: 获得SD卡的信息 Function: get the information of SD card
** 输 入: unsigned char cardtype: 卡类型 Input: unsigned char cardtype: card type
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*******************************************************************************************************************/
unsigned char SD_GetCardInfo()
{
unsigned long tmp;
unsigned char csdbuf[16],ret;
ret = SD_ReadCSD(16,csdbuf); /* 读CSD寄存器 read CSD register */
if (ret != SD_NO_ERR)
return ret;
SD_CalTimeout(csdbuf); /* 计算超时时间值 calculate timeout value */
/* 计算块的最大长度 */ /* calculate the size of a sector */
sds.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK); /* (2 ^ READ_BL_LEN) */
/* 计算卡中块的个数 */ /* calculate the sector numbers of the SD Card */
sds.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10) +
(csdbuf[C_SIZE_POS2] << 2) +
((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6) + 1; /* (C_SIZE + 1)*/
tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1) +
((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7) + 2; /* (C_SIZE_MULT + 2) */
/* 获得卡中块的数量 */ /* get the block numbers in card */
sds.block_num = sds.block_num * (1 << tmp); /* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
/* 计算扇区大小 */ /*calculate the size of sector */
sds.erase_unit = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +
((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1; /* SD (SECTOR_SIZE + 1) */
return SD_NO_ERR; /* 返回执行成功 return perform sucessfully */
}
/*******************************************************************************************************************
** 函数名称: unsigned char SD_CalTimeout() Name: unsigned char SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间 Function: get the information of SD card
** 输 入: unsigned char cardtype: 卡类型 Input: unsigned char cardtype: card type
unsigned char *csdbuf : CSD寄存器内容 unsigned char *csdbuf : CSD register content
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
*******************************************************************************************************************/
void SD_CalTimeout(unsigned char *csdbuf)
{
unsigned long tmp;
unsigned char time_u,time_v,fator;
sds.timeout_read = READ_TIMEOUT_100MS; /* 默认读超时为100ms */
sds.timeout_write = WRITE_TIMEOUT_250MS; /* 默认写超时为250ms */
sds.timeout_erase = WRITE_TIMEOUT_250MS;
time_u = (csdbuf[TAAC_POS] & TAAC_MSK); /* 读超时时间单位 read timeout unit */
time_v = (csdbuf[TAAC_POS] & NSAC_MSK) >> 3; /* 读超时时间值 read timeout value */
fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2; /* 写超时时间因数 write timeout factor */
if(time_v == 0) return;
if(fator >= 6) return;
tmp = SPI_CLOCK * time_value[time_v] / 10 / time_unit[time_u]; /* TACC * f (单位 unit: clock) */
tmp = tmp + csdbuf[NSAC_POS] * 100; /* TACC * f + NSAC * 100 (单位 unit: clock) */
/* 计算得到的超时值 the timeout value of being calculated */
sds.timeout_read = tmp;
sds.timeout_write = tmp * r2w_fator[fator]; /* (TACC * f + NSAC * 100) * R2WFACTOR (单位 unit:clock)*/
sds.timeout_read = sds.timeout_read * 100 / 8; /* 实际值为计算值的100倍 */
sds.timeout_write = sds.timeout_write * 100 / 8;
if (sds.timeout_read > READ_TIMEOUT_100MS) /* 取计算值与默认值中的最小值 */
sds.timeout_read = READ_TIMEOUT_100MS;
if (sds.timeout_write > WRITE_TIMEOUT_250MS)
sds.timeout_write = WRITE_TIMEOUT_250MS;
sds.timeout_erase = sds.timeout_write;
}
/*******************************************************************************************************************
** 函数名称: unsigned char SD_CalTimeout() Name: unsigned char SD_CalTimeout()
** 功能描述: 计算读/写/擦超时时间 Function: get the information of SD card
** 输 入: unsigned char *cardtype: 卡类型接收缓冲 Input: unsigned char *cardtype: card type receive buff
** 输 出: 0: 正确 >0: 错误码 Output: 0: right >0: error code
** 函数说明: 该命令不断重复发送到SD卡,直到响应R1的Bit0(Idle)位为0,表示SD卡内部初始化处理完成。
当响应的Idle位为0时,SD卡就完全进入SPI模式了。当然重复发送命令CMD1是有次数限制的,
最大次数为宏定义SD_IDLE_WAIT_MAX.
*******************************************************************************************************************/
unsigned char SD_ActiveInit(void)
{
unsigned char param[4] = {0,0,0,0},resp[5],ret;
unsigned long i = 0;
do
{ /* 发出CMD1, 查询卡的状态, send CMD1 to poll card status */
ret = SD_SendCmd(CMD1, param, CMD1_R, resp);
if (ret != SD_NO_ERR)
return ret;
i++;
}while (((resp[0] & MSK_IDLE) == MSK_IDLE) && (i < SD_IDLE_WAIT_MAX));
/* 如果响应R1的最低位Idle位为1,则继续循环 */
if (i >= SD_IDLE_WAIT_MAX)
return SD_ERR_TIMEOUT_WAITIDLE; /* 超时,返回错误 time out,return error */
return SD_NO_ERR;
}
/*******************************************************************************************************************
** 函数名称: unsigned short SD_GetZLGSDVer() Name: unsigned short SD_GetZLGSDVer()
** 功能描述: 得到ZLG/SD的版本号 Function: get the version of ZLG/SD
** 输 入: 无 Input: NULL
** 输 出: 版本号 Output: Version
*******************************************************************************************************************/
unsigned short SD_GetZLGSDVer(void)
{
return 0x0100; /* 版本号为 1.00 */
}
/**************************************************************
读写SD卡的SPI接口函数: SPI接口设置,发送/接收字节函数
**************************************************************/
/*******************************************************************************************************************
** 函数名称: void SD_Power() Name: void SD_Power()
** 功能描述: 对卡先下电,再上电 Function: turn off the card's power, and turn on
** 输 入: 无 Input: NULL
** 输 出: 无 Output: NULL
********************************************************************************************************************/
void SD_Power(void)
{
unsigned long i;
SD_POWER_GPIO();
SD_POWER_OUT();
SD_POWER_OFF(); /* 关闭 SD 卡电源 turn off power of sd card */
SPI_SCK_GPIO();
SPI_SCK_OUT();
SPI_SCK_CLR(); /* SCK 引脚置低 set SCK to zero */
SPI_MISO_GPIO();
SPI_MISO_OUT();
SPI_MISO_CLR(); /* MISO 引脚置低 set MISO to zero */
SPI_MOSI_GPIO();
SPI_MOSI_OUT();
SPI_MOSI_CLR(); /* MOSI 引脚置低 set MOSI to zero */
SPI_CS_GPIO();
SPI_CS_OUT();
SPI_CS_CLR(); /* CS 引脚置低 set CS to zero */
for(i = 0; i < 0x9000; i++); /* 关闭电源延时 delay after turn off power of sd card */
SD_POWER_ON(); /* 打开 SD 卡电源 turn on power of sd card */
}
/*******************************************************************************************************************
** 函数名称: void SD_HardWareInit() Name: void SD_HardWareInit()
** 功能描述: 初始化访问SD卡的硬件条件 Function: initialize the hardware condiction that access sd card
** 输 入: 无 Input: NULL
** 输 出: 无 Output: NULL
********************************************************************************************************************/
void SD_HardWareInit(void)
{
SD_Power(); /* 对卡先下电,再上电 turn off power of card, and turn on it */
SPI_INIT(); /* 初始化SPI接口 initialize SPI interface */
SD_INSERT_GPIO();
SD_INSERT_IN(); /* 检测卡完全插入口为输入口 the port checking card is input */
SD_WP_GPIO();
SD_WP_IN(); /* 写保护检测口为输入口 the port written protect is input */
SPI_CS_SET(); /* CS置高 set CS to high voltage */
SPI_Clk400k(); /* 设置SPI频率小于等于400kHZ set frequency of SPI below 400kHZ */
SPI_SPCR = (0x01 << 4) + (0x01 << 5); /* 设置SPI接口模式,MSTR = 1,CPOL = 1,CPHA = 0,LSBF=0 */
} /* configure SPI interface */
/*******************************************************************************************************************
** 函数名称: void SPI_Clk400k() Name: void SPI_Clk400k()
** 功能描述: 设置SPI的时钟小于400kHZ Function: set the clock of SPI less than 400kHZ
** 输 入: 无 Input: NULL
** 输 出: 无 Output: NULL
********************************************************************************************************************/
void SPI_Clk400k(void)
{
SPI_SPCCR = 128; /* 设置SPI时钟分频值为128 Set the value of dividing frequency to 128 */
}
/*******************************************************************************************************************
** 函数名称: void SPI_ClkToMax() Name: void SPI_ClkToMax()
** 功能描述: 设置SPI的clock到最大值 Function: set the clock of SPI to maximum
** 输 入: 无 Input: NULL
** 输 出: 无 Output: NULL
********************************************************************************************************************/
void SPI_ClkToMax(void)
{
SPI_SPCCR = 8; /* 设置SPI时钟分频值为8 Set the value of dividing frequency to 8 */
}
/*******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -