STM32F411 自定义SPI驱动读取SD卡始终返回0xFF求助
STM32自定义SPI驱动读取SD卡始终返回0xFF排查
问题背景
使用HAL驱动通过SPI读取SD卡功能正常,但速度过慢,因此自行编写裸机SPI驱动。GPIO配置确认无问题,但数据传输环节异常:无论发送什么数据,读取返回值始终为0xFF。已对比数十个STM32裸机SPI实现,未发现代码差异。
自定义SPI驱动代码
void fhSpiInit(u32 pScaler) { fhGpioInitSystemA(); fhGpioPinSetupA(FH_GPIO_PIN_07, FH_GPIO_MODE_ALTERNATE, FH_GPIO_OTYPE_PUSH_PULL, FH_GPIO_SPEED_HIGH, FH_GPIO_PULL_NONE); fhGpioPinSetupA(FH_GPIO_PIN_06, FH_GPIO_MODE_ALTERNATE, FH_GPIO_OTYPE_PUSH_PULL, FH_GPIO_SPEED_HIGH, FH_GPIO_PULL_NONE); fhGpioPinSetupA(FH_GPIO_PIN_05, FH_GPIO_MODE_ALTERNATE, FH_GPIO_OTYPE_PUSH_PULL, FH_GPIO_SPEED_HIGH, FH_GPIO_PULL_NONE); fhGpioPinSetupA(FH_GPIO_PIN_03, FH_GPIO_MODE_OUTPUT, FH_GPIO_OTYPE_PUSH_PULL, FH_GPIO_SPEED_HIGH, FH_GPIO_PULL_NONE); fhGpioAlternateFunctionA(FH_GPIO_PIN_07, 5); fhGpioAlternateFunctionA(FH_GPIO_PIN_06, 5); fhGpioAlternateFunctionA(FH_GPIO_PIN_05, 5); RCC->APB2RSTR &= ~RCC_APB2RSTR_SPI1; RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; SPI1->CR1 = 0; SPI1->CR2 = 0; SPI1->CR1 |= pScaler; SPI1->CR1 |= SPI_CR1_MSTR; SPI1->CR1 |= SPI_CR1_SSM; SPI1->CR1 |= SPI_CR1_SSI; SPI1->CR1 |= SPI_CR1_SPE; fhSpiCsHigh(); } void fhSpiDeinit() { SPI1->CR1 &= ~SPI_CR1_SPE; RCC->APB2ENR &= ~RCC_APB2ENR_SPI1EN; RCC->APB2RSTR |= RCC_APB2RSTR_SPI1RST; } void fhSpiReInit(u32 pScaler) { fhSpiDeinit(); fhSpiInit(pScaler); } u8 fhSpiTransferByte(u8 pToWrite) { SPI1->DR = pToWrite; halt(!(SPI1->SR & SPI_SR_TXE)); halt(!(SPI1->SR & SPI_SR_RXNE)); u8 ret = SPI1->DR; printf("\tSPI1: %02x <=> %02x\n", pToWrite, ret); return ret; } void fhSpiCsLow() { fhGpioPinWriteA(FH_GPIO_PIN_03, 0); } void fhSpiCsHigh() { fhGpioPinWriteA(FH_GPIO_PIN_03, 1); }
ulibSD SPI适配代码
/** \brief Initialize SPI hardware */ void SPI_Init(void) { fhSpiReInit(SPI_BAUDRATEPRESCALER_256); } /** \brief Read/Write a single byte. \param d Byte to send. \return Byte that arrived. */ BYTE SPI_RW(BYTE d) { return fhSpiTransferByte(d); } /** \brief Flush of SPI buffer. */ void SPI_Release(void) { return; } /** \brief Selecting function in SPI terms, associated with SPI module. */ void SPI_CS_Low(void) { fhSpiCsLow(); } /** \brief Deselecting function in SPI terms, associated with SPI module. */ void SPI_CS_High(void) { fhSpiCsHigh(); } /** \brief Setting frequency of SPI's clock to maximun possible. */ void SPI_Freq_High(void) { fhSpiReInit(SPI_BAUDRATEPRESCALER_2); } /** \brief Setting frequency of SPI's clock equal or lower than 400kHz. */ void SPI_Freq_Low(void) { fhSpiReInit(SPI_BAUDRATEPRESCALER_256); } uint32_t gSpiTimerEnd = 0; /** \brief Start a non-blocking timer. \param ms Milliseconds. */ void SPI_Timer_On(WORD ms) { gSpiTimerEnd = gSysTick + ms; } /** \brief Check the status of non-blocking timer. \return Status, TRUE if timeout is not reach yet. */ BOOL SPI_Timer_Status(void) { if (gSpiTimerEnd == -1) { return false; } if (gSysTick >= gSpiTimerEnd) { SPI_Timer_Off(); return false; } return true; } /** \brief Stop of non-blocking timer. Mandatory. */ void SPI_Timer_Off(void) { gSpiTimerEnd = -1; }
接线与电压检测
- 接线方式:
- USB_VCC -> STM_5V
- USB_GND -> STM_GND
- SD_GND -> STM_GND
- SD_VDD -> STM_3V3
- SD_MOSI -> STM_MOSI1
- SD_MISO -> STM_MISO1
- SD_CLK -> STM_CLK1
- SD_CS -> STM_A3
- 电压检测:
- STM32微控制器输入电压:5.06V
- STM板输出到SD卡的电压:3.44V(略高,判断无影响)
输出日志
SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: 40 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 95 <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: 40 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 95 <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: 40 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 95 <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: 40 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 95 <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: 40 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 95 <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: 40 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 00 <=> ff SPI1: 95 <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SPI1: ff <=> ff SD_Init: 1
排查方向
从日志可见,SD卡初始化阶段发送CMD0(0x40开头的指令)后,始终未收到SD卡响应,返回全0xFF,需排查以下点:
- SPI配置是否遗漏数据位宽、CPOL/CPHA模式等SD卡要求的参数
- MISO引脚的硬件连接或GPIO配置是否存在异常(如浮空未拉、引脚复用错误)
- SD卡初始化时序是否符合规范(如CS拉低前的时钟同步、指令发送间隔)
- 自定义SPI传输函数的等待逻辑是否存在时序问题(如RXNE等待是否过早)
内容的提问来源于stack exchange,提问作者zlovro
相关产品推荐
相关产品推荐

