一、硬件连接与配置
引脚映射
nRF52832的SPI接口与SD卡引脚对应关系(以SPI0为例):
SD卡引脚 nRF52832引脚 功能说明 CS P0.17 片选信号(主动低电平) SCK P0.19 时钟信号 MOSI P0.20 主设备输出/从设备输入 MISO P0.21 主设备输入/从设备输出 SPI模式配置
SD卡SPI模式需设置为CPOL=1、CPHA=1(模式3),对应nRF52832的SPI模式配置:
nrf_drv_spi_config_tspi_config=NRF_DRV_SPI_DEFAULT_CONFIG;spi_config.mode=NRF_DRV_SPI_MODE_3;// CPOL=1, CPHA=1spi_config.frequency=NRF_DRV_SPI_FREQ_1M;// 初始频率1MHz
二、SPI驱动初始化
SPI外设初始化
使用
nrf_drv_spi_init函数初始化SPI模块:ret_code_terr_code;constnrf_drv_spi_tspi_instance=NRF_DRV_SPI_INSTANCE(0);// SPI0实例err_code=nrf_drv_spi_init(&spi_instance,&spi_config,spi_event_handler,NULL);APP_ERROR_CHECK(err_code);SPI传输函数
实现SPI数据收发函数(需处理片选信号):
voidspi_transfer(uint8_t*tx_buf,uint8_t*rx_buf,uint16_tlen){spi_xfer_done=false;APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi_instance,tx_buf,len,rx_buf,len));while(!spi_xfer_done);// 等待传输完成}
三、SD卡初始化流程
复位SD卡(CMD0)
发送复位命令并等待响应:
#defineCMD00x40// 复位命令uint8_tcmd0[]={CMD0,0x95,0x00};// 命令+参数+CRCspi_transfer(cmd0,NULL,3);// 发送命令spi_transfer(NULL,response,1);// 读取响应检查电压兼容性(CMD8)
验证SD卡支持的工作电压:
#defineCMD80x48// 电压检查命令uint8_tcmd8[]={CMD8,0x1AA,0x87};// 参数为0x1AA,CRC=0x87spi_transfer(cmd8,response,5);// 响应包含4字节数据+CRC激活SD卡(ACMD41)
发送初始化命令直至成功:
#defineACMD410x60// 初始化命令uint8_tacmd41[]={0x60,0x00,0xE5};// HCS=1(高容量卡支持)do{spi_transfer(acmd41,response,4);nrf_delay_ms(10);// 延时等待初始化完成}while(response[0]!=0x01);
四、文件系统实现
FATFS移植
关键函数实现:需实现
disk_read和disk_write接口:DSTATUSdisk_read(BYTE*buff,LBA_t sector,UINT count){for(UINT i=0;i<count;i++){spi_transfer(sector+i,buff+i*512,512);// 按扇区读取}returnRES_OK;}SPI读写优化:使用DMA传输提升效率(需配置SPIM)。
文件操作示例
FATFS fs;FIL file;FRESULT res;res=f_mount(&fs,"",1);// 挂载文件系统if(res==FR_OK){res=f_open(&file,"test.txt",FA_WRITE|FA_CREATE_ALWAYS);if(res==FR_OK){f_puts("Hello SD Card!",&file);f_close(&file);}}
五、性能优化与调试
SPI时钟优化
初始阶段使用1MHz,初始化完成后提升至20MHz(需SD卡支持):
spi_config.frequency=NRF_DRV_SPI_FREQ_20M;nrf_drv_spi_uninit(&spi_instance);nrf_drv_spi_init(&spi_instance,&spi_config,NULL,NULL);
错误处理机制
添加超时检测与重试逻辑:
#defineSPI_TIMEOUT_MS100uint32_tstart=nrf_delay_us_get();while(!spi_xfer_done&&(nrf_delay_us_get()-start<SPI_TIMEOUT_MS*1000));if(!spi_xfer_done){// 处理超时错误}
调试工具
- 使用逻辑分析仪捕获SPI波形,验证命令时序是否符合SD卡规范。
参考代码 使用nrf52832,通过文件系统操作sd卡www.youwenfan.com/contentcsq/70337.html
六、常见问题解决
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| SD卡无响应(CMD0失败) | 片选信号未正确拉低 | 检查CS引脚连接与驱动配置 |
| 读取数据错误(CRC校验失败) | SPI时钟频率过高 | 降低SPI频率至1MHz以下 |
| 文件系统挂载失败 | FAT表损坏或未格式化 | 使用PC工具格式化SD卡为FAT32 |
七、扩展功能
多块写入优化
使用
CMD24(单块写入)和CMD25(多块写入)提升传输效率:#defineCMD240x58// 写入单块uint8_tcmd24[]={CMD24,0x00,0x00,0x00,0x00,0x95};// 参数+CRCspi_transfer(cmd24,NULL,6);// 发送写入命令SD卡容量检测
通过
CMD9读取CSD寄存器解析容量:#defineCMD90x49// 读取CSD寄存器uint8_tcmd9[]={CMD9,0x00,0x00,0x00,0x00,0x77};// CRC=0x77spi_transfer(cmd9,csd_data,16);// 读取16字节CSD数据