各位老师/大佬好,我在使用Nation开发板N32G45XCL-STB的硬件SPI驱动SDXC卡时遇到了非常棘手的几个问题:
上电后第一次读某个扇区成功,可以读到数据。
但是后续再读其它扇区,返回的数据依然是第一次的内容(像是重复读取缓存数值)。
CMD24 返回 R1=0x00
SD卡发送 Start Token 0xFE
发送完 512 字节数据 + 2 字节 CRC (0xFF,0xFF)后 Data Response 一直是 0xFF (按规范应该是 0x05),且之后卡也没有进入 Busy。如果马上再读这个扇区,会读到写入过的数据,但断电后数据全部丢失,推测数据只是写到缓存。
恳请有经验的大佬们提供一些排查思路或方向。非常感谢!附本人写的SPI和SD代码如下:*附件:SD.c.txt.pdf*附件:SD.h.txt.pdf*附件:SPI.c.txt.pdf*附件:SPI.h.txt.pdf
针对N32G45XCL-STB开发板在SPI模式下初始化部分SDXC卡失败及读写异常的问题,结合SD卡规范和调试经验,提出以下解决方案:
// 上电后发送至少74个时钟周期(建议100-150个)
SD_CS_HIGH(); // 确保CS拉高
for (int i = 0; i < 150; i++) {
SPI_ReadWrite(0xFF);
} uint8_t retry = 0;
do {
SD_CS_LOW();
response = SD_SendCmd(CMD0, 0, 0x95); // CRC=0x95
SPI_ReadWrite(0xFF); // 额外时钟
SD_CS_HIGH();
delay_ms(10); // 每次重试后延时10ms
retry++;
} while (response != 0x01 && retry < 20); // 最多重试20次 response = SD_SendCmd(CMD8, 0x1AA, 0x87); // 参数=0x1AA, CRC=0x87
if (response == 0x01) {
// 读取R7响应(4字节)
uint32_t ocr = SPI_ReadWrite(0xFF) << 24;
ocr |= SPI_ReadWrite(0xFF) << 16;
ocr |= SPI_ReadWrite(0xFF) << 8;
ocr |= SPI_ReadWrite(0xFF);
if ((ocr & 0xFFF) != 0x1AA) { // 检查低12位是否为0x1AA
// 电压不匹配,需处理错误
}
} uint32_t start_time = get_tick();
do {
SD_SendCmd(CMD55, 0, 0x65); // 必须先发CMD55
response = SD_SendCmd(ACMD41, 0x40000000, 0x77); // HCS=1
delay_ms(5); // 每次循环延时5ms
} while (response != 0x00 && (get_tick() - start_time) < 2000); // 超时2s // 在CMD17后读取数据块
if (SD_ReadBlock(buffer, sector) == SUCCESS) {
// 读取完成后额外发送8个时钟
for (int i = 0; i < 8; i++) {
SPI_ReadWrite(0xFF);
}
} void SD_ResetSPI() {
SD_CS_HIGH();
for (int i = 0; i < 10; i++) SPI_ReadWrite(0xFF); // 发送10个空字节
}
// 每次读写前调用
SD_ResetSPI(); uint8_t SD_WriteBlock(uint8_t *buffer, uint32_t sector) {
SD_SendCmd(CMD24, sector, 0xFF); // CMD24
// ... 发送数据令牌0xFE + 512字节数据 + CRC
while (SPI_ReadWrite(0xFF) == 0x00) {} // 等待非0xFF(卡片忙)
return SUCCESS;
} // 发送数据后立即读取响应
uint8_t resp = SPI_ReadWrite(0xFF);
if ((resp & 0x1F) != 0x05) { // 低5位应为00101
return WRITE_ERROR;
}时序与SPI配置:
电源稳定性:
信号完整性:
错误处理增强:
if (SD_Init() != SUCCESS) {
// 尝试降低SPI速度(如分频512)
SPI_SetSpeed(SPI_SPEED_512);
SD_Init(); // 重试初始化
}sdparm -t(Linux)检查卡参数。SCR寄存器确认总线宽度:SD_SendCmd(ACMD51, 0, 0xFF); // 读取SCR通过以上步骤,可解决多品牌SDXC卡兼容性问题。不同品牌SD卡对时序和复位敏感度存在差异,重点优化复位流程、超时机制和信号稳定性是关键。
举报
更多回帖