当前位置: 首页 新闻资讯 行业新闻

SDNAND容量SDSC跟SDHC的区别有哪些

SD NAND-贴片式TF卡-贴片式SD卡-免费测试2023-06-06660

SDNAND芯片是一种基于NAND闪存的存储设备,用于嵌入式系统和工业应用中。SDNAND芯片规格分为SDSC(Secure Digital Standard Capacity)和SDHC(Secure Digital High Capacity)两种类型,它们之间的主要区别在于容量和文件系统支持,具体如下:

  1. 容量:SDSC芯片通常包括2GB或更小容量的芯片,而SDHC芯片可以容纳4GB~32GB的数据。

  2. 文件系统支持:SDSC芯片使用FAT16文件系统,而SDHC芯片支持FAT32文件系统,可处理单个文件尺寸高达4GB之内的数据。

  3. 命令参数:SDSC和SDHC之间存在差异的命令参数,主要体现在读命令和写命令的形式上,例如,SDHC芯片中,读命令的命令码为0x13,而SDSC芯片中为0x11。同样的,SDHC芯片的写命令为0x18,而SDSC芯片为0x10。

  4. 设置块长度:SDHC芯片允许块长度设置为512字节,1024字节或2048字节,而SDSC芯片则只支持512字节的块长度设置。

  5. 写保护组:SDHC芯片中的写保护组数目更多,允许设置更多不同的写保护组参数,而SDSC芯片则没有这个功能。

  6. 读写速度:SDHC芯片具有更高的读写速度,能够达到更高的数据吞吐量。但在相同速度等级下,SDSC和SDHC的写入速度和读取速度大致相同。

  7. 工作电压需求:SDHC芯片的工作电压范围为2.7V~3.6V,而SDSC芯片的工作电压范围为2.0V~3.6V。

  8. 速度:在相同速度等级下,SDHC芯片一般写入速度比SDSC芯片快,读取速度则差不多。

  9. 局部访问和位移访问:SDSC和SDHC芯片都支持局部访问和位移访问的方式,但是在不同的芯片规格中,局部访问和位移访问的指令格式可能会有所不同。

  10. 容量限制:SDSC是SD卡标准中容量较小的一种,最大容量为2GB。而SDHC是高速SD卡标准,最大容量为32GB。当然,根据不断进步的技术,现在还有更高容量的SDXC(扩展容量)标准,最高容量为2TB。

  11. 命令参数:SDSC和SDHC在命令参数方面也有所不同。在SDSC中,命令参数是固定的,而SDHC允许更多的命令参数选项。例如,SDHC支持在SD命令中使用位移访问,而SDSC不支持。

  12. 局部访问和位移访问:局部访问和位移访问是SD卡的两种不同访问方式。局部访问是指在读取或写入数据时,只能按块进行,而位移访问是可以按字节或位进行读取或写入。SDHC支持位移访问,可以更好地满足需求。

  13. 设置块长度:设置块长度是在SD卡的读/写操作中,指定每个块的长度。SDHC允许从512字节到2048字节的块长度。而SDSC只支持标准块长度512字节。

  14. 写保护组:写保护组是当SD卡被设置为只读时使用的参数。在SDHC中,写保护组可以是任何512字节的数据块。而SDSC仅支持第0扇区作为保护组。

  15. 读和写:无论是SDSC还是SDHC,它们使用的读和写操作都是相同的。区别仅在于它们支持的命令参数和块长度。

  16. 综上所述,SDNAND芯片容量SDSC和SDHC之间最大的区别在于容量限制和命令参数。SDHC支持更多的命令参数选项和位移访问,允许更大的块长度,并允许任何512字节的数据块作为写保护组。因此,如果需要更高的容量和更高级别的命令参数,建议选择SDHC芯片。

下面将分别介绍MCU驱动SDSC和SDHC的代码编写方法,并提供详细的代码示例。

    方法一

  1. MCU驱动SDSC代码示例

以下是基于SPI接口驱动SDSC的MCU代码示例:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #define SDSC_SPI_CS                 P10 #define SDSC_SPI_SCK                P11 #define SDSC_SPI_MISO               P12 #define SDSC_SPI_MOSI               P13 #define SDSC_CMD_GO_IDLE_STATE     0x40 #define SDSC_CMD_SEND_OP_COND      0x41     #define SDSC_CMD_SEND_IF_COND      0x48 #define SDSC_CMD_SEND_CSD          0x49 #define SDSC_CMD_SEND_CID          0x4A #define SDSC_CMD_STOP_TRANSMISSION 0x4C #define SDSC_CMD_SEND_STATUS       0x4D #define SDSC_CMD_READ_BLOCK        0x51 #define SDSC_CMD_READ_MULTIPLE     0x52 #define SDSC_CMD_WRITE_BLOCK       0x58 #define SDSC_CMD_WRITE_MULTIPLE    0x59   #define SDSC_CMD_APP_CMD           0x77 #define SDSC_CMD_READ_OCR          0x7A #define SDSC_R1_IDLE_STATE         0x01 #define SDSC_R1_ILLEGAL_COMMAND    0x04 #define SDSC_R1_CRC_ERROR          0x08 #define SDSC_R1_ERASE_SEQ_ERROR    0x10 #define SDSC_R1_ADDRESS_ERROR      0x20 #define SDSC_R1_PARAMETER_ERROR    0x40 static uint32_t sdsc_data_offset = 0; static void spi_bus_init(void) {    // 用于初始化SPI总线 } static void sdsc_send_cmd(uint8_t cmd_byte, uint32_t arg) {    // 用于向SDSC发送命令 } static uint8_t sdsc_read_byte(void) {    // 用于从SDSC读取一个字节的数据 } static void sdsc_write_byte(uint8_t data_byte) {    // 用于向SDSC写入一个字节的数据 } static uint8_t sdsc_read_r1_response(void) {    // 用于读取SDSC的R1响应字节 } static uint8_t sdsc_wait_for_r1_response(void) {    uint8_t r1_response;    uint16_t timer;    timer = 500;    while ((r1_response = sdsc_read_r1_response()) == 0xff && --timer > 0);    return r1_response; } static void sdsc_go_idle_state(void) {    sdsc_send_cmd(SDSC_CMD_GO_IDLE_STATE, 0);    sdsc_wait_for_r1_response(); } static uint8_t sdsc_send_op_cond(void) {    sdsc_send_cmd(SDSC_CMD_SEND_OP_COND, 0x40000000);    return sdsc_wait_for_r1_response(); } static uint8_t sdsc_read_cid(uint8_t* cid) {    sdsc_send_cmd(SDSC_CMD_SEND_CID, 0);    return sdsc_wait_for_r1_response(); } static uint8_t sdsc_read_csd(uint8_t* csd) {    sdsc_send_cmd(SDSC_CMD_SEND_CSD, 0);    return sdsc_wait_for_r1_response(); } static uint8_t sdsc_set_blocklength(uint32_t block_length) {    sdsc_send_cmd(0x10, block_length);    return sdsc_wait_for_r1_response(); } static uint8_t sdsc_read_block(uint32_t block_address, uint8_t* buffer, uint32_t buffer_length) {    uint8_t cmd = (buffer_length > 512) ? SDSC_CMD_READ_MULTIPLE : SDSC_CMD_READ_BLOCK;    sdsc_send_cmd(cmd, block_address << 9);    if (sdsc_wait_for_r1_response() != SDSC_R1_IDLE_STATE)        return 1;    while (sdsc_read_byte() != 0xfe);    spi_bus_read(buffer, buffer_length);    sdsc_read_byte();    sdsc_read_byte();    return 0; } static uint8_t sdsc_write_block(uint32_t block_address, const uint8_t* buffer, uint32_t buffer_length) {    uint8_t cmd = (buffer_length > 512) ? SDSC_CMD_WRITE_MULTIPLE : SDSC_CMD_WRITE_BLOCK;    sdsc_send_cmd(cmd, block_address << 9);    if (sdsc_wait_for_r1_response() != SDSC_R1_IDLE_STATE)        return 1;    sdsc_write_byte(0xfe);    spi_bus_write(buffer, buffer_length);    sdsc_write_byte(0xff);    sdsc_write_byte(0xff);    if (sdsc_read_r1_response() != 0x00)        return 1;    return 0; } static uint8_t sdsc_initialize_card(void) {    uint8_t i, response, ocr[4], cid[16], csd[16];    spi_bus_init();    spi_bus_set_frequency(100000);    for (i = 0; i < 10; i++)        sdsc_write_byte(0xff);    sdsc_go_idle_state();    for (i = 0; i < 10; i++)        sdsc_write_byte(0xff);    response = sdsc_send_op_cond();    if (response != SDSC_R1_IDLE_STATE)        return 1;    sdsc_read_cid(cid);    sdsc_read_csd(csd);    sdsc_set_blocklength(512);    return 0; } static uint8_t sdsc_read_sector(uint32_t sector, uint8_t* buffer) {    uint32_t block_address = sector * 512;    return sdsc_read_block(block_address, buffer, 512); } static uint8_t sdsc_write_sector(uint32_t sector, const uint8_t* buffer) {    uint32_t block_address = sector * 512;    return sdsc_write_block(block_address, buffer, 512); }

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h>#define SDSC_SPI_CS                 P10#define SDSC_SPI_SCK                P11#define SDSC_SPI_MISO               P12#define SDSC_SPI_MOSI               P13#define SDSC_CMD_GO_IDLE_STATE     0x40#define SDSC_CMD_SEND_OP_COND      0x41    #define SDSC_CMD_SEND_IF_COND      0x48#define SDSC_CMD_SEND_CSD          0x49#define SDSC_CMD_SEND_CID          0x4A#define SDSC_CMD_STOP_TRANSMISSION 0x4C#define SDSC_CMD_SEND_STATUS       0x4D#define SDSC_CMD_READ_BLOCK        0x51#define SDSC_CMD_READ_MULTIPLE     0x52#define SDSC_CMD_WRITE_BLOCK       0x58#define SDSC_CMD_WRITE_MULTIPLE    0x59   #define SDSC_CMD_APP_CMD           0x77#define SDSC_CMD_READ_OCR          0x7A#define SDSC_R1_IDLE_STATE         0x01#define SDSC_R1_ILLEGAL_COMMAND    0x04#define SDSC_R1_CRC_ERROR          0x08#define SDSC_R1_ERASE_SEQ_ERROR    0x10#define SDSC_R1_ADDRESS_ERROR      0x20#define SDSC_R1_PARAMETER_ERROR    0x40static uint32_t sdsc_data_offset = 0;static void spi_bus_init(void){
    // 用于初始化SPI总线}static void sdsc_send_cmd(uint8_t cmd_byte, uint32_t arg){
    // 用于向SDSC发送命令}static uint8_t sdsc_read_byte(void){
    // 用于从SDSC读取一个字节的数据}static void sdsc_write_byte(uint8_t data_byte){
    // 用于向SDSC写入一个字节的数据}static uint8_t sdsc_read_r1_response(void){
    // 用于读取SDSC的R1响应字节}static uint8_t sdsc_wait_for_r1_response(void){
    uint8_t r1_response;
    uint16_t timer;

    timer = 500;
    while ((r1_response = sdsc_read_r1_response()) == 0xff && --timer > 0);

    return r1_response;}static void sdsc_go_idle_state(void){
    sdsc_send_cmd(SDSC_CMD_GO_IDLE_STATE, 0);
    sdsc_wait_for_r1_response();}static uint8_t sdsc_send_op_cond(void){
    sdsc_send_cmd(SDSC_CMD_SEND_OP_COND, 0x40000000);
    return sdsc_wait_for_r1_response();}static uint8_t sdsc_read_cid(uint8_t* cid){
    sdsc_send_cmd(SDSC_CMD_SEND_CID, 0);
    return sdsc_wait_for_r1_response();}static uint8_t sdsc_read_csd(uint8_t* csd){
    sdsc_send_cmd(SDSC_CMD_SEND_CSD, 0);
    return sdsc_wait_for_r1_response();}static uint8_t sdsc_set_blocklength(uint32_t block_length){
    sdsc_send_cmd(0x10, block_length);
    return sdsc_wait_for_r1_response();}static uint8_t sdsc_read_block(uint32_t block_address, uint8_t* buffer, uint32_t buffer_length){
    uint8_t cmd = (buffer_length > 512) ? SDSC_CMD_READ_MULTIPLE : SDSC_CMD_READ_BLOCK;

    sdsc_send_cmd(cmd, block_address << 9);
    if (sdsc_wait_for_r1_response() != SDSC_R1_IDLE_STATE)
        return 1;

    while (sdsc_read_byte() != 0xfe);

    spi_bus_read(buffer, buffer_length);

    sdsc_read_byte();
    sdsc_read_byte();

    return 0;}static uint8_t sdsc_write_block(uint32_t block_address, const uint8_t* buffer, uint32_t buffer_length){
    uint8_t cmd = (buffer_length > 512) ? SDSC_CMD_WRITE_MULTIPLE : SDSC_CMD_WRITE_BLOCK;

    sdsc_send_cmd(cmd, block_address << 9);
    if (sdsc_wait_for_r1_response() != SDSC_R1_IDLE_STATE)
        return 1;

    sdsc_write_byte(0xfe);
    spi_bus_write(buffer, buffer_length);
    sdsc_write_byte(0xff);
    sdsc_write_byte(0xff);

    if (sdsc_read_r1_response() != 0x00)
        return 1;

    return 0;}static uint8_t sdsc_initialize_card(void){
    uint8_t i, response, ocr[4], cid[16], csd[16];

    spi_bus_init();
    spi_bus_set_frequency(100000);

    for (i = 0; i < 10; i++)
        sdsc_write_byte(0xff);

    sdsc_go_idle_state();

    for (i = 0; i < 10; i++)
        sdsc_write_byte(0xff);

    response = sdsc_send_op_cond();
    if (response != SDSC_R1_IDLE_STATE)
        return 1;

    sdsc_read_cid(cid);
    sdsc_read_csd(csd);

    sdsc_set_blocklength(512);

    return 0;}static uint8_t sdsc_read_sector(uint32_t sector, uint8_t* buffer){
    uint32_t block_address = sector * 512;
    return sdsc_read_block(block_address, buffer, 512);}static uint8_t sdsc_write_sector(uint32_t sector, const uint8_t* buffer){
    uint32_t block_address = sector * 512;
    return sdsc_write_block(block_address, buffer, 512);}

这只是一个简单的示例代码,具体操作需要根据具体的系列和型号进行相应的修改。

  1. MCU驱动SDHC代码示例

以下是基于SDIO接口驱动SDHC的MCU代码示例:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdint.h>#define SDHC_SDIO_CMD_REGISTER      0x03#define SDHC_SDIO_CRC

方法二

驱动SDSC(SD Standard Capacity)和SDHC(SD High Capacity)的代码实现方式略有不同,下面将分别介绍。

  1. MCU驱动SDSC的代码示例

需要一个MCU内核、时钟、GPIO、SPI接口和SDSC芯片选通信号。以下是具体实现步骤的代码示例:

头文件定义:

/* Include Required Libraries */
#include <stdint.h>
#include <stdbool.h>
#include "stm32f10x.h"
#include "delay.h"

/* SDSC Chip Slave Select (SS) GPIO Pin */
#define SDSC_CS_PORT	GPIOC
#define SDSC_CS_PIN	GPIO_Pin_4

/* SDSC CMD0 - GO_IDLE_STATE */
#define SDSC_GO_IDLE_STATE	0x00

/* SDSC CMD8 - SEND_IF_COND */
#define SDSC_SEND_IF_COND	0x08

/* SDSC CMD55 - APP_CMD */
#define SDSC_APP_CMD		0x37

/* SDSC ACMD41 - SEND_OP_COND */
#define SDSC_SEND_OP_COND	0x29

/* SDSC Response Constants */
#define SDSC_RESPONSE_NO_ERROR		0x01
#define SDSC_RESPONSE_IDLE_STATE	0x01
#define SDSC_RESPONSE_CRC_ERROR		0x02
#define SDSC_RESPONSE_WRITE_ERROR	0x04
#define SDSC_RESPONSE_READ_ERROR	0x08

初始化SDSC接口的函数:

void sdsc_init_interface(void) {
    /* Port Clock Enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    /* Set the Control Lines */
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.GPIO_Pin = SDSC_CS_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(SDSC_CS_PORT, &GPIO_InitStruct);

    /* Set the Card to Disabled */
    GPIO_SetBits(SDSC_CS_PORT, SDSC_CS_PIN);

    /* Set SD Card to default state */
    sdsc_reset();

    /* Wait for Card Initialization */
    delay_ms(100);
}

发送命令到SDSC的函数:

uint8_t sdsc_send_command(uint8_t cmd, uint32_t arg, uint8_t crc) {
    /* Send the Preceding Commands */
    if(cmd == SDSC_CMD_GO_IDLE_STATE) {
        /* Send Command 0 with the CRC7=0x95 */
        sdsc_send_byte(SDSC_CMD_GO_IDLE_STATE, SDSC_RESPONSE_NO_ERROR);
        sdsc_send_byte(0x00, SDSC_RESPONSE_NO_ERROR);
        sdsc_send_byte(0x00, SDSC_RESPONSE_NO_ERROR);
        sdsc_send_byte(0x00, SDSC_RESPONSE_NO_ERROR);
        sdsc_send_byte(0x95, SDSC_RESPONSE_NO_ERROR);
    } else {
        /* Preliminary - Send CMD55 to Initialize the SDSC */
        if(sdsc_send_command(SDSC_CMD_APP_CMD, 0x00, 1) != SDSC_RESPONSE_NO_ERROR) {
            return 0xFF;
        }

        /* Send Command */
        sdsc_send_byte(cmd | 0x40, SDSC_RESPONSE_NO_ERROR);
        sdsc_send_byte((uint8_t)(arg >> 24), SDSC_RESPONSE_NO_ERROR);
        sdsc_send_byte((uint8_t)(arg >> 16), SDSC_RESPONSE_NO_ERROR);
        sdsc_send_byte((uint8_t)(arg >> 8), SDSC_RESPONSE_NO_ERROR);
        sdsc_send_byte((uint8_t)(arg), SDSC_RESPONSE_NO_ERROR);
        sdsc_send_byte(crc, SDSC_RESPONSE_NO_ERROR);

        /* Perform End of Read Operation */
        if(cmd == SDSC_CMD_APP_CMD) {
            sdsc_send_byte(0x00, SDSC_RESPONSE_NO_ERROR);
        }
    }

  /* Return Success */
  return SDSC_RESPONSE_NO_ERROR;
}

发送数据和接收数据的函数:

void sdsc_send_bytes(const uint8_t *data, uint16_t size) {
    /* Loop through all the bytes */
    while(size--) {
        sdsc_send_byte(*data++, SDSC_RESPONSE_NO_ERROR);
    }
}

void sdsc_receive_bytes(uint8_t *data, uint16_t size) {
    /* Loop through all the bytes */
    while(size--) {
        *data++ = sdsc_receive_byte();
    }
}
  1. MCU驱动SDHC的代码示例

需要一个MCU内核、时钟、GPIO、SPI接口和SDHC芯片选通信号。以下是具体实现步骤的代码示例:

头文件定义:

/* Include Required Libraries */
#include <stdint.h>
#include <stdbool.h>
#include "stm32f10x.h"
#include "delay.h"

/* SDHC Chip Slave Select (SS) GPIO Pin */
#define SDHC_CS_PORT	GPIOC
#define SDHC_CS_PIN		GPIO_Pin_4

/* SDHC CMD0 - GO_IDLE_STATE */
#define SDHC_GO_IDLE_STATE	0x00

/* SDHC CMD8 - SEND_IF_COND */
#define SDHC_SEND_IF_COND	0x08

/* SDHC CMD55 - APP_CMD */
#define SDHC_APP_CMD		0x37

/* SDHC ACMD41 - SEND_OP_COND */
#define SDHC_SEND_OP_COND	0x29

/* SDHC CMD9 - SEND_CSD */
#define SDHC_SEND_CSD		0x09

/* SDHC CMD10 - SEND_CID */
#define SDHC_SEND_CID		0x0A

/* SDHC CMD17 - READ_SINGLE_BLOCK */
#define SDHC_READ_SINGLE_BLOCK	0x11

/* SDHC Response Constants */
#define SDHC_RESPONSE_NO_ERROR		0x01
#define SDHC_RESPONSE_IDLE_STATE	0x01
#define SDHC_RESPONSE_CRC_ERROR		0x02
#define SDHC_RESPONSE_WRITE_ERROR	0x04
#define SDHC_RESPONSE_READ_ERROR	0x08

/* SDHC Wait Constants */
#define SDHC_WAIT_TIMEOUT			0xFFFF /* Timeout in cycles (microseconds) */
#define SDHC_WAIT_READ_DATA_TOKEN	0xFE /* Token used for Read Data */
#define SDHC_WAIT_WRITE_DATA_TOKEN	0xFD /* Token used for Write Data */

/* SDHC Error Checking Constants */
#define SDHC_ERROR_CHECK_MASK		0x0F /* Mask for Error Checking (Older Versions of SDHC) */
#define SDHC_ERROR_ERASE_RESET		0x20 /* Error Code - Reset ID Data on Success */ 
#define SDHC_ERROR_CARD_LOCKED		0x10 /* Error Code - Card Locked */

初始化SDHC接口的函数:

void sdhc_init_interface(void) {
    /* Port Clock Enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

    /* Set the Control Lines */
    GPIO_InitTypeDef GPIO_InitStruct;

    GPIO_InitStruct.GPIO_Pin = SDHC_CS_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_Init(SDHC_CS_PORT, &GPIO_InitStruct);

    /* Set the Card to Disabled */
    GPIO_SetBits(SDHC_CS_PORT, SDHC_CS_PIN);

    /* Set SD Card to default state */
    sdhc_reset();

    /* Wait for Card Initialization

热门标签:SDNAND贴片式TF卡贴片式SD卡SLC NANDSD FLASHNAND FLASH


SD NAND-贴片式TF卡-贴片式SD卡-免费测试

深圳市芯存者科技有限公司

售前咨询
售前咨询
售后服务
售后服务
联系我们

电话:176-6539-0767

Q Q:135-0379-986

邮箱:1350379986@qq.com

地址:深圳市南山区蛇口街道后海大道1021号B C座C422W8

在线客服 在线客服 QQ客服 微信客服 淘宝店铺 联系我们 返回顶部