flqcandy 发表于 2014-11-4 15:05:11

基于STM32Cube移植FatFs文件系统,f_Open返回FR_NOT_READY?

本帖最后由 flqcandy 于 2014-11-4 15:05 编辑

新手移植FatFs文件系统,利用STM32Cube,初始化SPI2,选择PB9作为片选信号,没用使用cube自带的fatfs文件系统;问题如标题所示,f_Open返回FR_NOT_READY,通过断点调试,发现在调用SD_Init()函数中,发送CMD0,让SD进入IDLE状态时,返回值不是0x01;调试了一周,也没找到问题所在。【系统时钟160MHz,SPI2所在的APBH1时钟为40MHz,SD卡为16G的SDHC卡】,跪求指导;
代码见楼下:

flqcandy 发表于 2014-11-4 15:05:29

main.c
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "main.h"
#include "diskio.h"
/* Private variables ---------------------------------------------------------*/
SPI_HandleTypeDef hspi2;

/* USER CODE BEGIN 0 */
FATFS fs;// Work area (file system object) for logical drive
//        DIR dir;
FIL fsrc, fdst;      // file objects
FRESULT fr;// FatFs function common result code
/* USER CODE END 0 */

/* Private function prototypes -----------------------------------------------*/
static void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_SPI2_Init(void);

int main(void)
{

/* USER CODE BEGIN 1 */
char buffer; // file copy buffer
        UINT br, bw;         // File R/W count
//        DSTATUS status;
        unsigned char w_buffer[]="123456789123456789123456789123456789";//??????
/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* Configure the system clock */
SystemClock_Config();

/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_SPI2_Init();

/* USER CODE BEGIN 2 */
//        status = disk_initialize(0);
//        if(status==0)
//         {
//                return RES_OK;
//          }
fr=f_mount(0,&fs);
        //fr=f_opendir(&dir,"");
        fr = f_open(&fsrc,"0:/srcfile.txt",FA_CREATE_ALWAYS|FA_WRITE);
        if(fr==FR_OK)
           fr = f_write(&fsrc,w_buffer,strlen(w_buffer),&bw);
        fr = f_close(&fsrc);
        f_mount(0,NULL);
/* USER CODE END 2 */

/* USER CODE BEGIN 3 */
/* Infinite loop */
while (1)
{

}
/* USER CODE END 3 */

}

/** System Clock Configuration
*/
static void SystemClock_Config(void)
{

RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;

__PWR_CLK_ENABLE();

__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 15;
RCC_OscInitStruct.PLL.PLLN = 192;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
                              |RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

}

/* SPI2 init function */
void MX_SPI2_Init(void)
{

hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLED;
hspi2.Init.CRCPolynomial = 7;
HAL_SPI_Init(&hspi2);

}

/** Configure pins as
      * Analog
      * Input
      * Output
      * EVENT_OUT
      * EXTI
*/
void MX_GPIO_Init(void)
{

GPIO_InitTypeDef GPIO_InitStruct;

/* GPIO Ports Clock Enable */
__GPIOH_CLK_ENABLE();
__GPIOC_CLK_ENABLE();
__GPIOB_CLK_ENABLE();

/*Configure GPIO pin : PB9 */
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_MEDIUM;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

}

flqcandy 发表于 2014-11-4 15:05:54

diskio.c
/* Includes ------------------------------------------------------------------*/
#include "diskio.h"
#include "ffconf.h"
#include "Spi_SD_Driver.h"
#include <stdio.h>

/* Private variables ---------------------------------------------------------*/
//extern MSD_CARDINFO SD0_CardInfo;


DSTATUS disk_initialize (
        BYTE drv                                /* Physical drive nmuber (0..) */
)
{
        int Status;
        Status = SD_Init();
        if(Status==0)
         {
                return RES_OK;
          }else{
                return STA_NOINIT;
          }
}




DSTATUS disk_status (
        BYTE drv                /* Physical drive nmuber (0..) */
)
{
       
        return RES_OK;
               
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                      */

DRESULT disk_read (
        BYTE drv,                /* Physical drive nmuber (0..) */
        BYTE *buff,                /* Data buffer to store read data */
        DWORD sector,        /* Sector address (LBA) */
        BYTE count                /* Number of sectors to read (1..255) */
)
{
        int Status;
        if( !count )
        {   
                return RES_PARERR;/* count²»ÄܵÈÓÚ0£¬·ñÔò·µ»Ø²ÎÊý´íÎó */
        }
        if(count==1)            /* 1¸ösectorµÄ¶Á²Ù×÷ */      
        {   
                Status = SD_ReadSingleBlock( sector ,buff );
                if(Status == 0){
                        return RES_OK;
                }else{
                        return RES_ERROR;
                }   
        }                                                
        else                  /* ¶à¸ösectorµÄ¶Á²Ù×÷ */   
        {
                Status = SD_ReadMultiBlock( sector , buff ,count);
                if(Status == 0){
                        return RES_OK;
                }else{
                        return RES_ERROR;
                }
        }                                                
               
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */

#if _READONLY == 0
DRESULT disk_write (
        BYTE drv,                        /* Physical drive nmuber (0..) */
        const BYTE *buff,                /* Data to be written */
        DWORD sector,                /* Sector address (LBA) */
        BYTE count                        /* Number of sectors to write (1..255) */
)
{
        int Status;
        if( !count )
        {   
                return RES_PARERR;/* count²»ÄܵÈÓÚ0£¬·ñÔò·µ»Ø²ÎÊý´íÎó */
        }
       
        if(count==1)            /* 1¸ösectorµÄд²Ù×÷ */      
        {   
                Status = SD_WriteSingleBlock( sector , (uint8_t *)(&buff) );
                if(Status == 0){
                        return RES_OK;
                }else{
                        return RES_ERROR;
                }
        }                                                
        else                  /* ¶à¸ösectorµÄд²Ù×÷ */   
        {
        Status = SD_WriteMultiBlock( sector , (uint8_t *)(&buff) , count );
                if(Status == 0){
                        return RES_OK;
                }else{
                        return RES_ERROR;
                }   
        }                                                
               
}
#endif /* _READONLY */



/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                             */

//DRESULT disk_ioctl (
//        BYTE drv,                /* Physical drive nmuber (0..) */
//        BYTE ctrl,                /* Control code */
//        void *buff                /* Buffer to send/receive control data */
//)
//{
//        //MSD0_GetCardInfo(&SD0_CardInfo);
//        switch (ctrl)
//        {
//                case CTRL_SYNC :
//                        return RES_OK;
//                case GET_SECTOR_COUNT :
//                        //*(DWORD*)buff = SD0_CardInfo.Capacity/SD0_CardInfo.BlockSize;
//                          return RES_OK;
//                case GET_BLOCK_SIZE :
//                        //*(WORD*)buff = SD0_CardInfo.BlockSize;
//                          return RES_OK;       
//                case CTRL_POWER :
//                        break;
//                case CTRL_LOCK :
//                        break;
//                case CTRL_EJECT :
//                        break;
//                      /* MMC/SDC command */
//                case MMC_GET_TYPE :
//                        break;
//                case MMC_GET_CSD :
//                        break;
//                case MMC_GET_CID :
//                        break;
//                case MMC_GET_OCR :
//                        break;
//                case MMC_GET_SDSTAT :
//                        break;       
//        }
//   
//}
DRESULT disk_ioctl(BYTE drv,/* Physical drive nmuber (0..) */
BYTE ctrl,/* Control code */
void *buff /* Buffer to send/receive control data */
)
{
    return RES_OK;

}


/* µÃµ½ÎļþCalendar¸ñʽµÄ½¨Á¢ÈÕÆÚ,ÊÇDWORD get_fattime (void) Äæ±ä»» */                                                       
/*-----------------------------------------------------------------------*/
/* User defined function to give a current time to fatfs module          */
/* 31-25: Year(0-127 org.1980), 24-21: Month(1-12), 20-16: Day(1-31) */                                                                                                                                                                                                                                          
/* 15-11: Hour(0-23), 10-5: Minute(0-59), 4-0: Second(0-29 *2) */                                                                                                                                                                                                                                                
DWORD get_fattime (void)
{
   
    return 0;
}

flqcandy 发表于 2014-11-4 15:12:06

SPI_SD_Driver.c分3部分上传,Part1:
/* Includes ------------------------------------------------------------------*/
//#include "config.h"
#include "Spi_SD_Driver.h"
#include "stm32f4xx.h"
#include "main.h"

u8SD_Type=0;


/* Private functions ---------------------------------------------------------*/

// ÒÔÏÂÊÇSPIÄ£¿éµÄ³õʼ»¯´úÂ룬ÅäÖóÉÖ÷»úģʽ£¬·ÃÎÊSD¿¨




/*******************************************************************************
* Function Name: SPI_SetSpeed
* Description    : SPIÉèÖÃËÙ¶ÈΪ¸ßËÙ
* Input          : u8 SpeedSet
*                  Èç¹ûËÙ¶ÈÉèÖÃÊäÈë0£¬ÔòµÍËÙģʽ£¬·Ç0Ôò¸ßËÙģʽ
*                  SPI_SPEED_HIGH   1
*                  SPI_SPEED_LOW    0
* Output         : None
* Return         : None
*******************************************************************************/
void SPI_SetSpeed(u8 SpeedSet)
{

hspi2.Instance=SPI2;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLED;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_ENABLED;
        hspi2.Init.CRCPolynomial = 7;
if(SpeedSet==SPI_SPEED_LOW)
    {
        hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
    }
    else
    {
      hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
    }
HAL_SPI_Init(&hspi2);




}
/*******************************************************************************
* Function Name: SPI_ReadWriteByte
* Description    : SPI¶Áдһ¸ö×Ö½Ú£¨·¢ËÍÍê³Éºó·µ»Ø±¾´ÎͨѶ¶ÁÈ¡µÄÊý¾Ý£©
* Input          : u8 TxData ´ý·¢Ë͵ÄÊý
* Output         : None
* Return         : u8 RxData ÊÕµ½µÄÊý
*******************************************************************************/

u8 SPI_ReadWriteByte(u8 TxData)
{

   u8 RxData;
   HAL_SPI_TransmitReceive(&hspi2,&TxData,&RxData,1,1);
   return RxData;

}

/*******************************************************************************
* Function Name: SD_WaitReady
* Description    : µÈ´ýSD¿¨Ready
* Input          : None
* Output         : None
* Return         : u8
*                   0£º ³É¹¦
*                   other£ºÊ§°Ü
*******************************************************************************/
u8 SD_WaitReady(void)
{
    u8 r1;
    u16 retry;
    retry = 0;
    do
    {
      r1 = SPI_ReadWriteByte(0xFF);
      if(retry==0xfffe)
      {
            return 1;
      }
    }while(r1!=0xFF);

    return 0;
}



/*******************************************************************************
* Function Name: SD_SendCommand
* Description    : ÏòSD¿¨·¢ËÍÒ»¸öÃüÁî
* Input          : u8 cmd   ÃüÁî
*                  u32 argÃüÁî²ÎÊý
*                  u8 crc   crcУÑéÖµ
* Output         : None
* Return         : u8 r1 SD¿¨·µ»ØµÄÏìÓ¦
*******************************************************************************/
u8 SD_SendCommand(u8 cmd, u32 arg, u8 crc)
{
    unsigned char r1;
    unsigned char Retry = 0;

    //????????
    SPI_ReadWriteByte(0xff);
    //Ƭѡ¶ËÖõͣ¬Ñ¡ÖÐSD¿¨
    SD_CS_ENABLE();

    //·¢ËÍ
    SPI_ReadWriteByte(cmd | 0x40);                         //·Ö±ðдÈëÃüÁî
    SPI_ReadWriteByte(arg >> 24);
    SPI_ReadWriteByte(arg >> 16);
    SPI_ReadWriteByte(arg >> 8);
    SPI_ReadWriteByte(arg);
    SPI_ReadWriteByte(crc);
   
    //µÈ´ýÏìÓ¦£¬»ò³¬Ê±Í˳ö
    while((r1 = SPI_ReadWriteByte(0xFF))==0xFF)
    {
      Retry++;
      if(Retry > 200)
      {
            break;
      }
    }
   

    //¹Ø±ÕƬѡ
    SD_CS_DISABLE();
    //ÔÚ×ÜÏßÉ϶îÍâÔö¼Ó8¸öʱÖÓ£¬ÈÃSD¿¨Íê³ÉÊ£ÏµĹ¤×÷
    SPI_ReadWriteByte(0xFF);

    //·µ»Ø״ֵ̬
    return r1;
}


/*******************************************************************************
* Function Name: SD_SendCommand_NoDeassert
* Description    : ÏòSD¿¨·¢ËÍÒ»¸öÃüÁî(½áÊøÊDz»Ê§ÄÜƬѡ£¬»¹ÓкóÐøÊý¾Ý´«À´£©
* Input          : u8 cmd   ÃüÁî
*                  u32 argÃüÁî²ÎÊý
*                  u8 crc   crcУÑéÖµ
* Output         : None
* Return         : u8 r1 SD¿¨·µ»ØµÄÏìÓ¦
*******************************************************************************/
u8 SD_SendCommand_NoDeassert(u8 cmd, u32 arg, u8 crc)
{
    unsigned char r1;
    unsigned char Retry = 0;

    //????????
    SPI_ReadWriteByte(0xff);
    //Ƭѡ¶ËÖõͣ¬Ñ¡ÖÐSD¿¨
    SD_CS_ENABLE();

    //·¢ËÍ
    SPI_ReadWriteByte(cmd | 0x40);                         //·Ö±ðдÈëÃüÁî
    SPI_ReadWriteByte(arg >> 24);
    SPI_ReadWriteByte(arg >> 16);
    SPI_ReadWriteByte(arg >> 8);
    SPI_ReadWriteByte(arg);
    SPI_ReadWriteByte(crc);

    //µÈ´ýÏìÓ¦£¬»ò³¬Ê±Í˳ö
    while((r1 = SPI_ReadWriteByte(0xFF))==0xFF)
    {
      Retry++;
      if(Retry > 200)
      {
            break;
      }
    }
    //·µ»ØÏìÓ¦Öµ
    return r1;
}



flqcandy 发表于 2014-11-4 15:14:35

Part2:
/*******************************************************************************
* Function Name: SD_Init
* Description    : ³õʼ»¯SD¿¨
* Input          : None
* Output         : None
* Return         : u8
*                  0£ºNO_ERR
*                  1£ºTIME_OUT
*                  99£ºNO_CARD
*******************************************************************************/
u8 SD_Init(void)
{
    u16 i;      // ÓÃÀ´Ñ­»·¼ÆÊý
    u8 r1;      // ´æ·ÅSD¿¨µÄ·µ»ØÖµ
    u16 retry;// ÓÃÀ´½øÐг¬Ê±¼ÆÊý
    u8 buff;

    //Èç¹ûûÓмì²âµ½¿¨²åÈ룬ֱ½ÓÍ˳ö£¬·µ»Ø´íÎó±êÖ¾
//    if(!SD_DET())
//    {
//      //return 99;      
//      return STA_NODISK;//FatFS´íÎó±êÖ¾£ºÃ»ÓвåÈë´ÅÅÌ
//    }

    //SD¿¨Éϵç
   // SD_PWR_ON();
    // ´¿ÑÓʱ£¬µÈ´ýSD¿¨ÉϵçÍê³É

        /*******************************************************
        //Õâ¸öµØ·½Òª¼ÓÒ»¾ä,ÉèÖÃSPIËÙ¶ÈΪµÍËÙ¡£
        //ΪʲôÓеĿ¨¿ÉÒÔÄØ£¿ÒòΪSPI³õʼ»¯Ê±ÊǵÍËٵģ¬SD¿¨³õʼ»¯
        //Íê³ÉºóÉèÖÃΪ¸ßËÙ£¬ÓеĿ¨Ö»Òª³õʼ»¯Ò»´Î¾ÍÐУ¬³ÌÐò¾Íok£»
        //µ«ÓеĿ¨ÐèÒª¶à´Î¸´Î»£¬ºÇºÇ£¬Õâ¸öµØ·½²îÕâÒ»¾ä£¬
        //ÕâÖÖ¿¨¾ÍÓò»³É¿©£¡
        *******************************************************/
    SPI_SetSpeed(0); //ÉèÖÃSPIËÙ¶ÈΪµÍËÙ
               
    //ÏȲúÉú>74¸öÂö³å£¬ÈÃSD¿¨×Ô¼º³õʼ»¯Íê³É
    for(i=0;i<10;i++)
    {
      SPI_ReadWriteByte(0xFF);
    }

    //-----------------SD¿¨¸´Î»µ½idle¿ªÊ¼-----------------
    //Ñ­»·Á¬Ðø·¢ËÍCMD0£¬Ö±µ½SD¿¨·µ»Ø0x01,½øÈëIDLE״̬
    //³¬Ê±ÔòÖ±½ÓÍ˳ö
                SD_CS_ENABLE();
    retry = 0;
    do
    {
      //·¢ËÍCMD0£¬ÈÃSD¿¨½øÈëIDLE״̬
      r1 = SD_SendCommand(CMD0, 0, 0x95);
      retry++;
    }while((r1 != 0x01) && (retry<200));

    //Ìø³öÑ­»·ºó£¬¼ì²éÔ­Òò£º³õʼ»¯³É¹¦£¿or ÖØÊÔ³¬Ê±£¿
    if(retry==200)
    {
      return 1;   //³¬Ê±·µ»Ø1
    }
//                retry=20;
//                do
//                {
//                        r1=SD_SendCommand(CMD0,0,0x95);
//                }while((r1!=0x01)&&retry--);
//                SD_Type=0;
    //-----------------SD¿¨¸´Î»µ½idle½áÊø-----------------



    //»ñÈ¡¿¨Æ¬µÄSD°æ±¾ÐÅÏ¢
    r1 = SD_SendCommand_NoDeassert(8, 0x1aa, 0x87);

    //Èç¹û¿¨Æ¬°æ±¾ÐÅÏ¢ÊÇv1.0°æ±¾µÄ£¬¼´r1=0x05£¬Ôò½øÐÐÒÔϳõʼ»¯
    if(r1 == 0x05)
    {
      //ÉèÖÿ¨ÀàÐÍΪSDV1.0£¬Èç¹ûºóÃæ¼ì²âµ½ÎªMMC¿¨£¬ÔÙÐÞ¸ÄΪMMC
      SD_Type = SD_TYPE_V1;

      //Èç¹ûÊÇV1.0¿¨£¬CMD8Ö¸ÁîºóûÓкóÐøÊý¾Ý
      //ƬѡÖøߣ¬½áÊø±¾´ÎÃüÁî
      SD_CS_DISABLE();
      //¶à·¢8¸öCLK£¬ÈÃSD½áÊøºóÐø²Ù×÷
      SPI_ReadWriteByte(0xFF);

      //-----------------SD¿¨¡¢MMC¿¨³õʼ»¯¿ªÊ¼-----------------

      //·¢¿¨³õʼ»¯Ö¸ÁîCMD55+ACMD41
      // Èç¹ûÓÐÓ¦´ð£¬ËµÃ÷ÊÇSD¿¨£¬ÇÒ³õʼ»¯Íê³É
      // ûÓлØÓ¦£¬ËµÃ÷ÊÇMMC¿¨£¬¶îÍâ½øÐÐÏàÓ¦³õʼ»¯
      retry = 0;
      do
      {
            //ÏÈ·¢CMD55£¬Ó¦·µ»Ø0x01£»·ñÔò³ö´í
            r1 = SD_SendCommand(CMD55, 0, 0);
            if(r1 != 0x01)
            {
                return r1;
            }
            //µÃµ½ÕýÈ·ÏìÓ¦ºó£¬·¢ACMD41£¬Ó¦µÃµ½·µ»ØÖµ0x00£¬·ñÔòÖØÊÔ200´Î
            r1 = SD_SendCommand(ACMD41, 0, 0);
            retry++;
      }while((r1!=0x00) && (retry<400));

      // ÅжÏÊdz¬Ê±»¹Êǵõ½ÕýÈ·»ØÓ¦
      // ÈôÓлØÓ¦£ºÊÇSD¿¨£»Ã»ÓлØÓ¦£ºÊÇMMC¿¨
      
      //----------MMC¿¨¶îÍâ³õʼ»¯²Ù×÷¿ªÊ¼------------
      if(retry==400)
      {
            retry = 0;
            //·¢ËÍMMC¿¨³õʼ»¯ÃüÁûÓвâÊÔ£©
            do
            {
                r1 = SD_SendCommand(1, 0, 0);
                retry++;
            }while((r1!=0x00)&& (retry<400));
            if(retry==400)
            {
                return 1;   //MMC¿¨³õʼ»¯³¬Ê±
            }
            //дÈ뿨ÀàÐÍ
            SD_Type = SD_TYPE_MMC;
      }
      //----------MMC¿¨¶îÍâ³õʼ»¯²Ù×÷½áÊø------------
      
      //ÉèÖÃSPIΪ¸ßËÙģʽ
      SPI_SetSpeed(1);

                SPI_ReadWriteByte(0xFF);
      
      //½ûÖ¹CRCУÑé
      /*
                r1 = SD_SendCommand(CMD59, 0, 0x01);
      if(r1 != 0x00)
      {
            return r1;//ÃüÁî´íÎ󣬷µ»Ør1
      }
      */   
      //ÉèÖÃSector Size
      r1 = SD_SendCommand(CMD16, 512, 0xff);
      if(r1 != 0x00)
      {
            return r1;//ÃüÁî´íÎ󣬷µ»Ør1
      }
      //-----------------SD¿¨¡¢MMC¿¨³õʼ»¯½áÊø-----------------

    }//SD¿¨ÎªV1.0°æ±¾µÄ³õʼ»¯½áÊø
   

    //ÏÂÃæÊÇV2.0¿¨µÄ³õʼ»¯
    //ÆäÖÐÐèÒª¶ÁÈ¡OCRÊý¾Ý£¬ÅжÏÊÇSD2.0»¹ÊÇSD2.0HC¿¨
    else if( r1 == 0x01)
    {
      //V2.0µÄ¿¨£¬CMD8ÃüÁîºó»á´«»Ø4×Ö½ÚµÄÊý¾Ý£¬ÒªÌø¹ýÔÙ½áÊø±¾ÃüÁî
      buff = SPI_ReadWriteByte(0xFF);//should be 0x00
      buff = SPI_ReadWriteByte(0xFF);//should be 0x00
      buff = SPI_ReadWriteByte(0xFF);//should be 0x01
      buff = SPI_ReadWriteByte(0xFF);//should be 0xAA
   
      SD_CS_DISABLE();
      //the next 8 clocks
      SPI_ReadWriteByte(0xFF);
      
      //Åжϸÿ¨ÊÇ·ñÖ§³Ö2.7V-3.6VµÄµçѹ·¶Î§
      if(buff==0x01 && buff==0xAA)
      {
            //Ö§³Öµçѹ·¶Î§£¬¿ÉÒÔ²Ù×÷
            retry = 0;
            //·¢¿¨³õʼ»¯Ö¸ÁîCMD55+ACMD41
                    do
                    {
                            r1 = SD_SendCommand(CMD55, 0, 0);
                            if(r1!=0x01)
                            {
                                    return r1;
                            }
                            r1 = SD_SendCommand(ACMD41, 0x40000000, 0);
                if(retry>200)   
                {
                  return r1;//³¬Ê±Ôò·µ»Ør1״̬
                }
            }while(r1!=0);
         
            //³õʼ»¯Ö¸Áî·¢ËÍÍê³É£¬½ÓÏÂÀ´»ñÈ¡OCRÐÅÏ¢

            //-----------¼ø±ðSD2.0¿¨°æ±¾¿ªÊ¼-----------
            r1 = SD_SendCommand_NoDeassert(CMD58, 0, 0);
            if(r1!=0x00)
            {
                return r1;//Èç¹ûÃüÁîûÓзµ»ØÕýÈ·Ó¦´ð£¬Ö±½ÓÍ˳ö£¬·µ»ØÓ¦´ð
            }
            //¶ÁOCRÖ¸Áî·¢³öºó£¬½ô½Ó×ÅÊÇ4×Ö½ÚµÄOCRÐÅÏ¢
            buff = SPI_ReadWriteByte(0xFF);
            buff = SPI_ReadWriteByte(0xFF);
            buff = SPI_ReadWriteByte(0xFF);
            buff = SPI_ReadWriteByte(0xFF);

            //OCR½ÓÊÕÍê³É£¬Æ¬Ñ¡Öøß
            SD_CS_DISABLE();
            SPI_ReadWriteByte(0xFF);

            //¼ì²é½ÓÊÕµ½µÄOCRÖеÄbit30루CCS£©£¬È·¶¨ÆäΪSD2.0»¹ÊÇSDHC
            //Èç¹ûCCS=1£ºSDHC   CCS=0£ºSD2.0
            if(buff&0x40)    //¼ì²éCCS
            {
                SD_Type = SD_TYPE_V2HC;
            }
            else
            {
                SD_Type = SD_TYPE_V2;
            }
            //-----------¼ø±ðSD2.0¿¨°æ±¾½áÊø-----------         
            //ÉèÖÃSPIΪ¸ßËÙģʽ
            SPI_SetSpeed(1);
      }

    }
    return r1;
}



/*******************************************************************************
* Function Name: SD_ReceiveData
* Description    : ´ÓSD¿¨ÖжÁ»ØÖ¸¶¨³¤¶ÈµÄÊý¾Ý£¬·ÅÖÃÔÚ¸ø¶¨Î»ÖÃ
* Input          : u8 *data(´æ·Å¶Á»ØÊý¾ÝµÄÄÚ´æ>len)
*                  u16 len(Êý¾Ý³¤¶È£©
*                  u8 release(´«ÊäÍê³ÉºóÊÇ·ñÊÍ·Å×ÜÏßCSÖÃ¸ß 0£º²»ÊÍ·Å 1£ºÊÍ·Å£©
* Output         : None
* Return         : u8
*                  0£ºNO_ERR
*                  other£º´íÎóÐÅÏ¢
*******************************************************************************/
u8 SD_ReceiveData(u8 *data, u16 len, u8 release)
{
    u16 retry;
    u8 r1;

    // Æô¶¯Ò»´Î´«Êä
    SD_CS_ENABLE();
    //µÈ´ýSD¿¨·¢»ØÊý¾ÝÆðʼÁîÅÆ0xFE
    retry = 0;
    do
    {
      r1 = SPI_ReadWriteByte(0xFF);
      retry++;
      if(retry>2000)//2000´ÎµÈ´ýºóûÓÐÓ¦´ð£¬Í˳ö±¨´í
      {
            SD_CS_DISABLE();
            return 1;
      }
    }while(r1 != 0xFE);
    //¿ªÊ¼½ÓÊÕÊý¾Ý
    while(len--)
    {
      *data = SPI_ReadWriteByte(0xFF);
      data++;
    }
    //ÏÂÃæÊÇ2¸öαCRC£¨dummy CRC£©
    SPI_ReadWriteByte(0xFF);
    SPI_ReadWriteByte(0xFF);
    //°´ÐèÊÍ·Å×ÜÏߣ¬½«CSÖøß
    if(release == RELEASE)
    {
      //´«Êä½áÊø
      SD_CS_DISABLE();
      SPI_ReadWriteByte(0xFF);
    }

    return 0;
}


flqcandy 发表于 2014-11-4 15:15:47

Part3:
/*******************************************************************************
* Function Name: SD_GetCID
* Description    : »ñÈ¡SD¿¨µÄCIDÐÅÏ¢£¬°üÀ¨ÖÆÔìÉÌÐÅÏ¢
* Input          : u8 *cid_data(´æ·ÅCIDµÄÄڴ棬ÖÁÉÙ16Byte£©
* Output         : None
* Return         : u8
*                  0£ºNO_ERR
*                  1£ºTIME_OUT
*                  other£º´íÎóÐÅÏ¢
*******************************************************************************/
u8 SD_GetCID(u8 *cid_data)
{
    u8 r1;

    //·¢CMD10ÃüÁ¶ÁCID
    r1 = SD_SendCommand(CMD10, 0, 0xFF);
    if(r1 != 0x00)
    {
      return r1;//û·µ»ØÕýÈ·Ó¦´ð£¬ÔòÍ˳ö£¬±¨´í
    }
    //½ÓÊÕ16¸ö×Ö½ÚµÄÊý¾Ý
    SD_ReceiveData(cid_data, 16, RELEASE);

    return 0;
}


/*******************************************************************************
* Function Name: SD_GetCSD
* Description    : »ñÈ¡SD¿¨µÄCSDÐÅÏ¢£¬°üÀ¨ÈÝÁ¿ºÍËÙ¶ÈÐÅÏ¢
* Input          : u8 *cid_data(´æ·ÅCIDµÄÄڴ棬ÖÁÉÙ16Byte£©
* Output         : None
* Return         : u8
*                  0£ºNO_ERR
*                  1£ºTIME_OUT
*                  other£º´íÎóÐÅÏ¢
*******************************************************************************/
u8 SD_GetCSD(u8 *csd_data)
{
    u8 r1;

    //·¢CMD9ÃüÁ¶ÁCSD
    r1 = SD_SendCommand(CMD9, 0, 0xFF);
    if(r1 != 0x00)
    {
      return r1;//û·µ»ØÕýÈ·Ó¦´ð£¬ÔòÍ˳ö£¬±¨´í
    }
    //½ÓÊÕ16¸ö×Ö½ÚµÄÊý¾Ý
    SD_ReceiveData(csd_data, 16, RELEASE);

    return 0;
}


/*******************************************************************************
* Function Name: SD_GetCapacity
* Description    : »ñÈ¡SD¿¨µÄÈÝÁ¿
* Input          : None
* Output         : None
* Return         : u32 capacity
*                   0£º È¡ÈÝÁ¿³ö´í
*******************************************************************************/
u32 SD_GetCapacity(void)
{
    u8 csd;
    u32 Capacity;
    u8 r1;
    u16 i;
        u16 temp;

    //È¡CSDÐÅÏ¢£¬Èç¹ûÆÚ¼ä³ö´í£¬·µ»Ø0
    if(SD_GetCSD(csd)!=0)
    {
      return 0;
    }
      
    //Èç¹ûΪSDHC¿¨£¬°´ÕÕÏÂÃ淽ʽ¼ÆËã
    if((csd&0xC0)==0x40)
    {
      Capacity =(((u32)csd)<<8 + (u32)csd +1)*(u32)1024;
    }
    else
    {
      //ÏÂÃæ´úÂëΪÍøÉÏ°æ±¾
      ////////////formula of the capacity///////////////
      //
      //memory capacity = BLOCKNR * BLOCK_LEN
      //       
      //        BLOCKNR = (C_SIZE + 1)* MULT
      //
      //         C_SIZE_MULT+2
      //        MULT = 2
      //
      //               READ_BL_LEN
      //        BLOCK_LEN = 2
      /**********************************************/
      //C_SIZE
            i = csd&0x03;
            i<<=8;
            i += csd;
            i<<=2;
            i += ((csd&0xc0)>>6);
   
      //C_SIZE_MULT
            r1 = csd&0x03;
            r1<<=1;
            r1 += ((csd&0x80)>>7);
   
      //BLOCKNR
            r1+=2;
            temp = 1;
            while(r1)
            {
                    temp*=2;
                    r1--;
            }
            Capacity = ((u32)(i+1))*((u32)temp);
   
      // READ_BL_LEN
            i = csd&0x0f;
      //BLOCK_LEN
            temp = 1;
            while(i)
            {
                    temp*=2;
                    i--;
            }
      //The final result
            Capacity *= (u32)temp;
            //Capacity /= 512;
    }
    return (u32)Capacity;
}


/*******************************************************************************
* Function Name: SD_ReadSingleBlock
* Description    : ¶ÁSD¿¨µÄÒ»¸öblock
* Input          : u32 sector È¡µØÖ·£¨sectorÖµ£¬·ÇÎïÀíµØÖ·£©
*                  u8 *buffer Êý¾Ý´æ´¢µØÖ·£¨´óСÖÁÉÙ512byte£©
* Output         : None
* Return         : u8 r1
*                   0£º ³É¹¦
*                   other£ºÊ§°Ü
*******************************************************************************/
u8 SD_ReadSingleBlock(u32 sector, u8 *buffer)
{
        u8 r1;

    //ÉèÖÃΪ¸ßËÙģʽ
    SPI_SetSpeed(SPI_SPEED_LOW);
   
    //Èç¹û²»ÊÇSDHC£¬½«sectorµØַת³ÉbyteµØÖ·
    if(SD_Type!=SD_TYPE_V2HC)
    {
      sector = sector<<9;
    }

        r1 = SD_SendCommand(CMD17, sector, 0);//¶ÁÃüÁî
       
        if(r1 != 0x00)
    {
      return r1;
    }
   
    r1 = SD_ReceiveData(buffer, 512, RELEASE);
    if(r1 != 0)
    {
      return r1;   //¶ÁÊý¾Ý³ö´í£¡
    }
    else
    {
      return 0;
    }
}

/*******************************************************************************
* Function Name: SD_WriteSingleBlock
* Description    : дÈëSD¿¨µÄÒ»¸öblock
* Input          : u32 sector ÉÈÇøµØÖ·£¨sectorÖµ£¬·ÇÎïÀíµØÖ·£©
*                  u8 *buffer Êý¾Ý´æ´¢µØÖ·£¨´óСÖÁÉÙ512byte£©
* Output         : None
* Return         : u8 r1
*                   0£º ³É¹¦
*                   other£ºÊ§°Ü
*******************************************************************************/
u8 SD_WriteSingleBlock(u32 sector, const u8 *data)
{
    u8 r1;
    u16 i;
    u16 retry;


    //ÉèÖÃΪ¸ßËÙģʽ
    SPI_SetSpeed(SPI_SPEED_LOW);

    //Èç¹û²»ÊÇSDHC£¬¸ø¶¨µÄÊÇsectorµØÖ·£¬½«Æäת»»³ÉbyteµØÖ·
    if(SD_Type!=SD_TYPE_V2HC)
    {
      sector = sector<<9;
    }

    r1 = SD_SendCommand(CMD24, sector, 0x00);
    if(r1 != 0x00)
    {
      return r1;//Ó¦´ð²»ÕýÈ·£¬Ö±½Ó·µ»Ø
    }
   
    //¿ªÊ¼×¼±¸Êý¾Ý´«Êä
    SD_CS_ENABLE();
    //ÏÈ·Å3¸ö¿ÕÊý¾Ý£¬µÈ´ýSD¿¨×¼±¸ºÃ
    SPI_ReadWriteByte(0xff);
    SPI_ReadWriteByte(0xff);
    SPI_ReadWriteByte(0xff);
    //·ÅÆðʼÁîÅÆ0xFE
    SPI_ReadWriteByte(0xFE);

    //·ÅÒ»¸ösectorµÄÊý¾Ý
    for(i=0;i<512;i++)
    {
      SPI_ReadWriteByte(*data++);
    }
    //·¢2¸öByteµÄdummy CRC
    SPI_ReadWriteByte(0xff);
    SPI_ReadWriteByte(0xff);
   
    //µÈ´ýSD¿¨Ó¦´ð
    r1 = SPI_ReadWriteByte(0xff);
    if((r1&0x1F)!=0x05)
    {
      SD_CS_DISABLE();
      return r1;
    }
   
    //µÈ´ý²Ù×÷Íê³É
    retry = 0;
    while(!SPI_ReadWriteByte(0xff))
    {
      retry++;
      if(retry>0xfffe)      //Èç¹û³¤Ê±¼äдÈëûÓÐÍê³É£¬±¨´íÍ˳ö
      {
            SD_CS_DISABLE();
            return 1;         //дÈ볬ʱ·µ»Ø1
      }
    }

    //дÈëÍê³É£¬Æ¬Ñ¡ÖÃ1
    SD_CS_DISABLE();
    SPI_ReadWriteByte(0xff);

    return 0;
}


flqcandy 发表于 2014-11-4 15:16:45

由于字数限制,3部分没传完,只能补一部分啦,Part4:
/*******************************************************************************
* Function Name: SD_ReadMultiBlock
* Description    : ¶ÁSD¿¨µÄ¶à¸öblock
* Input          : u32 sector È¡µØÖ·£¨sectorÖµ£¬·ÇÎïÀíµØÖ·£©
*                  u8 *buffer Êý¾Ý´æ´¢µØÖ·£¨´óСÖÁÉÙ512byte£©
*                  u8 count Á¬Ðø¶Ácount¸öblock
* Output         : None
* Return         : u8 r1
*                   0£º ³É¹¦
*                   other£ºÊ§°Ü
*******************************************************************************/
u8 SD_ReadMultiBlock(u32 sector, u8 *buffer, u8 count)
{
    u8 r1;

    //ÉèÖÃΪ¸ßËÙģʽ
    SPI_SetSpeed(SPI_SPEED_LOW);
   
    //Èç¹û²»ÊÇSDHC£¬½«sectorµØַת³ÉbyteµØÖ·
    if(SD_Type!=SD_TYPE_V2HC)
    {
      sector = sector<<9;
    }
    //SD_WaitReady();
    //·¢¶Á¶à¿éÃüÁî
        r1 = SD_SendCommand(CMD18, sector, 0);//¶ÁÃüÁî
        if(r1 != 0x00)
    {
      return r1;
    }
    //¿ªÊ¼½ÓÊÕÊý¾Ý
    do
    {
      if(SD_ReceiveData(buffer, 512, NO_RELEASE) != 0x00)
      {
            break;
      }
      buffer += 512;
    } while(--count);

    //È«²¿´«ÊäÍê±Ï£¬·¢ËÍÍ£Ö¹ÃüÁî
    SD_SendCommand(CMD12, 0, 0);
    //ÊÍ·Å×ÜÏß
    SD_CS_DISABLE();
    SPI_ReadWriteByte(0xFF);
   
    if(count != 0)
    {
      return count;   //Èç¹ûûÓд«Í꣬·µ»ØÊ£Óà¸öÊý
    }
    else
    {
      return 0;
    }
}


/*******************************************************************************
* Function Name: SD_WriteMultiBlock
* Description    : дÈëSD¿¨µÄN¸öblock
* Input          : u32 sector ÉÈÇøµØÖ·£¨sectorÖµ£¬·ÇÎïÀíµØÖ·£©
*                  u8 *buffer Êý¾Ý´æ´¢µØÖ·£¨´óСÖÁÉÙ512byte£©
*                  u8 count дÈëµÄblockÊýÄ¿
* Output         : None
* Return         : u8 r1
*                   0£º ³É¹¦
*                   other£ºÊ§°Ü
*******************************************************************************/
u8 SD_WriteMultiBlock(u32 sector, const u8 *data, u8 count)
{
    u8 r1;
    u16 i=0;
   

    //ÉèÖÃΪ¸ßËÙģʽ
    SPI_SetSpeed(SPI_SPEED_LOW);

    //Èç¹û²»ÊÇSDHC£¬¸ø¶¨µÄÊÇsectorµØÖ·£¬½«Æäת»»³ÉbyteµØÖ·
    if(SD_Type != SD_TYPE_V2HC)
    {
      sector = sector<<9;
    }
    //Èç¹ûÄ¿±ê¿¨²»ÊÇMMC¿¨£¬ÆôÓÃACMD23Ö¸ÁîʹÄÜÔ¤²Á³ý
    if(SD_Type != SD_TYPE_MMC)
    {
      r1 = SD_SendCommand(ACMD23, count, 0x00);
    }
    //·¢¶à¿éдÈëÖ¸Áî
    r1 = SD_SendCommand(CMD25, sector, 0x00);
    if(r1 != 0x00)
    {
      return r1;//Ó¦´ð²»ÕýÈ·£¬Ö±½Ó·µ»Ø
    }
   
    //¿ªÊ¼×¼±¸Êý¾Ý´«Êä
    SD_CS_ENABLE();
    //ÏÈ·Å3¸ö¿ÕÊý¾Ý£¬µÈ´ýSD¿¨×¼±¸ºÃ
    SPI_ReadWriteByte(0xff);
    SPI_ReadWriteByte(0xff);

    //--------ÏÂÃæÊÇN¸ösectorдÈëµÄÑ­»·²¿·Ö
    do
    {
      //·ÅÆðʼÁîÅÆ0xFC ±íÃ÷ÊǶà¿éдÈë
      SPI_ReadWriteByte(0xFC);
   
      //·ÅÒ»¸ösectorµÄÊý¾Ý
      for(i=0;i<512;i++)
      {
            SPI_ReadWriteByte(*data++);
      }
      //·¢2¸öByteµÄdummy CRC
      SPI_ReadWriteByte(0xff);
      SPI_ReadWriteByte(0xff);
      
      //µÈ´ýSD¿¨Ó¦´ð
      r1 = SPI_ReadWriteByte(0xff);
      if((r1&0x1F)!=0x05)
      {
            SD_CS_DISABLE();    //Èç¹ûÓ¦´ðΪ±¨´í£¬Ôò´ø´íÎó´úÂëÖ±½ÓÍ˳ö
            return r1;
      }

      //µÈ´ýSD¿¨Ð´ÈëÍê³É
      if(SD_WaitReady()==1)
      {
            SD_CS_DISABLE();    //µÈ´ýSD¿¨Ð´ÈëÍê³É³¬Ê±£¬Ö±½ÓÍ˳ö±¨´í
            return 1;
      }

      //±¾sectorÊý¾Ý´«ÊäÍê³É
    }while(--count);
   
    //·¢½áÊø´«ÊäÁîÅÆ0xFD
    r1 = SPI_ReadWriteByte(0xFD);
    if(r1==0x00)
    {
      count =0xfe;
    }

    if(SD_WaitReady())
    {
      while(1)
      {
      }
    }
   
    //дÈëÍê³É£¬Æ¬Ñ¡ÖÃ1
    SD_CS_DISABLE();
    SPI_ReadWriteByte(0xff);

    return count;   //·µ»ØcountÖµ£¬Èç¹ûдÍêÔòcount=0£¬·ñÔòcount=1
}

zqyycl 发表于 2015-10-28 16:52:14

LZ您好,我现在也遇到了您同样的问题,请问您解决了吗?

zqyycl 发表于 2015-10-28 16:52:30

在线等您的答案

不良苏 发表于 2018-12-15 14:17:33

我也遇到了求大神赐教

★↣Rese♧rve 发表于 2018-12-15 23:41:17

解决了吗?

kepma 发表于 2020-2-13 21:26:30

请问解决了嘛?

freefishmj 发表于 2021-3-1 13:29:20


请问解决了嘛?
页: [1]
查看完整版本: 基于STM32Cube移植FatFs文件系统,f_Open返回FR_NOT_READY?