当前位置: 首页 新闻资讯 技术问答

GD32F303RC的SD卡程序

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

/**
 * GD32F303RC SD卡驱动测试程序
 */

#include "gd32f30x.h"
#include "sd_card_driver.h"
#include <stdio.h>

/* 测试数据缓冲区 */
#define TEST_BLOCK_SIZE 512
uint8_t writeBuffer[TEST_BLOCK_SIZE];
uint8_t readBuffer[TEST_BLOCK_SIZE];

/* 串口初始化 */
void UART_Init(void)
{
    /* 使能GPIO和USART时钟 */
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_USART0);
    
    /* 配置USART0 Tx (PA9)为复用推挽输出 */
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
    
    /* 配置USART0 Rx (PA10)为浮空输入 */
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
    
    /* USART配置 */
    usart_deinit(USART0);
    usart_baudrate_set(USART0, 115200);
    usart_word_length_set(USART0, USART_WL_8BIT);
    usart_stop_bit_set(USART0, USART_STB_1BIT);
    usart_parity_config(USART0, USART_PM_NONE);
    usart_hardware_flow_rts_config(USART0, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART0, USART_CTS_DISABLE);
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    usart_enable(USART0);
}

/* 重定向printf函数到USART0 */
int fputc(int ch, FILE *f)
{
    usart_data_transmit(USART0, (uint8_t)ch);
    while(RESET == usart_flag_get(USART0, USART_FLAG_TBE));
    return ch;
}

int main(void)
{
    SD_Status status;
    SD_CardInfo cardInfo;
    
    /* 系统时钟配置 */
    SystemInit();
    
    /* 初始化串口 */
    UART_Init();
    
    printf("GD32F303RC SD卡测试程序 ");
    
    /* 初始化SDIO接口 */
    SDIO_Init();
    
    /* 初始化SD卡 */
    printf("正在初始化SD卡... ");
    status = SD_CardInit();
    if(status == SD_OK) {
        printf("SD卡初始化成功! ");
        
        /* 获取卡信息 */
        status = SD_GetCardInfo();
        if(status == SD_OK) {
            SD_GetInfo(&cardInfo);
            printf("卡类型: %s ", cardInfo.type == 1 ? "SDSC" : "SDHC/SDXC");
            printf("卡容量: %lu MB ", cardInfo.capacity);
            printf("块大小: %lu 字节 ", cardInfo.block_size);
            
            /* 测试读写操作 */
            printf("准备测试读写操作... ");
            
            /* 填充测试数据 */
            for(int i = 0; i < TEST_BLOCK_SIZE; i++) {
                writeBuffer[i] = (uint8_t)i;
            }
            
            /* 写入测试块 */
            printf("写入测试块... ");
            status = SD_WriteBlock(0, writeBuffer);
            if(status == SD_OK) {
                printf("写入成功! ");
                
                /* 读取测试块 */
                printf("读取测试块... ");
                status = SD_ReadBlock(0, readBuffer);
                if(status == SD_OK) {
                    printf("读取成功! ");
                    
                    /* 验证数据 */
                    for(int i = 0; i < TEST_BLOCK_SIZE; i++) {
                        if(readBuffer[i] != writeBuffer[i]) {
                            printf("数据验证失败! 位置: %d, 预期: 0x%02X, 实际: 0x%02X ", 
                                   i, writeBuffer[i], readBuffer[i]);
                            break;
                        }
                    }
                    printf("数据验证成功! ");
                } else {
                    printf("读取失败! 状态: %d ", status);
                }
            } else {
                printf("写入失败! 状态: %d ", status);
            }
        } else {
            printf("获取卡信息失败! 状态: %d ", status);
        }
    } else {
        printf("SD卡初始化失败! 状态: %d ", status);
    }
    
    while(1) {
        /* 主循环 */
    }
}    

/**
 * GD32F303RC SD卡驱动程序 - 基于SDIO接口
 * 支持SD卡初始化、数据读写等功能
 */

#include "gd32f30x.h"
#include "sd_card_driver.h"
#include <string.h>

/* SDIO时钟频率设置 */
#define SDIO_CK_DIV_INIT      0x7F    /* 初始化时频率约400kHz */
#define SDIO_CK_DIV_NORMAL    0x03    /* 正常通信时频率约24MHz */

/* SD卡命令定义 */
#define CMD0        0       /* 复位SD卡 */
#define CMD1        1       /* 初始化SD卡 */
#define ACMD41      41      /* 初始化SDHC卡 */
#define CMD8        8       /* 检查SD卡支持的电压 */
#define CMD16       16      /* 设置块大小 */
#define CMD17       17      /* 读单块 */
#define CMD24       24      /* 写单块 */
#define CMD55       55      /* 发送应用命令前缀 */
#define CMD58       58      /* 读取OCR寄存器 */

/* SD卡响应类型 */
typedef enum {
    RESPONSE_NONE = 0,      /* 无响应 */
    RESPONSE_SHORT = 1,     /* 短响应(48位) */
    RESPONSE_LONG = 2,      /* 长响应(136位) */
} SD_ResponseType;

/* SD卡状态 */
typedef enum {
    SD_OK = 0,              /* 成功 */
    SD_ERROR = 1,           /* 错误 */
    SD_TIMEOUT = 2,         /* 超时 */
    SD_NOT_SUPPORTED = 3,   /* 不支持 */
} SD_Status;

/* SD卡信息结构体 */
typedef struct {
    uint32_t type;          /* 卡类型 */
    uint32_t capacity;      /* 卡容量(MB) */
    uint32_t block_size;    /* 块大小(字节) */
} SD_CardInfo;

/* 全局变量 */
static SD_CardInfo g_sdCardInfo;

/**
 * 初始化SDIO接口
 */
void SDIO_Init(void)
{
    /* 使能SDIO和GPIO时钟 */
    rcu_periph_clock_enable(RCU_SDIO);
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_GPIOD);
    
    /* 配置SDIO引脚 */
    /* PC8: SDIO_D0, PC9: SDIO_D1, PC10: SDIO_D2, PC11: SDIO_D3 */
    /* PC12: SDIO_CK, PD2: SDIO_CMD */
    gpio_init(GPIOC, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, 
              GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12);
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
    
    /* 配置SDIO参数 */
    /* 关闭SDIO */
    SDIO_CTL(SDIO) &= ~SDIO_CTL_SDIOEN;
    
    /* 设置时钟分频 - 初始化时使用低频率(约400kHz) */
    SDIO_CLKCR(SDIO) = (SDIO_CK_DIV_INIT << 8) | 
                      SDIO_CLKCR_WIDBUS_1B | 
                      SDIO_CLKCR_PWRSAV | 
                      SDIO_CLKCR_BYPASS | 
                      SDIO_CLKCR_CLKEN;
    
    /* 使能SDIO */
    SDIO_CTL(SDIO) |= SDIO_CTL_SDIOEN;
}

/**
 * 发送SD卡命令
 * @param cmd 命令号
 * @param arg 命令参数
 * @param response_type 响应类型
 * @return 命令响应
 */
uint32_t SDIO_SendCommand(uint8_t cmd, uint32_t arg, SD_ResponseType response_type)
{
    uint32_t timeout = 0xFFFF;
    
    /* 等待命令线空闲 */
    while((SDIO_STAT(SDIO) & SDIO_STAT_CMDACT) && (timeout-- > 0));
    if(timeout == 0) return SD_TIMEOUT;
    
    /* 清除中断标志 */
    SDIO_ICR(SDIO) = 0x0007FFDF;
    
    /* 设置命令参数 */
    SDIO_ARG(SDIO) = arg;
    
    /* 设置命令寄存器 */
    SDIO_CMD(SDIO) = (cmd & 0x3F) | 
                    ((response_type == RESPONSE_LONG) ? SDIO_CMD_RESPTYP_136BIT : 
                     (response_type == RESPONSE_SHORT) ? SDIO_CMD_RESPTYP_48BIT : 0) |
                    ((response_type != RESPONSE_NONE) ? SDIO_CMD_WAITRESP : 0) |
                    SDIO_CMD_CMDSEND;
    
    /* 等待命令发送完成 */
    timeout = 0xFFFF;
    if(response_type != RESPONSE_NONE) {
        while(!(SDIO_STAT(SDIO) & SDIO_STAT_CMDRDY) && (timeout-- > 0));
        if(timeout == 0) return SD_TIMEOUT;
    }
    
    /* 返回响应 */
    if(response_type == RESPONSE_SHORT) {
        return SDIO_RESP0(SDIO);
    } else if(response_type == RESPONSE_LONG) {
        return SDIO_RESP1(SDIO);
    }
    
    return SD_OK;
}

/**
 * 初始化SD卡
 * @return 操作状态
 */
SD_Status SD_CardInit(void)
{
    uint32_t response;
    uint32_t timeout;
    uint8_t ocr[4];
    
    /* 发送74个时钟周期 */
    for(int i = 0; i < 10; i++) {
        SDIO_SendCommand(0, 0, RESPONSE_NONE);
    }
    
    /* 发送CMD0 - 复位SD卡 */
    response = SDIO_SendCommand(CMD0, 0, RESPONSE_SHORT);
    if(response != 0x01) return SD_ERROR;
    
    /* 发送CMD8 - 检查SD卡支持的电压 */
    response = SDIO_SendCommand(CMD8, 0x1AA, RESPONSE_SHORT);
    if(response == 0x01) {
        /* SDHC卡 */
        g_sdCardInfo.type = 2;  /* SDHC/SDXC */
        
        /* 发送ACMD41 - 初始化SDHC卡 */
        timeout = 0xFFFF;
        do {
            SDIO_SendCommand(CMD55, 0, RESPONSE_SHORT);
            response = SDIO_SendCommand(ACMD41, 0x40000000, RESPONSE_SHORT);
        } while((response & 0x01) && (timeout-- > 0));
        
        if(timeout == 0) return SD_TIMEOUT;
        
        /* 发送CMD58 - 读取OCR寄存器 */
        response = SDIO_SendCommand(CMD58, 0, RESPONSE_SHORT);
        ocr[0] = (response >> 24) & 0xFF;
        ocr[1] = (response >> 16) & 0xFF;
        ocr[2] = (response >> 8) & 0xFF;
        ocr[3] = response & 0xFF;
        
        /* 设置块大小为512字节 */
        response = SDIO_SendCommand(CMD16, 512, RESPONSE_SHORT);
        if(response != 0x00) return SD_ERROR;
        
        g_sdCardInfo.block_size = 512;
    } else {
        /* SDSC卡或MMC卡 */
        g_sdCardInfo.type = 1;  /* SDSC */
        
        /* 发送CMD1 - 初始化SDSC卡 */
        timeout = 0xFFFF;
        do {
            response = SDIO_SendCommand(CMD1, 0, RESPONSE_SHORT);
        } while((response & 0x01) && (timeout-- > 0));
        
        if(timeout == 0) return SD_TIMEOUT;
        
        /* 设置块大小为512字节 */
        response = SDIO_SendCommand(CMD16, 512, RESPONSE_SHORT);
        if(response != 0x00) return SD_ERROR;
        
        g_sdCardInfo.block_size = 512;
    }
    
    /* 提高通信频率 */
    SDIO_CLKCR(SDIO) = (SDIO_CK_DIV_NORMAL << 8) | 
                      SDIO_CLKCR_WIDBUS_1B | 
                      SDIO_CLKCR_PWRSAV | 
                      SDIO_CLKCR_BYPASS | 
                      SDIO_CLKCR_CLKEN;
    
    return SD_OK;
}

/**
 * 读取SD卡容量信息
 * @return 操作状态
 */
SD_Status SD_GetCardInfo(void)
{
    uint32_t response;
    uint8_t cid[16];
    uint8_t csd[16];
    uint32_t capacity;
    
    /* 发送CMD2 - 获取CID */
    response = SDIO_SendCommand(CMD2, 0, RESPONSE_LONG);
    if(response != 0x00) return SD_ERROR;
    
    /* 读取CID */
    for(int i = 0; i < 4; i++) {
        cid[i*4] = (SDIO_RESP1(SDIO) >> 24) & 0xFF;
        cid[i*4+1] = (SDIO_RESP1(SDIO) >> 16) & 0xFF;
        cid[i*4+2] = (SDIO_RESP1(SDIO) >> 8) & 0xFF;
        cid[i*4+3] = SDIO_RESP1(SDIO) & 0xFF;
    }
    
    /* 发送CMD3 - 获取RCA */
    response = SDIO_SendCommand(CMD3, 0, RESPONSE_SHORT);
    if(response == 0x00) return SD_ERROR;
    
    /* 发送CMD9 - 获取CSD */
    response = SDIO_SendCommand(CMD9, (response & 0xFFFF0000), RESPONSE_LONG);
    if(response != 0x00) return SD_ERROR;
    
    /* 读取CSD */
    for(int i = 0; i < 4; i++) {
        csd[i*4] = (SDIO_RESP1(SDIO) >> 24) & 0xFF;
        csd[i*4+1] = (SDIO_RESP1(SDIO) >> 16) & 0xFF;
        csd[i*4+2] = (SDIO_RESP1(SDIO) >> 8) & 0xFF;
        csd[i*4+3] = SDIO_RESP1(SDIO) & 0xFF;
    }
    
    /* 计算容量 */
    if(g_sdCardInfo.type == 2) {  /* SDHC/SDXC */
        uint32_t c_size = ((csd[7] & 0x3F) << 16) | (csd[8] << 8) | csd[9];
        capacity = (c_size + 1) * 512 / 1024 / 1024;  /* MB */
    } else {  /* SDSC */
        uint8_t csd_ver = (csd[0] >> 6) & 0x03;
        uint32_t c_size;
        
        if(csd_ver == 0) {  /* CSD version 1.0 */
            uint32_t c_size_mult = ((csd[10] & 0x03) << 1) | ((csd[11] >> 7) & 0x01);
            uint32_t read_bl_len = csd[5] & 0x0F;
            c_size = ((csd[6] & 0x03) << 10) | (csd[7] << 2) | ((csd[8] >> 6) & 0x03);
            capacity = (c_size + 1) * (1 << (c_size_mult + 2)) * (1 << read_bl_len) / 1024 / 1024;  /* MB */
        } else {  /* CSD version 2.0 */
            c_size = ((csd[7] & 0x3F) << 16) | (csd[8] << 8) | csd[9];
            capacity = (c_size + 1) * 512 / 1024 / 1024;  /* MB */
        }
    }
    
    g_sdCardInfo.capacity = capacity;
    return SD_OK;
}

/**
 * 读取单个数据块
 * @param block_addr 块地址
 * @param buffer 数据缓冲区
 * @return 操作状态
 */
SD_Status SD_ReadBlock(uint32_t block_addr, uint8_t *buffer)
{
    uint32_t timeout;
    
    /* 如果是SDSC卡,需要转换为字节地址 */
    if(g_sdCardInfo.type == 1) {
        block_addr *= g_sdCardInfo.block_size;
    }
    
    /* 发送CMD17 - 读取单块 */
    if(SDIO_SendCommand(CMD17, block_addr, RESPONSE_SHORT) != 0x00) {
        return SD_ERROR;
    }
    
    /* 等待数据准备好 */
    timeout = 0xFFFF;
    while(!(SDIO_STAT(SDIO) & SDIO_STAT_DBCKEND) && (timeout-- > 0));
    if(timeout == 0) return SD_TIMEOUT;
    
    /* 读取数据 */
    for(int i = 0; i < g_sdCardInfo.block_size; i += 4) {
        uint32_t data = SDIO_FIFO(SDIO);
        buffer[i] = (data >> 24) & 0xFF;
        buffer[i+1] = (data >> 16) & 0xFF;
        buffer[i+2] = (data >> 8) & 0xFF;
        buffer[i+3] = data & 0xFF;
    }
    
    return SD_OK;
}

/**
 * 写入单个数据块
 * @param block_addr 块地址
 * @param buffer 数据缓冲区
 * @return 操作状态
 */
SD_Status SD_WriteBlock(uint32_t block_addr, uint8_t *buffer)
{
    uint32_t timeout;
    
    /* 如果是SDSC卡,需要转换为字节地址 */
    if(g_sdCardInfo.type == 1) {
        block_addr *= g_sdCardInfo.block_size;
    }
    
    /* 配置数据传输 */
    SDIO_DCTRL(SDIO) = 0;
    SDIO_DLEN(SDIO) = g_sdCardInfo.block_size;
    SDIO_DCTRL(SDIO) = SDIO_DCTRL_DBLOCKSIZE_512B | 
                     SDIO_DCTRL_DTEN | 
                     SDIO_DCTRL_DTDIR_TX;
    
    /* 发送CMD24 - 写入单块 */
    if(SDIO_SendCommand(CMD24, block_addr, RESPONSE_SHORT) != 0x00) {
        return SD_ERROR;
    }
    
    /* 写入数据 */
    for(int i = 0; i < g_sdCardInfo.block_size; i += 4) {
        uint32_t data = (buffer[i] << 24) | (buffer[i+1] << 16) | (buffer[i+2] << 8) | buffer[i+3];
        SDIO_FIFO(SDIO) = data;
    }
    
    /* 等待数据传输完成 */
    timeout = 0xFFFF;
    while(!(SDIO_STAT(SDIO) & SDIO_STAT_DBCKEND) && (timeout-- > 0));
    if(timeout == 0) return SD_TIMEOUT;
    
    /* 等待卡就绪 */
    timeout = 0xFFFFFF;
    while(!(SDIO_STAT(SDIO) & SDIO_STAT_RTO) && (timeout-- > 0));
    
    return SD_OK;
}

/**
 * 获取SD卡信息
 * @param card_info 卡信息结构体指针
 */
void SD_GetInfo(SD_CardInfo *card_info)
{
    memcpy(card_info, &g_sdCardInfo, sizeof(SD_CardInfo));
}    

/**
 * GD32F303RC SD卡驱动头文件
 */

#ifndef __SD_CARD_DRIVER_H__
#define __SD_CARD_DRIVER_H__

#include "gd32f30x.h"

/* SD卡状态 */
typedef enum {
    SD_OK = 0,              /* 成功 */
    SD_ERROR = 1,           /* 错误 */
    SD_TIMEOUT = 2,         /* 超时 */
    SD_NOT_SUPPORTED = 3,   /* 不支持 */
} SD_Status;

/* SD卡信息结构体 */
typedef struct {
    uint32_t type;          /* 卡类型 */
    uint32_t capacity;      /* 卡容量(MB) */
    uint32_t block_size;    /* 块大小(字节) */
} SD_CardInfo;

/* 函数声明 */
void SDIO_Init(void);
SD_Status SD_CardInit(void);
SD_Status SD_GetCardInfo(void);
SD_Status SD_ReadBlock(uint32_t block_addr, uint8_t *buffer);
SD_Status SD_WriteBlock(uint32_t block_addr, uint8_t *buffer);
void SD_GetInfo(SD_CardInfo *card_info);

#endif /* __SD_CARD_DRIVER_H__ */    

热门标签:SD NAND FLASH 贴片式TF卡 贴片式SD卡 SD FLASH NAND FLASH


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

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

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

电话:176-6539-0767

Q Q:135-0379-986

邮箱:1350379986@qq.com

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

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