STM32F303上使用SPI进行SD卡初始化的问题

3
我正在尝试在STM32F303上使用SPI初始化SD卡,当我发送CMD0命令(0x40 0x00 0x00 0x00 0x00 0x95)时,在示波器上查看MOSI传输的信号时,我看到了不同的信号,如下图所示。请注意,SPI速度为281.25kBits/s。任何帮助将不胜感激。
以下是我用来测试MOSI输出的代码部分:
uint8_t cmd0[6]={0x40,0x00,0x00,0x00,0x00,0x95};
FATFS_CS_HIGH;
HAL_SPI_Transmit(&hspi1, (uint8_t*)0xff, 1, 10);
    for(int i=0;i<10;i++)
  {
    HAL_SPI_Transmit(&hspi1, (uint8_t*)0xff, 1, 10);
   }

  FATFS_CS_LOW;

while(1){

      HAL_SPI_Transmit(&hspi1, (uint8_t *)cmd0[0], 1, 10);

      HAL_SPI_Transmit(&hspi1, (uint8_t *)cmd0[1], 1, 10);
      HAL_SPI_Transmit(&hspi1, (uint8_t *)cmd0[2], 1, 10);
      HAL_SPI_Transmit(&hspi1, (uint8_t *)cmd0[3], 1,10);
      HAL_SPI_Transmit(&hspi1,(uint8_t *) cmd0[4], 1, 10);
      HAL_SPI_Transmit(&hspi1, (uint8_t *)cmd0[5], 1, 10);

    }

现在我发送了正确的命令并且可以在示波器上看到。然而,我从SD卡(SanDisk Ultra 40MB/s ...16GB)没有收到0x01响应,我一直收到0xff。我正在使用以下代码:

FATFS_CS_HIGH;
for (int i = 0; i < 10; i++) {
    HAL_SPI_Transmit(&hspi1, &dumb, 1, 10);
    while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
}

FATFS_CS_LOW;

HAL_SPI_Transmit(&hspi1, cmd0, 6, 10);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

for (int i = 0; i < 10; i++) {
    HAL_SPI_Transmit(&hspi1, &dumb, 1, 10);
    while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
}
HAL_SPI_Receive(&hspi1, &c, 1, 10);

你能解释一下应该发生什么,以便任何有答案的人都能理解,并且还包括你到目前为止尝试解决这个问题的方法吗? - mike510a
抱歉,我不明白你的意思。 - Abdelraheem Alkuor
1个回答

5

在启动下一个SPI传输之前,不需要等待上一个传输结束。同时,您也不应该逐个字节地发送缓冲区,可以通过一次调用来发送整个缓冲区。

HAL_SPI_Transmit(&hspi1, cmd0, 6, 10);
while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

你的代码这一部分只是发送垃圾数据,除了你在发送下一个字节之前不等待的问题外。
HAL_SPI_Transmit(&hspi1, (uint8_t*)0xff, 1, 10);

for(int i=0;i<10;i++)
{
    HAL_SPI_Transmit(&hspi1, (uint8_t*)0xff, 1, 10);
}

第二个参数是数据缓冲区的指针。如果您的代码发送0xff,实际上会发送位于内存地址0xff处的一些垃圾数据。
要发送0xff,请按以下步骤进行:
uint8_t value = 0xff
HAL_SPI_Transmit(&hspi1, &value, 1, 10);
while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

更新:

还有这样的行:

HAL_SPI_Transmit(&hspi1, (uint8_t *)cmd0[0], 1, 10);

还要发送垃圾数据。

这个 cmd0[0] 将返回数组的第一个元素(数据),即 0x40,然后您将其转换为 uint8_t* ,并将其作为 数据缓冲区的指针 传递给 HAL_SPI_Transmit 函数。因此,实际发送的数据是在内存位置 0x40 的一些随机值。

你的数组中某个字节的地址是 &cmd[0] ,请注意返回地址的 & 运算符。正确的调用方式如下:

HAL_SPI_Transmit(&hspi1, &cmd0[0], 1, 10);
while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);

因此,我再次建议像我上面展示的那样将整个数组一次性发送。

您的代码不会发送0xff,而是发送到0xff内存地址的垃圾数据-这是主要问题。 - imbearr
非常感谢Bence Kaulics。我已经尝试了很多次,但都没有成功。我以为“HAL_SPI_Transmit”会确保一个字节被完整发送。你能推荐一些好的参考资料来处理stm32系列吗?再次感谢。 - Abdelraheem Alkuor
页面底部有一个可下载的压缩文件:http://www.st.com/en/embedded-software/stm32cubef3.html,其中包含STM32F3 HAL示例。 - Bence Kaulics
请查看我编辑过的问题,Bence Kaulics。谢谢。 - Abdelraheem Alkuor
@AbdelraheemAlkuor 我会尽快查看它的。 - Bence Kaulics

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接