打印
[RISC-V MCU 应用开发]

【RISC-V MCU CH32V103测评】+TF卡的SPI驱动

[复制链接]
1041|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
coslight|  楼主 | 2020-11-18 14:02 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
TF卡的SPI驱动
硬件连接关系
SD采用SPI模式时的引脚连接关系
硬件系统设计图如下所示:
SPI模式的TF卡引脚连接关系图如下。
  
序号
  
TF卡引脚
CPU引脚
1
CS
PA3
2
SCK
PA5
3
MISO
PA6
4
MOSI
PA7
5
SD_IN
PA8
这里需要特别提醒,CS引脚默认是不焊接的,如果需要测试必须先短接后PA3引脚才能生效。在这里绕了好几天。
软件驱动
1)     IO口配置
这里默认配置SPI的CS引脚为软件控制。
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE );
    GPIO_InitStructure.GPIO_Pin = GPIO_SCK;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_MISO;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init( GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_MOSI;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_NSS;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init( GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_SDCMD;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init( GPIOA, &GPIO_InitStructure);
2)     SPI设备配置
SPI设备采用SPI1,全双工2线方式,软件控制CS信号。
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //SPI_CPOL_High
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
    SPI_InitStructure.SPI_BaudRatePrescaler =SPI_BaudRatePrescaler_256;
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
    SPI_InitStructure.SPI_CRCPolynomial = 7;
    SPI_Init( SPI1, &SPI_InitStructure );
    SPI_Cmd( SPI1, ENABLE );
3)     TF卡驱动
向SD卡写入一个CMD或者ACMD指令的过程是这样的: 首先使CS为低电平,SD卡使能;其次在SD卡的Din写入指令;写入指令后还要附加8个填充时钟,是SD卡完成内部操作;之后在SD卡的Dout上接受回应;回应接受完毕使CS为低电平,再附加8个填充时钟。
注意:在SD卡的Din没有数据写入时,应使Din保持高电平。
l  SD卡复位:
1.拉高CS,发送至少74个clk周期来使SD卡达到正常工作电压和进行同步
2.选低CS,发送CMD0,需要收到回应0x01表示成功进入idle状态
3.拉高CS,发送8个时钟
       实现代码:
    for(i=0;i<10;i++)
      SPI_ReadWrite_Byte(0XFF);//发送至少74个脉冲
    retry=20;
    do
    {
        r1=SD_SendCmd(CMD0,0,0x95);//进入IDLE状态
    }while((r1!=0X01) && retry--);
l  SD卡初始化:
复位成功后,SD卡就进入了SPI模式,接着应该进行初始化。发送CMD55+ACMD41完成初始化。
时序图如下:
程序代码实现:
     SD_SendCmd(CMD55,0,0X01);     //发送CMD55
     r1=SD_SendCmd(CMD41,0,0X01);  //发送CMD41
l  SDK卡读操作
操作流程:
1.发送CMD18读,收到0x00表示成功
2.连续读直到读到开始字节0xFE
3.读512字节
4.读两个CRC字节
5.如果还想读下一扇区,重复2-4
6.发送CMD12来停止读多块操作
时序图如下:
程序实现:
r1=SD_SendCmd(CMD18,sector,0X01);
        do
        {
          r1=SD_RecvData(buf,512);
          buf+=512;
        }while(--cnt && r1==0);
SD_SendCmd(CMD12,0,0X01)
l  SDK卡写操作
操作走流程:
    1.发送CMD24(写单块),CMD25(写多块)收到0x00表示成功
    2.发送若干时钟
    3.发送写单块开始字节0xFE,写多块开始字节0xFC
    4.发送512个字节数据
    5.发送2字节CRC(可以均为0xff)
    6.连续读直到读到XXX00101表示数据写入成功
7.继续读进行忙检测(读到0x00表示SD卡正忙),当读到0xff表示写操作完成
    8.如果想写下一扇区重复2-7步骤
    9.发送写多块停止字节0xFD来停止写操作
    10.进行忙检测直到读到0xFF
时序图:
程序代码实现:
       r1=SD_SendCmd(CMD25,sector,0X01);
       if(r1==0)
       {
           do
           {
               r1=SD_SendBlock(buf,0xFC);
               buf+=512;
           }while(--cnt && r1==0);
           r1=SD_SendBlock(0,0xFD);
       }
测试效果
成功的完成SD卡初始化,并且读到了SD卡容量。

使用特权

评论回复
评论
LIzs6 2020-12-9 15:45 回复TA
程序源码可以放出来看看吗 
dirtwillfly 2020-11-20 13:26 回复TA
感谢分享 

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

928

帖子

5

粉丝