STM32入门学习笔记之SD卡基础读写实验4

2023-09-27  

(2)创建sdio_sdcard.c文件,并输入以下代码。


#include "sdio_sdcard.h"

#include "string.h"



SD_CardInfo SDCardInfo ;                                        //SD卡信息

u8 CardType=SDIO_STD_CAPACITY_SD_CARD_V1_1 ;                              //SD卡类型

/***************************************************

Name    :SDIO_Clock_Set

Function  :SDIO发送命令函数

Paramater  :

      cmdindex:命令索引,低六位有效

      waitrsp:期待的相应

        00/10:无响应

        01:短响应

        11:长响应

      arg:参数

Return    :错误代码

***************************************************/

void SDIO_Send_Cmd( u8 cmdindex, u8 waitrsp, u32 arg )

{      

  u32 tmpreg ;

  SDIO->ARG = arg ;

  tmpreg = SDIO->CMD ;

  tmpreg &= 0xFFFFF800 ;                                        //清除index和waitrsp

  tmpreg |= cmdindex&0X3F ;                                      //设置新的index

  tmpreg |= waitrsp<<6 ;                                        //设置新的wait rsp

  tmpreg |= 0<<8 ;                                          //无等待

  tmpreg |= 1<<10 ;                                          //命令通道状态机使能

  SDIO->CMD = tmpreg ;

}

/***************************************************

Name    :SDIO_Send_Data_Cfg

Function  :SDIO发送数据配置函数

Paramater  :

      datatimeout:超时时间设置

      datalen:传输数据长度,低25位有效,必须为块大小的整数倍

      blksize:块大小.实际大小为:2^blksize字节

      dir:数据传输方向

        0:控制器到卡

        1:卡到控制器

Return    :错误代码

***************************************************/

void SDIO_Send_Data_Cfg( u32 datatimeout, u32 datalen, u8 blksize, u8 dir )

{

  u32 tmpreg;

  SDIO->DTIMER = datatimeout ;

  SDIO->DLEN = datalen&0x1FFFFFF ;                                  //低25位有效

  tmpreg = SDIO->DCTRL ; 

  tmpreg &= 0xFFFFFF08 ;                                        //清除之前的设置

  tmpreg |= blksize<<4 ;                                        //设置块大小

  tmpreg |= 0<<2 ;                                          //块数据传输

  tmpreg |= ( dir&0x01 )<<1 ;                                      //方向控制

  tmpreg |= 1<<0 ;                                          //数据传输使能,DPSM状态机

  SDIO->DCTRL = tmpreg ;

}

/***************************************************

Name    :SDIO_Clock_Set

Function  :SDIO时钟初始化设置

Paramater  :

      clkdiv:时钟分频系数

Return    :错误代码

***************************************************/

void SDIO_Clock_Set( u8 clkdiv )

{

  u32 tmpreg = SDIO->CLKCR ;

  tmpreg &= 0xFFFFFF00 ;

  tmpreg |= clkdiv;

  SDIO->CLKCR = tmpreg ;

}

/***************************************************

Name    :CmdError

Function  :检查CMD0的执行状态

Paramater  :None

Return    :错误代码

***************************************************/

SD_Error CmdError()

{

  SD_Error errorstatus = SD_OK ;

  u32 timeout=SDIO_CMD0TIMEOUT ;

  while( timeout-- )

  {

    //命令已发送(无需响应)

    if( SDIO->STA&( 1<<7 ) )

      break ;

  }

  if( timeout==0 )

    return SD_CMD_RSP_TIMEOUT ;

  SDIO->ICR = 0x5FF ;                                          //清除标记

  return errorstatus ;

}

/***************************************************

Name    :CmdResp7Error

Function  :检查R7响应的错误状态

Paramater  :None

Return    :错误代码

***************************************************/

SD_Error CmdResp7Error()

{

  u32 status ;

  u32 timeout = 0x00010000 ;

   while( timeout-- )

  {

    status = SDIO->STA ;

    if( ( status&0x45 )!=0 )                                    //等待接收到应答

      break ;

  }

  //响应超时

   if( ( timeout==0 )||( ( status&0x04 )==0x04 ) )

  {

    //当前卡不是2.0兼容卡,或者不支持设定的电压范围

    SDIO->ICR |= 1<<2 ;                                        //清除命令响应超时标志

    return SD_CMD_RSP_TIMEOUT ;

  }

  //成功接收到响应

  if( ( status&0x40 )==0x40 )

    SDIO->ICR |= 1<<6 ;                                        //清除响应标志

  return SD_OK ;

}

/***************************************************

Name    :CmdResp1Error

Function  :检查R1响应的错误状态

Paramater  :

      cmd:当前命令

Return    :错误代码

***************************************************/

SD_Error CmdResp1Error( u8 cmd )

{    

     u32 status ;

  while( 1 )

  {

    status = SDIO->STA ;

    if( ( status&0x45 )!=0 )                                    //等待接收到应答

      break ;

  }

  //响应超时

  if( ( status&0x04 )==0x04 )

  {

     SDIO->ICR |= 1<<2 ;                                        //清除命令响应超时标志

    return SD_CMD_RSP_TIMEOUT ;

  }

  //CRC错误

   if( ( status&0x01 )==0x01 )

  {

     SDIO->ICR |= 1<<0;                                        //清除标志

    return SD_CMD_CRC_FAIL;

  }

  if( SDIO->RESPCMD!=cmd )

    return SD_ILLEGAL_CMD ;                                      //命令不匹配

    SDIO->ICR = 0x5FF ;                                          //清除标记

  return ( SD_Error )( SDIO->RESP1&0xFDFFE008 ) ;                            //返回卡响应

}

/***************************************************

Name    :CmdResp3Error

Function  :检查R3响应的错误状态

Paramater  :None

Return    :错误代码

***************************************************/

SD_Error CmdResp3Error()

{

  u32 status ;             

   while( 1 )

  {

    status = SDIO->STA ;

    if( ( status&0x45 )!=0 )                                     //等待接收到应答

      break ;

  }

  //响应超时

   if( ( status&0x04 )==0x04 )

  {

    SDIO->ICR |= 1<<2 ;                                        //清除命令响应超时标志

    return SD_CMD_RSP_TIMEOUT ;

  }

     SDIO->ICR = 0x5FF ;                                          //清除标记

   return SD_OK ;

}

/***************************************************

Name    :CmdResp2Error

Function  :检查R2响应的错误状态

Paramater  :None

Return    :错误代码

***************************************************/

SD_Error CmdResp2Error()

{

  u32 status ;

  u32 timeout = 0x00010000 ;

   while( timeout-- )

  {

    status = SDIO->STA ;

    if( ( status&0x45 )!=0 )                                    //接收到R2响应

      break ;

  }

  //响应超时

    if( ( timeout==0 )||( ( status&0x04 )==0x04 ) )

  {

    SDIO->ICR |= 1<<2 ;                                        //清除命令响应超时标志

    return SD_CMD_RSP_TIMEOUT ;

  }

  //CRC错误

  if( ( status&0x01 )==0x01 )

  {

    SDIO->ICR |= 1<<0 ;                                        //清除响应标志

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。