SDHC card get info from CSD
/**
* @brief Read the CSD card register.
* Reading the contents of the CSD register in SPI mode is a simple
* read-block transaction.
* @param SD_csd: pointer on an CSD register structure
* @retval The SD Response:
* - SD_RESPONSE_FAILURE: Sequence failed
* - SD_RESPONSE_NO_ERROR: Sequence succeed
*/
SD_GetCSDRegister(SD_CSD* SD_csd)
{
ulong i = 0;
rvalue = SD_RESPONSE_FAILURE;
uchar CSD_Tab[16];
/*!< SD chip select low */
SD_CS_LOW();
/*!< Send CMD9 (CSD register) or CMD10(CSD register) */
SD_SendCmd(SD_CMD_SEND_CSD, 0, 0xFF);
/*!< Wait for response in the R1 format (0x00 is no errors) */
if (!SD_GetResponse(SD_RESPONSE_NO_ERROR))
{
if (!SD_GetResponse(SD_START_DATA_SINGLE_BLOCK_READ))
{
for (i = 0; i < 16; i++)
{
/*!< Store CSD register value on CSD_Tab */
CSD_Tab[i] = SD_Read_Sector_Data();
}
}
/*!< Get CRC bytes (not really needed by us, but required by SD) */
Spi_Send_Byte(0xff);
Spi_Send_Byte(0xff);
/*!< Set response value to success */
rvalue = SD_RESPONSE_NO_ERROR;
}
/*!< SD chip select high */
SD_CS_HIGH();
/*!< Send dummy byte: 8 Clock pulses of delay */
Spi_Send_Byte(0xff);
/*!< Byte 0 */
SD_csd->CSDStruct = (CSD_Tab[0] & 0xC0) >> 6;
SD_csd->SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2;
SD_csd->Reserved1 = CSD_Tab[0] & 0x03;
/*!< Byte 1 */
SD_csd->TAAC = CSD_Tab[1];
/*!< Byte 2 */
SD_csd->NSAC = CSD_Tab[2];
/*!< Byte 3 */
SD_csd->MaxBusClkFrec = CSD_Tab[3];
/*!< Byte 4 */
SD_csd->CardComdClasses = CSD_Tab[4] << 4;
/*!< Byte 5 */
SD_csd->CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4;
SD_csd->RdBlockLen = CSD_Tab[5] & 0x0F;
/*!< Byte 6 */
SD_csd->PartBlockRead = (CSD_Tab[6] & 0x80) >> 7;
SD_csd->WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6;
SD_csd->RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5;
SD_csd->DSRImpl = (CSD_Tab[6] & 0x10) >> 4;
SD_csd->Reserved2 = 0; /*!< Reserved */
SD_csd->DeviceSize = (CSD_Tab[6] & 0x03) << 10;
//V1 V1.0
if ((SD_Type == SD_TYPE_V1) || (SD_Type == SD_TYPE_V2))
{
/*!< Byte 7 */
SD_csd->DeviceSize |= (CSD_Tab[7]) << 2;
/*!< Byte 8 */
SD_csd->DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6;
SD_csd->MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3;
SD_csd->MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07);
/*!< Byte 9 */
SD_csd->MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5;
SD_csd->MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2;
SD_csd->DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1;
/*!< Byte 10 */
SD_csd->DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7;
}
//SDHC V2.0
else if (SD_Type == SD_TYPE_V2HC)
{
SD_csd->DeviceSize = (CSD_Tab[7] & 0x3F) << 16;
SD_csd->DeviceSize |= (CSD_Tab[8] << 8);
SD_csd->DeviceSize |= (CSD_Tab[9]);
}
SD_csd->EraseGrSize = (CSD_Tab[10] & 0x40) >> 6;
SD_csd->EraseGrMul = (CSD_Tab[10] & 0x3F) << 1;
/*!< Byte 11 */
SD_csd->EraseGrMul |= (CSD_Tab[11] & 0x80) >> 7;
SD_csd->WrProtectGrSize = (CSD_Tab[11] & 0x7F);
/*!< Byte 12 */
SD_csd->WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7;
SD_csd->ManDeflECC = (CSD_Tab[12] & 0x60) >> 5;
SD_csd->WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2;
SD_csd->MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2;
/*!< Byte 13 */
SD_csd->MaxWrBlockLen |= (CSD_Tab[13] & 0xC0) >> 6;
SD_csd->WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5;
SD_csd->Reserved3 = 0;
SD_csd->ContentProtectAppli = (CSD_Tab[13] & 0x01);
/*!< Byte 14 */
SD_csd->FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7;
SD_csd->CopyFlag = (CSD_Tab[14] & 0x40) >> 6;
SD_csd->PermWrProtect = (CSD_Tab[14] & 0x20) >> 5;
SD_csd->TempWrProtect = (CSD_Tab[14] & 0x10) >> 4;
SD_csd->FileFormat = (CSD_Tab[14] & 0x0C) >> 2;
SD_csd->ECC = (CSD_Tab[14] & 0x03);
/*!< Byte 15 */
SD_csd->CSD_CRC = (CSD_Tab[15] & 0xFE) >> 1;
SD_csd->Reserved4 = 1;
/*!< Return the reponse */
return rvalue;
}
`
/**
* @brief Card Specific Data: CSD Register in "SD.h" file
*/
typedef struct
{
volatile uchar CSDStruct; /*!< CSD structure */
volatile uchar SysSpecVersion; /*!< System specification version */
volatile uchar Reserved1; /*!< Reserved */
volatile uchar TAAC; /*!< Data read access-time 1 */
volatile uchar NSAC; /*!< Data read access-time 2 in CLK cycles */
volatile uchar MaxBusClkFrec; /*!< Max. bus clock frequency */
volatile uint CardComdClasses; /*!< Card command classes */
volatile uchar RdBlockLen; /*!< Max. read data block length */
volatile uchar PartBlockRead; /*!< Partial blocks for read allowed */
volatile uchar WrBlockMisalign; /*!< Write block misalignment */
volatile uchar RdBlockMisalign; /*!< Read block misalignment */
volatile uchar DSRImpl; /*!< DSR implemented */
volatile uchar Reserved2; /*!< Reserved */
volatile ulong DeviceSize; /*!< Device Size */
volatile uchar MaxRdCurrentVDDMin; /*!< Max. read current @ VDD min */
volatile uchar MaxRdCurrentVDDMax; /*!< Max. read current @ VDD max */
volatile uchar MaxWrCurrentVDDMin; /*!< Max. write current @ VDD min */
volatile uchar MaxWrCurrentVDDMax; /*!< Max. write current @ VDD max */
volatile uchar DeviceSizeMul; /*!< Device size multiplier */
volatile uchar EraseGrSize; /*!< Erase group size */
volatile uchar EraseGrMul; /*!< Erase group size multiplier */
volatile uchar WrProtectGrSize; /*!< Write protect group size */
volatile uchar WrProtectGrEnable; /*!< Write protect group enable */
volatile uchar ManDeflECC; /*!< Manufacturer default ECC */
volatile uchar WrSpeedFact; /*!< Write speed factor */
volatile uchar MaxWrBlockLen; /*!< Max. write data block length */
volatile uchar WriteBlockPaPartial; /*!< Partial blocks for write allowed */
volatile uchar Reserved3; /*!< Reserded */
volatile uchar ContentProtectAppli; /*!< Content protection application */
volatile uchar FileFormatGrouop; /*!< File format group */
volatile uchar CopyFlag; /*!< Copy flag (OTP) */
volatile uchar PermWrProtect; /*!< Permanent write protection */
volatile uchar TempWrProtect; /*!< Temporary write protection */
volatile uchar FileFormat; /*!< File Format */
volatile uchar ECC; /*!< ECC code */
volatile uchar CSD_CRC; /*!< CSD CRC */
volatile uchar Reserved4; /*!< always 1*/
} SD_CSD;
key points
key word
volatile :易挥发的、不稳定的 、反复无常的量。 用这个关键词修饰之后就这些值不会随着编译器的编译而改变
编译器有两种编译方式:Debug和release 一个是调试版本,一个是发布版本。调试版本在编译的时候不会做任何修改,以便于发现漏洞,发布版本会做各种优化,以达到最快的运行速度和其他的性能指标。导致某些变量会在不确定的情况下改变,用volatile 修饰过的变量不会改变,每次读取他的时候都是直接访问内存上的值,不会访问在寄存器上的备份值。
简单的辨析volatile和const(常数) 前者修饰的词在编译器(将C语言编译成汇编再变化成机器码) 期间不能变化在运行期间(机器码在CPU中运行的时候) 也不能变化。 被后者修饰的词只作用在编译器期间告诉编译器这是一个常量,在机器码时,const不存在,没有作用。
struct
结构体
将不同的数据类型的数据组成一个结构体。
有三种形式:
只有结构体定义
struct stuff{ uchar job[20]; uint sex; ulong age; };
有结构体变量
struct stuff{ uchar job[20]; uint sex; ulong age; }stf;
这种结构相当于
struct stuff{ uchar job[20]; uint sex; ulong age; }; struct stuff stf;//现在这一句定义的是这个结构体的变量名是 *stf* 这一句单独存在表的是,这句如果单独使用表示的意思是这个结构体只有一个成员就是stf。
去掉结构体名称的方式更简洁
struct {uchar job[20]; uint sex; ulong age; }stf;
结构体的引用
两种方式:
- 通过“.”引用 赋值
struct { uchar job[20]; uint sex; ulong age; }stf;
stf.job[0]='M';
stf.age = 27;
- 通过“->” 引用赋值
stf->job[0]='M'