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

Abd*_*uor 3 c microcontroller hal spi stm32

当我发送CMD0命令(0x40 0x00 0x00 0x00 0x00 0x95)时,我试图在STM32F303上使用SPI初始化SDCard,我试着看一下示波器上来自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);

    }
Run Code Online (Sandbox Code Playgroud)

现在我发送正确的命令,我可以在范围内看到它.但是,我没有得到SD01的0x01响应(我一直得到0xff)(SanDisk Ultra 40MB/s ... 16GB)我使用下面的代码:

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);
Run Code Online (Sandbox Code Playgroud)

Ben*_*ics 5

在启动下一个SPI传输之前,您不会等待SPI传输结束.您也不应该逐字节发送缓冲区,您可以在一次调用中发送整个缓冲区.

HAL_SPI_Transmit(&hspi1, cmd0, 6, 10);
while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
Run Code Online (Sandbox Code Playgroud)

除了在发送下一个字节之前你没有等待的问题之外,你的代码的这部分只是发送垃圾:

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);
}
Run Code Online (Sandbox Code Playgroud)

第二个参数是指向数据缓冲区的指针.您的代码不会发送,0xff但会在0xff内存地址发送一些垃圾.

要发送0xff以下内容:

uint8_t value = 0xff
HAL_SPI_Transmit(&hspi1, &value, 1, 10);
while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
Run Code Online (Sandbox Code Playgroud)

更新:

还有这样的行:

HAL_SPI_Transmit(&hspi1, (uint8_t *)cmd0[0], 1, 10);
Run Code Online (Sandbox Code Playgroud)

也发送垃圾数​​据.

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);
Run Code Online (Sandbox Code Playgroud)

所以我建议再次发送整个数组,如上所示.