2017-10-31 34 views
0

私はSPIを使用してSTM32L152-DISCOVERYボード(STM32L152RCT6 ARM Cortex-M3)でmicroSDカードをインターフェースしようとしています。最終的な目標は、Decade PCでも読み取ることができるSDカードにセンサデータを保存するためにFatFshttp://elm-chan.org/fsw/ff/00index_e.html)を使用することです。 Chanのウェブサイトには、初期化プロセス(http://elm-chan.org/docs/mmc/im/sdinit.png)を説明する非常に有用なフローチャートがあります。SPIモードでのmicroSDカードの初期化。 ACMD41は常に0x01を返す

残念ながら、私のコードでは、SDCardの初期化を妨げる問題があります。具体的には、コマンドACMD41(CMD55 + CMD41)を送信すると、SDカードは常に0x01を返します。

私は何度もスタックオーバーフロー、特にSDHC microSD card and SPI initializationのポストに続いてコードを修正しましたが、それでも問題は解決しません。続き

は私のシステムのHWとSWのセットアップです:

ハードウェアのセットアップ

  • マイクロSDカードは、インターフェースUHS-I、容量16ギガバイト
  • SDカードアダプターが接続されていディスカバリーボードのSPI2ポート
  • MISO、MOSI、CLKピンについては、プルアップ抵抗をイネーブルにしました。 mcuのデータシートによると、内部プルアップ抵抗は約45Kohmになるはずです。
  • microSDカードの電源は、5Vピンを使用してarduinoボードから供給されています(私は狂ったように聞こえるかもしれませんが、私は今は他の電源を持っていません。 arduinoのGND、ディスカバリーGND、SDカードアダプターのGNDはすべてギアに接続されています。

ソフトウェアセットアップ - SPI初期化SPI周波数が最初に125キロヘルツとの間に設定されている

は、( - 400 kHzの私はそれが範囲100キロヘルツでなければなりません読みました)。

/* 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_LOW; 
    hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; 
    hspi2.Init.NSS = SPI_NSS_SOFT; 
    hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; 
    hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; 
    hspi2.Init.TIMode = SPI_TIMODE_DISABLE; 
    hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; 
    hspi2.Init.CRCPolynomial = 10; 
    if (HAL_SPI_Init(&hspi2) != HAL_OK) 
    { 
    _Error_Handler(__FILE__, __LINE__); 
    } 

} 

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle) 
{ 

    GPIO_InitTypeDef GPIO_InitStruct; 
    if(spiHandle->Instance==SPI2) 
    { 
    /* SPI2 clock enable */ 
    __HAL_RCC_SPI2_CLK_ENABLE(); 

    /**SPI2 GPIO Configuration  
    PB13  ------> SPI2_SCK 
    PB14  ------> SPI2_MISO 
    PB15  ------> SPI2_MOSI 
    */ 
    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; 
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 
    GPIO_InitStruct.Pull = GPIO_PULLUP; 
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; 
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; 
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); 
    } 
} 

ソフトウェアのセットアップ - SDCARDの初期化

#include <string.h> 
#include "ff_gen_drv.h" 

#define CS_HIGH() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET); 
#define CS_LOW() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12,GPIO_PIN_RESET); 

#define DEFAULT_TIMEOUT 10 

uint8_t dummy_clocks[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; 

/* Definitions for MMC/SDC command */ 
#define CMD0  (0)  /* GO_IDLE_STATE */ 
#define CMD1  (1)  /* SEND_OP_COND (MMC) */ 
#define ACMD41 (41) /* SEND_OP_COND (SDC) */ 
#define CMD8  (8)  /* SEND_IF_COND */ 
#define CMD9  (9)  /* SEND_CSD */ 
#define CMD10  (10) /* SEND_CID */ 
#define CMD12  (12) /* STOP_TRANSMISSION */ 
#define ACMD13 (13) /* SD_STATUS (SDC) */ 
#define CMD16  (16) /* SET_BLOCKLEN */ 
#define CMD17  (17) /* READ_SINGLE_BLOCK */ 
#define CMD18  (18) /* READ_MULTIPLE_BLOCK */ 
#define CMD23  (23) /* SET_BLOCK_COUNT (MMC) */ 
#define ACMD23 (23) /* SET_WR_BLK_ERASE_COUNT (SDC) */ 
#define CMD24  (24) /* WRITE_BLOCK */ 
#define CMD25  (25) /* WRITE_MULTIPLE_BLOCK */ 
#define CMD55  (55) /* APP_CMD */ 
#define CMD58  (58) /* READ_OCR */ 

static volatile DSTATUS Stat = STA_NOINIT; 
extern SPI_HandleTypeDef hspi2; 

DSTATUS USER_initialize (BYTE pdrv); 
DSTATUS USER_status (BYTE pdrv); 
DRESULT USER_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count); 
#if _USE_WRITE == 1 
DRESULT USER_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count); 
#endif /* _USE_WRITE == 1 */ 
#if _USE_IOCTL == 1 
DRESULT USER_ioctl (BYTE pdrv, BYTE cmd, void *buff); 
#endif /* _USE_IOCTL == 1 */ 

Diskio_drvTypeDef USER_Driver = 
{ 
    USER_initialize, 
    USER_status, 
    USER_read, 
    #if _USE_WRITE 
    USER_write, 
    #endif /* _USE_WRITE == 1 */ 
    #if _USE_IOCTL == 1 
    USER_ioctl, 
    #endif /* _USE_IOCTL == 1 */ 
}; 

void spi_init(void); 
uint8_t send_cmd(BYTE cmd, DWORD arg); 

DSTATUS USER_initialize (BYTE pdrv) 
{ 
    /* USER CODE BEGIN INIT */ 
    Stat = STA_NOINIT; 

    enum initialization_state 
    { 
    SD_POWER_CYCLE = 0, 
    SD_SEND_CMD0, 
    SD_WAIT_CMD0_ANSWER, 
    SD_SEND_CMD8, 
    SD_SEND_CMD55, 
    SD_SEND_ACMD41, 
    SD_SEND_CMD1, 
    SD_SEND_CMD58, 
    SD_SEND_CMD16, 
    SD_SUCCESS, 
    SD_ERROR, 
    } init_phase; 

    uint8_t response = 0x00; 
    DWORD arg = 0; 
    init_phase = SD_POWER_CYCLE; 

    spi_init(); 

    while(init_phase < SD_SUCCESS) 
    { 
    switch(init_phase) 
    { 
     case SD_POWER_CYCLE: 
     // Wait 1 ms 
     HAL_Delay(1); 
     HAL_SPI_Transmit(&hspi2, dummy_clocks, sizeof(dummy_clocks), 10); 
     init_phase = SD_SEND_CMD0; 
     break; 

     case SD_SEND_CMD0: 
     CS_LOW(); 
     response = send_cmd(CMD0,arg); 
     if(response == 0x01) 
      init_phase = SD_SEND_CMD8; 
     else 
      init_phase = SD_ERROR; 
     break; 

     case SD_SEND_CMD8: 
     arg = 0x000001AA; 
     response = send_cmd(CMD8,arg); 
     if(response == 0x01) 
      init_phase = SD_SEND_CMD55; 
     else 
      init_phase = SD_ERROR; 
     break; 

     case SD_SEND_CMD55: 
     arg = 0x00000000; 
     response = send_cmd(CMD55,arg); 
     if(response == 0x01) 
      init_phase = SD_SEND_ACMD41; 
     else 
      init_phase = SD_ERROR; 
     break; 

     case SD_SEND_ACMD41: 
     arg = 0x40000000; 
     response = send_cmd(ACMD41,arg); 
     if(response == 0x00) 
      init_phase = SD_SEND_CMD58; 
     else 
     { 
      // HAL_Delay(1000); 
      init_phase = SD_SEND_CMD55; 
     } 
     break; 

     case SD_SEND_CMD58: 
     arg = 0x00000000; 
     response = send_cmd(CMD58,arg); 
     break; 

     case SD_ERROR: 
     CS_HIGH(); 
     Stat = STA_NODISK; 
     break; 

     default: 
     // Something went wrong - Try to re-init 
     init_phase = SD_POWER_CYCLE; 
     spi_init(); 
     break; 

    } 
    } 

    return Stat; 
    /* USER CODE END INIT */ 
} 

... 
... 

void spi_init(void) 
{ 
    CS_HIGH(); 
    HAL_Delay(10); 
} 

uint8_t send_cmd(BYTE cmd, DWORD arg) 
{ 
    // cmd packet is of fixed lenght 
    uint8_t cmd_packet[6] = {0}; 

    // Response 
    uint8_t cmd_response = 0xFF; 
    // R1 is 1 byte only and it is used for most commands 
    uint8_t r1 = 0xFF; 
    // Commands R3 and R7 are 5 bytes long, (R1 + trailing 32-bit data) 
    uint8_t r3_7[5] = {0}; 

    // First byte is the command 
    // The cmd_packet must start with 01, therefore we add 0x40 to the cmd byte 
    cmd_packet[0] = 0x40 | cmd; 

    // Four bytes for the argument 
    for(uint8_t i = 1; i<=4; i++) 
    cmd_packet[i] = (uint8_t)(arg >> (4-i)*8); 

    // Add crc: it must be correct for CMD0 and CMD 8 only; for other commands, we use a dummy crc (0x01) 
    if(cmd == CMD0) 
    cmd_packet[5] = 0x95; 
    else if(cmd == CMD8) 
    cmd_packet[5] = 0x87; 
    else if(cmd == ACMD41) 
    cmd_packet[5] = 0x95; 
    else 
    cmd_packet[5] = 0x01; 

    // Send the command 
    HAL_SPI_Transmit(&hspi2, cmd_packet, sizeof(cmd_packet), DEFAULT_TIMEOUT); 

    // Receive the answer from SDcard 

    switch(cmd) 
    { 
    case CMD0: 
     // Try 3 times to get the answer 
     for(uint8_t j = 0; j<3; j++) 
     { 
     HAL_SPI_Transmit(&hspi2, (uint8_t*)&cmd_response, sizeof(cmd_response), DEFAULT_TIMEOUT); 
     HAL_SPI_Receive(&hspi2,&r1,sizeof(r1),DEFAULT_TIMEOUT); 
     if(r1 != 0xFF) 
      return r1; 
     } 
    break; 

    case CMD8: 
     HAL_SPI_Transmit(&hspi2, (uint8_t*)&cmd_response, sizeof(cmd_response), DEFAULT_TIMEOUT); 
     HAL_SPI_Receive(&hspi2,r3_7,sizeof(r3_7),DEFAULT_TIMEOUT); 
     if(r3_7[3] == 0x01 && r3_7[4] == 0xAA) 
     return 0x01; 
    break; 

    case CMD55: 
     HAL_SPI_Transmit(&hspi2, (uint8_t*)&cmd_response, sizeof(cmd_response), DEFAULT_TIMEOUT); 
     HAL_SPI_Receive(&hspi2,&r1,sizeof(r1),DEFAULT_TIMEOUT); 
     if(r1 != 0xFF) 
     return r1; 
    break; 

    case ACMD41:   
     for(int i = 0; i<150; i++) 
     { 
     HAL_SPI_Transmit(&hspi2, (uint8_t*)&cmd_response, sizeof(cmd_response), DEFAULT_TIMEOUT); 
     HAL_SPI_Receive(&hspi2,&r1,sizeof(r1),DEFAULT_TIMEOUT); 
     if(r1 == 0x00) 
      return r1; 
     else 
      HAL_Delay(10); 
     } 
     return 0xFF; 
    break; 

    case CMD58: 
     HAL_SPI_Transmit(&hspi2, (uint8_t*)&cmd_response, sizeof(cmd_response), DEFAULT_TIMEOUT); 
     HAL_SPI_Receive(&hspi2,r3_7,sizeof(r3_7),DEFAULT_TIMEOUT); 
     if(r3_7[1] & (1<<7)) 
     return 0x01; 
     else 
     return 0x00; 
     break; 
    } 
} 

答えて

1

私は同じ問題を抱えています。私はSDHCカードとSTM32F107VCボードとのインターフェースをとった。そして私はFatFsの使用に成功した。 実は、私はそれは、私もmircoSDをインターフェイスさ...そして働いていたにも成功し、このproblem.Iについての手がかりは、この(连接)デュポンLine.LikeとSDモジュールと付属のSDを使用してforwent

を見つけることはありません。

マイコード:

SD_SPI_Mode.c

#include <stdio.h> 
#include "SD_SPI_Mode.h" 
#include "hdware.h" 

SD_INFO G_SDCARD_INFO; 

SDErrorType SDInit(void) 
{ 
    u16 Response1; 
    u16 Buff[6] = {0}; 
    u16 Retry; 

    SPI_SetSpeed(SPI_BaudRatePrescaler_256); 

    for (Retry = 0; Retry < 10; Retry++) //至少74个时钟的高电平 
    { 
     SPI_ReadWriteByte2(DUMMY_BYTE); 
    } 
    Retry = 0; 
    sdEnable(); 
    for (Retry = 0; Retry < 0xFFF; Retry++) 
    { 
     Response1 = SDSendCommand(CMD0, 0, 0x95); 
     if (Response1 == 0x01) 
     { 
      Retry = 0; 
      break; 
     } 
    } 

    if (Retry == 0xFFF) 
    { 
     //printf("Reset card into IDLE state failed!\r\n"); 
     return ERROR_NOT_IN_IDLE; 
    } 

    Response1 = SDSendCommandHold(CMD8, 0x1AA, 0x87); 

    if (Response1 == 0x05) 
    { 
     G_SDCARD_INFO.CardType = CARDTYPE_SDV1; 
     sdDisable(); 
     //SPI_ReadWriteByte2(DUMMY_BYTE); 

     for (Retry = 0; Retry < 0xFFF; Retry++) 
     { 
      Response1 = SDSendCommand(CMD55, 0, 0); 
      if (Response1 != 0x01) 
      { 
       return ERROR_CMD55; 
      } 
      Response1 = SDSendCommand(ACMD41, 0, 0); 
      if (Response1 == 0x00) 
      { 
       Retry = 0; 
       break; 
      } 
     } 

     if (Retry == 0xFFF) 
     { 
      for (Retry = 0; Retry < 0xFFF; Retry++) 
      { 
       Response1 = SDSendCommand(CMD1, 0, 0); /* should be return 0x00 */ 
       if (Response1 == 0x00) 
       { 
        Retry = 0; 
        break; 
       } 
      } 
      if (Retry == 0xFFF) 
      { 
       return ERROR_CMD1; 
      } 
      G_SDCARD_INFO.CardType = CARDTYPE_MMC; 
      //printf("Card Type: MMC\r\n"); 
     } 
     else 
     { 
      G_SDCARD_INFO.CardType = CARDTYPE_SDV1; 
      //printf("Card Type: SD V1\r\n"); 
     } 

      Response1 = SDSendCommand(CMD16, BLOCKSIZE, 0xFF); 

      if (Response1 != 0x00) 
      { 
       return ERROR_CMD16; 
      } 
    } 
    else if (Response1 == 0x01) 
    { 
     Buff[0] = SPI_ReadWriteByte2(DUMMY_BYTE); //0x00 
     Buff[1] = SPI_ReadWriteByte2(DUMMY_BYTE); //0x00 
     Buff[2] = SPI_ReadWriteByte2(DUMMY_BYTE); //0x01 
     Buff[3] = SPI_ReadWriteByte2(DUMMY_BYTE); //0xAA 

     sdDisable(); 

     if (Buff[2] == 0x01 && Buff[3] == 0xAA) //检查电压范围 
     { 
      for (Retry = 0; Retry < 0xFFF; Retry++) 
      { 
       Response1 = SDSendCommand(CMD55, 0, 0x01); 
       sdEnable(); 
       Response1 = SPI_ReadWriteByte2(DUMMY_BYTE); 
       sdDisable(); 

       Response1 = SDSendCommand(ACMD41, 0x40FF8000, 0xFF); 
       if (Response1 == 0x00) 
       { 
        Retry = 0; 
        break; 
       } 
      } 
      if (Retry == 0xFFF) 
      { 
       return ERROR_ACMD41; 
      } 
       Response1 = SDSendCommandHold(CMD58, 0, 0); 
      if (Response1 != 0x00) 
      { 
       return ERROR_CMD58; 
      } 

      Buff[0] = SPI_ReadWriteByte2(DUMMY_BYTE); 
      Buff[1] = SPI_ReadWriteByte2(DUMMY_BYTE); 
      Buff[2] = SPI_ReadWriteByte2(DUMMY_BYTE); 
      Buff[3] = SPI_ReadWriteByte2(DUMMY_BYTE); 

      sdDisable(); 

      if (Buff[0] & 0x40) // OCR -> CCS(bit30) 1: SDV2HC 0: SDV2 
      { 
       G_SDCARD_INFO.CardType = CARDTYPE_SDV2HC; 
       //printf("Card Type: SD V2HC\r\n"); 
      } 
      else 
      { 
       G_SDCARD_INFO.CardType = CARDTYPE_SDV2; 
       //printf("Card Type: SD V2\r\n"); 
      } 
     } 
    } 
    SPI_SetSpeed(SPI_BaudRatePrescaler_2); 
    return ERROR_NOP; 
} 

SDErrorType getCardInfo(SD_INFO *G_SDCARD_INFO) 
{ 
    u8 CSD_Tab[16]; 
    u8 CID_Tab[16]; 

    if (SDSendCommand(CMD9, 0, 0x01)) //读CSD 
    { 
     return ERROR_CMD9; 
    } 

    sdEnable(); 
    if (SDReadToBuffer(CSD_Tab, 16, RELEASE)) 
    { 
     return ERROR_CSD_READ; 
    } 
    sdDisable(); 

    if (SDSendCommand(CMD10, 0, 0xFF)) //读CID 
    { 
     return ERROR_CMD10; 
    } 

    sdEnable(); 
    if (SDReadToBuffer(CID_Tab, 16, RELEASE)) 
    { 
     return ERROR_CID_READ; 
    } 
    sdDisable(); 

    /* Byte 0 */ 
    G_SDCARD_INFO->CSD.CSDStruct = (CSD_Tab[0] & 0xC0) >> 6; 
    G_SDCARD_INFO->CSD.SysSpecVersion = (CSD_Tab[0] & 0x3C) >> 2; 
    G_SDCARD_INFO->CSD.Reserved1 = CSD_Tab[0] & 0x03; 
    /* Byte 1 */ 
    G_SDCARD_INFO->CSD.TAAC = CSD_Tab[1]; 
    /* Byte 2 */ 
    G_SDCARD_INFO->CSD.NSAC = CSD_Tab[2]; 
    /* Byte 3 */ 
    G_SDCARD_INFO->CSD.MaxBusClkFrec = CSD_Tab[3]; 
    /* Byte 4 */ 
    G_SDCARD_INFO->CSD.CardComdClasses = CSD_Tab[4] << 4; 
    /* Byte 5 */ 
    G_SDCARD_INFO->CSD.CardComdClasses |= (CSD_Tab[5] & 0xF0) >> 4; 
    G_SDCARD_INFO->CSD.RdBlockLen = CSD_Tab[5] & 0x0F; 
    /* Byte 6 */ 
    G_SDCARD_INFO->CSD.PartBlockRead = (CSD_Tab[6] & 0x80) >> 7; 
    G_SDCARD_INFO->CSD.WrBlockMisalign = (CSD_Tab[6] & 0x40) >> 6; 
    G_SDCARD_INFO->CSD.RdBlockMisalign = (CSD_Tab[6] & 0x20) >> 5; 
    G_SDCARD_INFO->CSD.DSRImpl = (CSD_Tab[6] & 0x10) >> 4; 
    G_SDCARD_INFO->CSD.Reserved2 = 0; /* Reserved */ 
    G_SDCARD_INFO->CSD.DeviceSize = (CSD_Tab[6] & 0x03) << 10; 
    /* Byte 7 */ 
    G_SDCARD_INFO->CSD.DeviceSize |= (CSD_Tab[7]) << 2; 
    /* Byte 8 */ 
    G_SDCARD_INFO->CSD.DeviceSize |= (CSD_Tab[8] & 0xC0) >> 6; 
    G_SDCARD_INFO->CSD.MaxRdCurrentVDDMin = (CSD_Tab[8] & 0x38) >> 3; 
    G_SDCARD_INFO->CSD.MaxRdCurrentVDDMax = (CSD_Tab[8] & 0x07); 
    /* Byte 9 */ 
    G_SDCARD_INFO->CSD.MaxWrCurrentVDDMin = (CSD_Tab[9] & 0xE0) >> 5; 
    G_SDCARD_INFO->CSD.MaxWrCurrentVDDMax = (CSD_Tab[9] & 0x1C) >> 2; 
    G_SDCARD_INFO->CSD.DeviceSizeMul = (CSD_Tab[9] & 0x03) << 1; 
    /* Byte 10 */ 
    G_SDCARD_INFO->CSD.DeviceSizeMul |= (CSD_Tab[10] & 0x80) >> 7; 
    G_SDCARD_INFO->CSD.EraseGrSize = (CSD_Tab[10] & 0x7C) >> 2; 
    G_SDCARD_INFO->CSD.EraseGrMul = (CSD_Tab[10] & 0x03) << 3; 
    /* Byte 11 */ 
    G_SDCARD_INFO->CSD.EraseGrMul |= (CSD_Tab[11] & 0xE0) >> 5; 
    G_SDCARD_INFO->CSD.WrProtectGrSize = (CSD_Tab[11] & 0x1F); 
    /* Byte 12 */ 
    G_SDCARD_INFO->CSD.WrProtectGrEnable = (CSD_Tab[12] & 0x80) >> 7; 
    G_SDCARD_INFO->CSD.ManDeflECC = (CSD_Tab[12] & 0x60) >> 5; 
    G_SDCARD_INFO->CSD.WrSpeedFact = (CSD_Tab[12] & 0x1C) >> 2; 
    G_SDCARD_INFO->CSD.MaxWrBlockLen = (CSD_Tab[12] & 0x03) << 2; 
    /* Byte 13 */ 
    G_SDCARD_INFO->CSD.MaxWrBlockLen |= (CSD_Tab[13] & 0xc0) >> 6; 
    G_SDCARD_INFO->CSD.WriteBlockPaPartial = (CSD_Tab[13] & 0x20) >> 5; 
    G_SDCARD_INFO->CSD.Reserved3 = 0; 
    G_SDCARD_INFO->CSD.ContentProtectAppli = (CSD_Tab[13] & 0x01); 
    /* Byte 14 */ 
    G_SDCARD_INFO->CSD.FileFormatGrouop = (CSD_Tab[14] & 0x80) >> 7; 
    G_SDCARD_INFO->CSD.CopyFlag = (CSD_Tab[14] & 0x40) >> 6; 
    G_SDCARD_INFO->CSD.PermWrProtect = (CSD_Tab[14] & 0x20) >> 5; 
    G_SDCARD_INFO->CSD.TempWrProtect = (CSD_Tab[14] & 0x10) >> 4; 
    G_SDCARD_INFO->CSD.FileFormat = (CSD_Tab[14] & 0x0C) >> 2; 
    G_SDCARD_INFO->CSD.ECC = (CSD_Tab[14] & 0x03); 
    /* Byte 15 */ 
    G_SDCARD_INFO->CSD.CSD_CRC = (CSD_Tab[15] & 0xFE) >> 1; 
    G_SDCARD_INFO->CSD.Reserved4 = 1; 

    if (G_SDCARD_INFO->CardType == CARDTYPE_SDV2HC) 
    { 
     /* Byte 7 */ 
     G_SDCARD_INFO->CSD.DeviceSize = (u16)(CSD_Tab[8]) * 256; 
     /* Byte 8 */ 
     G_SDCARD_INFO->CSD.DeviceSize += CSD_Tab[9]; 
    } 

    G_SDCARD_INFO->Capacity = G_SDCARD_INFO->CSD.DeviceSize * BLOCKSIZE * 1024; 
    G_SDCARD_INFO->BlockSize = BLOCKSIZE; 

    /* Byte 0 */ 
    G_SDCARD_INFO->CID.ManufacturerID = CID_Tab[0]; 
    /* Byte 1 */ 
    G_SDCARD_INFO->CID.OEM_AppliID = CID_Tab[1] << 8; 
    /* Byte 2 */ 
    G_SDCARD_INFO->CID.OEM_AppliID |= CID_Tab[2]; 
    /* Byte 3 */ 
    G_SDCARD_INFO->CID.ProdName1 = CID_Tab[3] << 24; 
    /* Byte 4 */ 
    G_SDCARD_INFO->CID.ProdName1 |= CID_Tab[4] << 16; 
    /* Byte 5 */ 
    G_SDCARD_INFO->CID.ProdName1 |= CID_Tab[5] << 8; 
    /* Byte 6 */ 
    G_SDCARD_INFO->CID.ProdName1 |= CID_Tab[6]; 
    /* Byte 7 */ 
    G_SDCARD_INFO->CID.ProdName2 = CID_Tab[7]; 
    /* Byte 8 */ 
    G_SDCARD_INFO->CID.ProdRev = CID_Tab[8]; 
    /* Byte 9 */ 
    G_SDCARD_INFO->CID.ProdSN = CID_Tab[9] << 24; 
    /* Byte 10 */ 
    G_SDCARD_INFO->CID.ProdSN |= CID_Tab[10] << 16; 
    /* Byte 11 */ 
    G_SDCARD_INFO->CID.ProdSN |= CID_Tab[11] << 8; 
    /* Byte 12 */ 
    G_SDCARD_INFO->CID.ProdSN |= CID_Tab[12]; 
    /* Byte 13 */ 
    G_SDCARD_INFO->CID.Reserved1 |= (CID_Tab[13] & 0xF0) >> 4; 
    /* Byte 14 */ 
    G_SDCARD_INFO->CID.ManufactDate = (CID_Tab[13] & 0x0F) << 8; 
    /* Byte 15 */ 
    G_SDCARD_INFO->CID.ManufactDate |= CID_Tab[14]; 
    /* Byte 16 */ 
    G_SDCARD_INFO->CID.CID_CRC = (CID_Tab[15] & 0xFE) >> 1; 
    G_SDCARD_INFO->CID.Reserved2 = 1; 

    return ERROR_NOP; 
} 

SDErrorType SDReadToBuffer(u8 *buff, u16 len, u8 release) 
{ 
    u16 Response1; 
    u16 Retry; 

    //Start Block 
    for (Retry = 0; Retry < 2000; Retry++) 
    { 
     Response1 = SPI_ReadWriteByte2(DUMMY_BYTE); 
     if (Response1 == 0xFE) 
     { 
      Retry = 0; 
      break; 
     } 
    } 
    //Time out 
    if (Retry == 2000) 
    { 
     return ERROR_TIME_OUT; 
    } 

    //Start Read 
    for (Retry = 0; Retry < len; Retry++) 
    { 
     *(buff + Retry) = SPI_ReadWriteByte2(DUMMY_BYTE); 
    } 

    //CRC 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 

    if (release) 
    { 
     sdDisable();   
     SPI_ReadWriteByte2(DUMMY_BYTE); 
    } 

    return ERROR_NOP; 
} 

SDErrorType SDReadSingleBlock(u32 sector, u8 *Buffer) 
{ 
    if (G_SDCARD_INFO.CardType != CARDTYPE_SDV2HC) 
    { 
     sector = sector << 9; 
    } 
    if (SDSendCommand(CMD17, sector, 0x55)) 
    { 
     return ERROR_CMD17; 
    } 

    sdEnable(); 

    if (SDReadToBuffer(Buffer, BLOCKSIZE, RELEASE)) 
    { 
     return ERROR_DATA_READ; 
    } 
    sdDisable(); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 

    return ERROR_NOP; 
} 

SDErrorType SDReadMultiBlock(u32 sector, u8 *Buffer, u32 NumOfSector) 
{ 
    u32 i; 

    if (G_SDCARD_INFO.CardType != CARDTYPE_SDV2HC) 
    { 
     sector = sector << 9; 
    } 

    if (SDSendCommand(CMD18, sector, 0)) 
    { 
     return ERROR_CMD18; 
    } 

    sdEnable(); 

    for (i = 0; i < NumOfSector; i++) 
    { 
     if (SDReadToBuffer(Buffer + i * BLOCKSIZE, BLOCKSIZE, HOLD)) 
     { 
      SDSendCommand(CMD12, 0, 0); 
      sdDisable(); 
      return ERROR_DATA_READ; 
     } 
    } 

    SDSendCommand(CMD12, 0, 0); //停止位 

    sdDisable(); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    return ERROR_NOP; 
} 

SDErrorType SDWriteFromBuffer(u8 *buffer, bool isMultiply) 
{ 
    u16 Response1; 
    u16 i; 
    if (!isMultiply) 
    { 
     SPI_ReadWriteByte2(0xFE); 
    } 
    else if (isMultiply) 
    { 
     SPI_ReadWriteByte2(0xFC); 
    } 

    for (i = 0; i < BLOCKSIZE; i++) 
    { 
     SPI_ReadWriteByte2(*buffer++); 
    } 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 

    Response1 = SPI_ReadWriteByte2(DUMMY_BYTE); 

    if ((Response1 & 0x1F) != 0x05) 
    { 
     return ERROR_DATA_WRITE; 
    } 

    return ERROR_NOP; 
} 

SDErrorType SDWriteSingleBlock(u32 sector, u8 *buffer) 
{ 
    if (G_SDCARD_INFO.CardType != CARDTYPE_SDV2HC) 
    { 
     sector = sector << 9; 
    } 

    if (SDSendCommand(CMD24, sector, 0)) 
    { 
     return ERROR_CMD24; 
    } 
    sdEnable(); 

    SPI_ReadWriteByte2(DUMMY_BYTE); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 

    SDWriteFromBuffer(buffer, false); 

    if(SDBusyWait()) 
    { 
     sdDisable(); 
     return ERROR_DATA_WRITE; 
    } 

    sdDisable(); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    return ERROR_NOP; 
} 

SDErrorType SDWriteMultiBlock(u32 sector, u8 *Buffer, u32 NumOfSector) 
{ 
    u32 n; 

    if (G_SDCARD_INFO.CardType != CARDTYPE_SDV2HC) 
    { 
     sector = sector << 9; 
    } 

    if (G_SDCARD_INFO.CardType != CARDTYPE_MMC) 
    { 
     SDSendCommand(ACMD23, NumOfSector, 0x00); 
    } 

    if (SDSendCommand(CMD25, sector, 0)) 
    { 
     return ERROR_CMD25; 
    } 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 

    sdEnable(); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 

    SPI_ReadWriteByte2(DUMMY_BYTE); 

    for (n = 0; n < NumOfSector; n++) 
    { 
     SDWriteFromBuffer(Buffer, true); 
    } 

    if (SPI_ReadWriteByte2(0xFD)) 
    { 
     return ERROR_DATA_WRITE; 
    } 

    if(SDBusyWait()) 
    { 
     sdDisable(); 
     return ERROR_DATA_WRITE; 
    } 

    sdDisable(); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    return ERROR_NOP; 
} 

SDErrorType SDBusyWait(void) 
{ 
    u32 Retry = 0; 
    while (SPI_ReadWriteByte2(DUMMY_BYTE) == 0x00) 
    { 
     /* Timeout return */ 
     if (Retry++ == 0x40000) 
     { 
      return ERROR_TIME_OUT; 
     } 
    } 
    return ERROR_NOP; 
} 

u16 SDSendCommand(u8 cmd, u32 arg, u8 crc) 
{ 
    u16 Response1; 
    u16 Retry; 

    SPI_ReadWriteByte2(DUMMY_BYTE); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 

    sdEnable(); 

    SPI_ReadWriteByte2(cmd | 0x40); 
    SPI_ReadWriteByte2(arg >> 24); 
    SPI_ReadWriteByte2(arg >> 16); 
    SPI_ReadWriteByte2(arg >> 8); 
    SPI_ReadWriteByte2(arg); 
    SPI_ReadWriteByte2(crc | 1); 

    //Busy 
    for (Retry = 0; Retry < 200; Retry++) 
    { 
     Response1 = SPI_ReadWriteByte2(DUMMY_BYTE); 
     if (Response1 != 0xFF) 
     { 
      break; 
     } 
    } 
    sdDisable(); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 

    return Response1; 
} 

u16 SDSendCommandHold(u8 cmd, u32 arg, u8 crc) 
{ 
    u16 Response1; 
    u16 Retry; 

    SPI_ReadWriteByte2(DUMMY_BYTE); 
    SPI_ReadWriteByte2(DUMMY_BYTE); 
    sdEnable(); 

    SPI_ReadWriteByte2(cmd | 0x40); 
    SPI_ReadWriteByte2(arg >> 24); 
    SPI_ReadWriteByte2(arg >> 16); 
    SPI_ReadWriteByte2(arg >> 8); 
    SPI_ReadWriteByte2(arg); 
    SPI_ReadWriteByte2(crc); 

    //Busy 
    for (Retry = 0; Retry < 200; Retry++) 
    { 
     Response1 = SPI_ReadWriteByte2(DUMMY_BYTE); 
     if (Response1 != 0xFF) 
     { 
      break; 
     } 
    } 

    return Response1; 
} 

SD_SPI_Mode。時間

#ifndef _SD_SPI_MODE_H_ 
#define _SD_SPI_MODE_H_ 
/* Includes ------------------------------------------------------------------*/ 
#include "DIDO.h" 

/* Private define ------------------------------------------------------------*/ 
#define CARDTYPE_MMC 0x00 
#define CARDTYPE_SDV1 0x01 
#define CARDTYPE_SDV2 0x02 
#define CARDTYPE_SDV2HC 0x04 

#define DUMMY_BYTE 0xFF 
#define BLOCKSIZE 512 

/* SD/MMC command list - SPI mode */ 
#define CMD0 0 /* Reset */ 
#define CMD1 1 /* Send Operator Condition - SEND_OP_COND */ 
#define CMD8 8 /* Send Interface Condition - SEND_IF_COND */ 
#define CMD9 9 /* Read CSD */ 
#define CMD10 10 /* Read CID */ 
#define CMD12 12 /* Stop data transmit */ 
#define CMD16 16 /* Set block size, should return 0x00 */ 
#define CMD17 17 /* Read single block */ 
#define CMD18 18 /* Read multi block */ 
#define ACMD23 23 /* Prepare erase N-blokcs before multi block write */ 
#define CMD24 24 /* Write single block */ 
#define CMD25 25 /* Write multi block */ 
#define ACMD41 41 /* should return 0x00 */ 
#define CMD55 55 /* should return 0x01 */ 
#define CMD58 58 /* Read OCR */ 
#define CMD59 59 /* CRC disable/enbale, should return 0x00 */ 

#define sdEnable() GPIO_ResetBits(SD_CS_PORT, SD_CS_PIN) 
#define sdDisable() GPIO_SetBits(SD_CS_PORT, SD_CS_PIN) 
#define MSD0_card_power_on() ; 
#define isCardInsert() 0 

enum _CD_HOLD 
{ 
    HOLD = 0, 
    RELEASE = 1, 
}; 

typedef enum  
{ 
    ERROR_NOP = 0, 
    ERROR_NOT_IN_IDLE, 
    ERROR_TIME_OUT, 
    ERROR_CSD_READ, 
    ERROR_CID_READ, 
    ERROR_DATA_READ, 
    ERROR_DATA_WRITE, 
    ERROR_ACMD41, 
    ERROR_CMD1, 
    ERROR_CMD9, 
    ERROR_CMD10, 
    ERROR_CMD16, 
    ERROR_CMD17, 
    ERROR_CMD18, 
    ERROR_CMD24, 
    ERROR_CMD25, 
    ERROR_CMD55, 
    ERROR_CMD58, 
    ERROR_CMD59, 
} SDErrorType; 

typedef struct /* Card Specific Data */ 
{ 
    vu8 CSDStruct;   /* CSD structure */ 
    vu8 SysSpecVersion;  /* System specification version */ 
    vu8 Reserved1;   /* Reserved */ 
    vu8 TAAC;    /* Data read access-time 1 */ 
    vu8 NSAC;    /* Data read access-time 2 in CLK cycles */ 
    vu8 MaxBusClkFrec;  /* Max. bus clock frequency */ 
    vu16 CardComdClasses; /* Card command classes */ 
    vu8 RdBlockLen;   /* Max. read data block length */ 
    vu8 PartBlockRead;  /* Partial blocks for read allowed */ 
    vu8 WrBlockMisalign;  /* Write block misalignment */ 
    vu8 RdBlockMisalign;  /* Read block misalignment */ 
    vu8 DSRImpl;    /* DSR implemented */ 
    vu8 Reserved2;   /* Reserved */ 
    vu32 DeviceSize;   /* Device Size */ 
    vu8 MaxRdCurrentVDDMin; /* Max. read current @ VDD min */ 
    vu8 MaxRdCurrentVDDMax; /* Max. read current @ VDD max */ 
    vu8 MaxWrCurrentVDDMin; /* Max. write current @ VDD min */ 
    vu8 MaxWrCurrentVDDMax; /* Max. write current @ VDD max */ 
    vu8 DeviceSizeMul;  /* Device size multiplier */ 
    vu8 EraseGrSize;   /* Erase group size */ 
    vu8 EraseGrMul;   /* Erase group size multiplier */ 
    vu8 WrProtectGrSize;  /* Write protect group size */ 
    vu8 WrProtectGrEnable; /* Write protect group enable */ 
    vu8 ManDeflECC;   /* Manufacturer default ECC */ 
    vu8 WrSpeedFact;   /* Write speed factor */ 
    vu8 MaxWrBlockLen;  /* Max. write data block length */ 
    vu8 WriteBlockPaPartial; /* Partial blocks for write allowed */ 
    vu8 Reserved3;   /* Reserded */ 
    vu8 ContentProtectAppli; /* Content protection application */ 
    vu8 FileFormatGrouop; /* File format group */ 
    vu8 CopyFlag;   /* Copy flag (OTP) */ 
    vu8 PermWrProtect;  /* Permanent write protection */ 
    vu8 TempWrProtect;  /* Temporary write protection */ 
    vu8 FileFormat;   /* File Format */ 
    vu8 ECC;     /* ECC code */ 
    vu8 CSD_CRC;    /* CSD CRC */ 
    vu8 Reserved4;   /* always 1*/ 
} MSD_CSD; 

typedef struct /*Card Identification Data*/ 
{ 
    vu8 ManufacturerID; /* ManufacturerID */ 
    vu16 OEM_AppliID; /* OEM/Application ID */ 
    vu32 ProdName1;  /* Product Name part1 */ 
    vu8 ProdName2;  /* Product Name part2*/ 
    vu8 ProdRev;  /* Product Revision */ 
    vu32 ProdSN;  /* Product Serial Number */ 
    vu8 Reserved1;  /* Reserved1 */ 
    vu16 ManufactDate; /* Manufacturing Date */ 
    vu8 CID_CRC;  /* CID CRC */ 
    vu8 Reserved2;  /* always 1 */ 
} MSD_CID; 

typedef struct 
{ 
    MSD_CSD CSD; 
    MSD_CID CID; 
    u32 Capacity; /* Card Capacity */ 
    u32 BlockSize; /* Card Block Size */ 
    u16 RCA; 
    u8 CardType; 
    u32 SpaceTotal; /* Total space size in file system */ 
    u32 SpaceFree; /* Free space size in file system */ 
} SD_INFO; 

extern SD_INFO G_SDCARD_INFO; 

SDErrorType SDInit(void); 
SDErrorType getCardInfo(SD_INFO *G_SDCARD_INFO); 
SDErrorType SDReadSingleBlock(u32 sector, u8 *buffer); 
SDErrorType SDReadMultiBlock(u32 sector, u8 *buffer, u32 NumOfSector); 
SDErrorType SDWriteSingleBlock(u32 sector, u8 *buffer); 
SDErrorType SDWriteMultiBlock(u32 sector, u8 *buffer, u32 NumOfSector); 

static SDErrorType SDWriteFromBuffer(u8 *buffer,bool isMultiply); 
static u16 SDSendCommand(u8 cmd, u32 arg, u8 crc); 
static u16 SDSendCommandHold(u8 cmd, u32 arg, u8 crc); 
static SDErrorType SDReadToBuffer(u8 *buff, u16 len, u8 release); 
static SDErrorType SDBusyWait(void); 
#endif 

Additionly、私のファイル操作コード:

FileOperation.c

#include "stdlib.h" 
#include <stdbool.h> 
#include "string.h" 
#include "FileOperation.h" 


static FATFS Fs;   //逻辑磁盘工作区. 
static FIL File;   //文件 
static FILINFO FileInfo; //文件信息 
static DIR Dir;  //目录 
static u8 SDBuf;   //SD缓存 

FRESULT SDMount(u8 device) 
{ 
    return f_mount(device, &Fs); 
} 

FRESULT SDCreateDir(const u8 *pname) 
{ 
    return f_mkdir((const TCHAR *)pname); 
} 

FRESULT SDDirOpen(const u8 *path) 
{ 
    return f_opendir(&Dir, (const TCHAR *)path); 
} 

FRESULT SDDirRead(void) 
{ 
    FRESULT res; 
    char *FileName; 
    FileInfo.lfsize = _MAX_LFN * 2 + 1; 
    FileInfo.lfname = malloc(FileInfo.lfsize); 
    res = f_readdir(&Dir, &FileInfo); //读取一个文件的信息 
    if (res != FR_OK || FileInfo.fname[0] == 0) 
    { 
     free((void *)FileInfo.lfname); 
     return res; //读完了. 
    } 
    FileName = *(FileInfo.lfname) ? FileInfo.lfname : FileInfo.fname; 
    free((void *)FileInfo.lfname); 
    return FR_OK; 
} 

FRESULT SDFileRead(u8 *buf, u16 len) 
{ 
    u16 i; 
    FRESULT res; 
    UINT ByteCount; 
    for (i = 0; i < len/512; i++) 
    { 
     res = f_read(&File, buf, 512, &ByteCount); 
     if (res) 
     { 
      break; 
     } 
    } 
    if (len % 512) 
    { 
     res = f_read(&File, buf, len % 512, &ByteCount); 
    } 
    return res; 
} 

TCHAR *SDReadString(u16 size) 
{ 
    TCHAR *rbuf; 
    rbuf = f_gets((TCHAR *)&SDBuf, size, &File); 
    if (*rbuf == 0) 
     return NULL; //没有数据读到 
    else 
    { 
     return rbuf; 
    } 
} 

FRESULT SDFileWrite(const u8 *data, u16 len) 
{ 
    UINT ByteCount; 
    return f_write(&File, data, len, &ByteCount); 
} 

FRESULT SDScanFiles(const u8 *path, char **FileName) 
{ 
    FRESULT res; 
    u16 FileNum = 0; 
    FileInfo.lfsize = _MAX_LFN * 2 + 1; 
    FileInfo.lfname = malloc(FileInfo.lfsize); 

    res = f_opendir(&Dir, (const TCHAR *)path); //打开一个目录 
    if (res == FR_OK) 
    { 
     while (1) 
     { 
      res = f_readdir(&Dir, &FileInfo); //读取目录下的一个文件 
      if (res != FR_OK || FileInfo.fname[0] == 0) 
       break; //错误了/到末尾了,退出 
      FileName[FileNum] = *FileInfo.lfname ? FileInfo.lfname :  FileInfo.fname; 
      FileNum++; 
     } 
    } 
    free(FileInfo.lfname); 
    return res; 
} 

FRESULT SDShowFree(const u8 *drv, u32 *FreeSector, u32 *TotalSector) 
{ 
    FATFS *fs1; 
    FRESULT res; 
    u32 FreeClust = 0; 
    res = f_getfree((const TCHAR *)drv, (DWORD *)&FreeClust, &fs1); 
    if (res == FR_OK) 
    { 
     *TotalSector = (fs1->n_fatent - 2) * fs1->csize; //总扇区数 
     *FreeSector = FreeClust * fs1->csize;   //空闲扇区数 
     (*TotalSector) >>= 11; 
     (*FreeSector) >>= 11; 
    } 
    return res; 
} 

FRESULT SDFormat(u8 device, u8 mode, u16 au) 
{ 
    return f_mkfs(device, mode, au); //格式化,drv:盘符;mode:模式;au:簇大小 
} 

FRESULT SDRemoveFileOrDir(const u8 *pname) 
{ 
    return f_unlink((const TCHAR *)pname); 
} 

FRESULT SDRename(const u8 *oldname, const u8 *newname) 
{ 
    return f_rename((const TCHAR *)oldname, (const TCHAR *)newname); 
} 

FRESULT SDFileOpen(const u8 *path, u8 mode) 
{ 
    return f_open(&File, (const TCHAR *)path, mode); 
} 

FRESULT SDFileClose(void) 
{ 
    return f_close(&File); 
} 

u32 SDFileSize(void) 
{ 
    return f_size(&File); 
} 

FRESULT SDArgumentRead(const u8 *path, ArgumentInfo *argument, UINT *RecordNum) 
{ 
    FRESULT res; 
    u8 *PointToBuff; 
    UINT ByteCount; 

    res = SDFileOpen(path, FA_READ); 
    if (res != FR_OK) 
     return res; 

    PointToBuff = malloc(File.fsize); 

    res = f_read(&File, PointToBuff, File.fsize, &ByteCount); 
    if (res != FR_OK) 
    { 
     return res; 
    } 

    SDDataSolve(PointToBuff, argument, ByteCount, RecordNum); 

    free(PointToBuff); 

    return SDFileClose(); 
} 

FRESULT SDFileAppend(const u8 *path, const u8 *filename, const u8 *buff) 
{ 
    FRESULT res; 
    u16 len = strlen((const char*)buff); 
    u8 *FullPath; 

    res = SDCreateDir(path); 
    FullPath = malloc(strlen((const char*)path) + strlen((const char*)filename) + 2); 

    SDComplatePath(path, filename, FullPath); 

    res = SDFileOpen(FullPath, FA_OPEN_EXISTING | FA_WRITE); 

    if (res == FR_NO_FILE) 
     res = SDFileOpen(FullPath, FA_CREATE_ALWAYS | FA_WRITE); 

    if (res != FR_OK) 
     return res; 

    free(FullPath); 

    SDLseek(File.fsize); 
    res = SDFileWrite(buff, len); 

    if (res != FR_OK) 
     return res; 

    return SDFileClose(); 
} 

float stringToFloat(u8 *InputString) 
{ 
    return atof((const char*)(InputString)); 
} 

int stringToInt(u8 *InputString) 
{ 
    return atoi((const char*)(InputString)); 
} 

FRESULT SDLseek(u32 offset) 
{ 
    return f_lseek(&File, offset); 
} 

void SDDataSolve(u8 *buff, ArgumentInfo *argument, UINT ByteCount, UINT *RecordNum) 
{ 
    u8 col = 0; 
    UINT fileRow = 0, CharNum = 0; 
    u8 *CorChar = buff; 
    bool isValueRegion = false; 

    while (CharNum != ByteCount) 
    { 
     if (*CorChar == '=') 
     { 
      isValueRegion = true; 
      argument[fileRow].key[col] = '\0'; 
      col = 0; 
     } 
     else if (*CorChar == '\r' && *(CorChar + 1) == '\n') 
     { 
      CorChar++; 
      argument[fileRow].value[col] = '\0'; 
      isValueRegion = false; 
      col = 0; 
      fileRow++; 
     } 
     else 
     { 
      if (isValueRegion) 
      { 
       argument[fileRow].value[col] = *CorChar; 
      } 
      else 
      { 
       argument[fileRow].key[col] = *CorChar; 
      } 
      col++; 
     } 
     CorChar++; 
     CharNum++; 
    } 
    *RecordNum = CharNum; 
} 

void SDComplatePath(const u8 *Path,const u8 *FileName, u8 *FullPath) 
{ 
    u8 TempPath = '/'; 

    strcpy((char*)FullPath, (const char*)Path); 
    strcat((char*)FullPath, (const char*)&TempPath); 
    strcat((char*)FullPath, (const char*)FileName); 

} 

test.Mayが役に立つことだけのために...私の下手な英語のための

申し訳ありませんが、それはです私の母国語ではありません。

+0

ありがとうございます。私は間違いなくそれを試みます。外部プルアップ抵抗または内部プルアップ抵抗を使用しましたか?外部で使用する場合、どのような値ですか?どのライン? MISOのみ、またはMOSIですか? – Alek

+0

47k外部プルアップ抵抗、MISOのみ。 – user8873052

+0

あなたのCPHAとCPOLが私と違うことがわかりました。 \t \t SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; \t SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; – user8873052

関連する問題