sd卡spi驱动(1)--初始化

SD卡不同通信方式时的信号线

sd卡spi驱动(1)--初始化_第1张图片

sd卡spi驱动(1)--初始化_第2张图片

模拟 SPI 通信

这里需要注意的是 GPIO 是否有被复用,或被其他任务占用。

SPI 通信模式有四种,分别是 CPOL(时钟极性) 和 CPHA(时钟相位) 为 0 和 1 的情况

在维基百科有张图将这四种情况很好的表现出来了

sd卡spi驱动(1)--初始化_第3张图片

时钟是循环的,每个时钟可以分为上升沿和下降沿,数据在哪个边沿采样就是由 CPHA 决定;时钟在空闲时保持的电平状态就是由 CPOL 决定

CPHA=1 CPOL=1 对应的代码如下:

u8 spi_read_byte(void)
{
  u8 ret = 0;
  u8 i;
  for (i=0; i<8; i++)
  {
    SD_CLK_OUT_L();
    delay_us(DELAY);
    SD_CLK_OUT_H();
    ret = (ret << 1) | ((SD_DAT_STA() != 0) ? 1 : 0); // 上升沿传输
    delay_us(DELAY);
  }
}
void spi_write_byte(u8 byte)
{
  u8 i;
  for (i=8; i>0; i--)
  {
    SD_CLK_OUT_L();
    if (byte & (1<<(i-1))) { // 下降沿采样
      SD_CMD_OUT_H();
    }
    else {
      SD_CMD_OUT_L();
    }
    delay_us(DELAY);
    SD_CLK_OUT_H();
    delay_us(DELAY);
  }
}

SD 卡 SPI 通信

当 SD 卡发送 CMD0 时 CS 脚低电平就进入 SPI 模式

SD 卡的命令格式如图

sd卡spi驱动(1)--初始化_第4张图片

SD 卡的命令有6个字节长度,第1个字节是包头信息+命令,第2到5字节是命令参数,第6个字节是CRC;需要注意最后一个位要置1

SD 卡 SPI 模式的响应有几种类型,常见的是 R1,R1 会回复当前命令的执行状态,当命令非法或 CRC 校验等错误发生时,对应的位会置1,其他几种响应也会包含 R1 的信息,最长的有5个字节,下图是 R1 的位对应的错误信息
sd卡spi驱动(1)--初始化_第5张图片

SD 卡发送命令的实现如下,接口需要提供需要发送的命令、参数、CRC和响应类型

u8 sd_send_cmd_spi(u8 cmd, u32 args, u8 crc, u8 response)
{
  u8 recv = 0;
  sd_send_cmd_spi_enter();
  sd_send_cmd_spi_main(cmd, args, crc);
  recv = spi_read_byte();
  spi_send_clock((response-1)*8);
  sd_send_cmd_spi_exit();
  return recv;
}

其中的子函数实现时需要注意 SD 卡通信的时序问题,相关的时序图可以看这篇文章。我将其中最常用的时序图复制了过来
sd卡spi驱动(1)--初始化_第6张图片

从图中可以看出 SD 卡的传输时序是 MSB 的格式,具体过程:拉低CS -> CMD -> ARGS -> CRC -> 8个CLK -> 接收SD回应 -> 拉高CS -> 8个CLK

具体实现代码如下

void sd_send_cmd_spi_enter(void)
{
  SD_CLK_OUT_L();
  delay_us(10);
}

void sd_send_cmd_spi_exit(void)
{
  SD_CLK_OUT_L();
  SD_CMD_OUT_H(); // 空闲时保持高电平
  delay_us(10);
  spi_send_clock(8); // 末尾8个CLK
}

void sd_send_cmd_spi_main(u8 cmd, u32 args, u8 crc)
{
  u8 i;
  spi_write_byte(cmd);
  for (i=0; i<SD_CMD_ARGS_LEN; i++)
    spi_write_byte((args >> ((SD_CMD_ARGS_LEN-i-1)*8)) & 0xff); // 每次传输最低一个字节
  spi_write_byte(crc);
  spi_send_clock(8); // 末尾8个CLK
}

SD 卡初始化

SD 卡通信需要按照它内部的状态机规定的方式通信,具体过程如下图

sd卡spi驱动(1)--初始化_第7张图片

发送命令过程: CMD0 -> CMD8 -> CMD58 -> CMD55 -> ACMD41(循环)

发送 CMD8 的时候需要带上 CRC ,否则会报错,一般推荐参数是 0x1AA ,这样 CRC 就为 0x87

发送 ACMD41 前需要先发送 CMD55,否则 SD 卡会回应 0x05,也就是命令非法;初始化的时候需要循环发送 ACMD41,直到 SD 卡响应的最后一个位清0,也就是退出 idle 状态

你可能感兴趣的:(sd卡spi驱动(1)--初始化)