RISC-V技术论坛
直播中

安立路

9年用户 883经验值
私信 关注
[经验]

SD卡初始化原理讲解与实现

分享内容:SD卡
我们对 SD 的读写协议一般有 SPI 模式和SDIO 模式两种,由于SPI 在芯片管脚上只占用四根线,而且SPI实现SD卡读写只需要修改一些 SPI 接口逻辑就可以实现,因此,我们采用的是SPI 模式对SD卡进行操作。 SPI 是串行外设接口(Serial Peripheral Interface)的缩写。是 Motorola 公司推出的一种同步串行接口技术,是一种高速的,全双工,同步的通信总线。SPI 具有支持全双工通信;通信简单;数据传输速率快;高速、同步、全双工、非差分、总线式;主从机通信模式等特点。 SPI 模式的信号线有:CS、CLK、MISO、MOSI,4 根线。
由于板子只能插入 TF 卡即 MicroSD card,我查阅相关资料得到 TF 卡的 SPI 模式接口(如图),通过这些接口,将 SD 卡和 FPGA 通过 SPI 模式连接起来对其进行操作。
  

  
  



图5.4:SD卡接口简介

  

  
SD卡管脚

  
  
FPGA管脚

  


  
sd_miso

  
  
F16

  


  
sd_clk

  
  
C18

  


  
sd_cs

  
  
F18

  


SD卡初始化步骤:
SD 卡初始化过程: 在对 SD 卡初始化之前,我们需要对其上电后复位。复位的方法为:
1 拉高 CS,发送至少 74 个时钟周期来使 SD 卡达到正常工作电压和进行同步
2 选低 CS,发送 CMD0,需要收到回应 0x01 表示成功进入等待状态
3 拉高 CS,发送 8 个时钟
复位成功后我们就可以对其进行初始化了。初始化的过程较复杂,对其过程总结如下:
4 使用 CMD,发送 CMD1,收到 0x00 表示成功
5 使用CMD55+ACMD41
6 发送 CMD55(表示接下来要对其使用 ACMDx 类的命令),收到 0x01

7 发送 ACMD41,收到 0x00 表示成功
命令RTL代码




       parameter  CMD0  = {8'h40,8'h00,8'h00,8'h00,8'h00,8'h95};       parameter  CMD8  = {8'h48,8'h00,8'h00,8'h01,8'haa,8'h87};       parameter  CMD55 = {8'h77,8'h00,8'h00,8'h00,8'h00,8'hff};         parameter  ACMD41= {8'h69,8'h40,8'h00,8'h00,8'h00,8'hff};       parameter  DIV_FREQ = 200;       parameter  OVER_tiME_NUM = 25000;





状态机实现部分RTL代码
case(cur_state)
            st_idle : begin
                sd_cs <= 1'b1;
                sd_mosi <= 1'b1;
            end     
            st_send_cmd0 : begin
                cmd_bit_cnt <= cmd_bit_cnt + 6'd1;        
                sd_cs <= 1'b0;                           
                sd_mosi <= CMD0[6'd47 - cmd_bit_cnt];
                if(cmd_bit_cnt == 6'd47)                  
                    cmd_bit_cnt <= 6'd0;                  
            end
            st_wait_cmd0 : begin                          
                sd_mosi <= 1'b1;            
                if(res_en)
                    sd_cs <= 1'b1;                                      
                over_time_cnt <= over_time_cnt + 1'b1;
                if(over_time_cnt == OVER_TIME_NUM - 1'b1)
                    over_time_en <= 1'b1;
                if(over_time_en)
                    over_time_cnt <= 16'd0;                                       
            end                                          
            st_send_cmd8 : begin
                if(cmd_bit_cnt<=6'd47) begin
                    cmd_bit_cnt <= cmd_bit_cnt + 6'd1;
                    sd_cs <= 1'b0;
                    sd_mosi <= CMD8[6'd47 - cmd_bit_cnt];
                end
                else begin
                    sd_mosi <= 1'b1;
                    if(res_en) begin
                        sd_cs <= 1'b1;
                        cmd_bit_cnt <= 6'd0;
                    end   
                end                                                                  
            end
            st_send_cmd55 : begin
                if(cmd_bit_cnt<=6'd47) begin
                    cmd_bit_cnt <= cmd_bit_cnt + 6'd1;
                    sd_cs <= 1'b0;
                    sd_mosi <= CMD55[6'd47 - cmd_bit_cnt];      
                end
                else begin
                    sd_mosi <= 1'b1;
                    if(res_en) begin
                        sd_cs <= 1'b1;
                        cmd_bit_cnt <= 6'd0;     
                    end        
                end                                                                                    
            end
            st_send_acmd41 : begin
                if(cmd_bit_cnt <= 6'd47) begin
                    cmd_bit_cnt <= cmd_bit_cnt + 6'd1;
                    sd_cs <= 1'b0;
                    sd_mosi <= ACMD41[6'd47 - cmd_bit_cnt];      
                end
                else begin
                    sd_mosi <= 1'b1;
                    if(res_en) begin
                        sd_cs <= 1'b1;
                        cmd_bit_cnt <= 6'd0;  
                    end        
                end     
            end
            st_init_done : begin
                sd_init_done <= 1'b1;
                sd_cs <= 1'b1;
                sd_mosi <= 1'b1;
            end
            default : begin
                sd_cs <= 1'b1;
                sd_mosi <= 1'b1;               
            end   
        endcase


      

更多回帖

发帖
×
20
完善资料,
赚取积分