2017-02-02 3 views
0

Ich verwende STM32F4-Entwicklungskarte mit einem STM32F407-Chip. Um mit der SD-Karte zu kommunizieren, verwende ich SPI1 und verwende die von Chan erstellte FatFs-Bibliothek.Kann nicht auf SD-Kartendatei mit SPI schreiben mit Chan FatFs-Bibliothek auf einem STM32F407

Also der Kern des Problems ist, dass es mir gelungen ist, eine Datei auf der SD-Karte zu erstellen, kann ich daraus lesen. Aber wenn ich versuche, in die Datei zu schreiben, verdirbt es entweder die Datei oder druckt solche Daten wie "{46040EDD-C". Wenn ich mir das Gedächtnis ansehe, kann ich sehen, was ich geschrieben habe, aber irgendwie wird es an die falsche Adresse geschrieben.

Ein anderes Problem, das ich habe ist, dass das erste Mal, dass ich eine Datei erstellen und versuche, mit f_write zu schreiben, ich bekomme die Antwort FR_DISK_ERR. Der Fehler tritt bei dem Versuch auf, eine Cluster-Kette zu erstellen, wenn ich durch den Code gehe, funktioniert es gut. Es könnte also eine Verspätung fehlen. Das nächste Mal, wenn ich das Programm starte, funktioniert es, und f_write gibt FR_OK zurück.

Ich bin nicht sicher, ob diese Probleme zusammenhängen oder nicht. Ich habe versucht, dies für etwa zwei Wochen zur Arbeit zu bringen und würde jede Hilfe, die ich bekommen kann, lieben. Vielen Dank.

Der Code:

main.c

int main(void) 
{ 
    int i; 

    //SD CARD INIT 

    //Fatfs object 
    FATFS FatFs; 
    //File object 
    FIL fil; 
    UINT fa; 

    FRESULT res_mount, res_open, res_seek, res_write; 

    delay(10ms); 
    res_mount = f_mount(&FatFs, "", 1); 
    if (res_mount == FR_OK) { 
     GPIO_ToggleBits(GPIOD, GPIO_Pin_12); 
     delay(10ms); 
     res_open = f_open(&fil, "test.txt", FA_OPEN_ALWAYS | FA_READ | FA_WRITE); 
     if (res_open == FR_OK) { 
      GPIO_ToggleBits(GPIOD, GPIO_Pin_13); 
      delay(10ms); 
      res_seek = f_lseek(&fil, f_size(&fil)); 
      if(res_seek == FR_OK) 
      { 
       delay(10ms); 
       GPIO_ToggleBits(GPIOD, GPIO_Pin_14); 
       res_write = f_write(&fil, "Alpha Beta\n", 11, &fa); 
       if (fa > 0 && res_write == FR_OK) { 
        GPIO_ToggleBits(GPIOD, GPIO_Pin_15); 
        f_sync(&fil); 
       } 
      } 
      f_close(&fil); 
     } 
     f_mount(0, "", 1); 
    } 

    while(1); 

    //SD CARD INIT END 
} 

Chans diskio.c Datei, die ich bearbeitet haben.

#include "diskio.h"  /* FatFs lower layer API */ 

/* Definitions of physical drive number for each drive */ 
#define DEV_RAM  0 /* Example: Map Ramdisk to physical drive 0 */ 
#define DEV_MMC  1 /* Example: Map MMC/SD card to physical drive 1 */ 
#define DEV_USB  2 /* Example: Map USB MSD to physical drive 2 */ 

static volatile DSTATUS Stat = STA_NOINIT; /* Disk status */ 

static BYTE CardType; /* Card type flags (b0:MMC, b1:SDv1, b2:SDv2, b3:Block addressing) */ 



/*-----------------------------------------------------------------------*/ 
/* Get Drive Status              */ 
/*-----------------------------------------------------------------------*/ 

DSTATUS disk_status (
    BYTE pdrv  /* Physical drive nmuber to identify the drive */ 
) 
{ 
    if(pdrv) 
     return STA_NOINIT;  // Supports only drive 0 

    return Stat; 
} 



/*-----------------------------------------------------------------------*/ 
/* Inidialize a Drive             */ 
/*-----------------------------------------------------------------------*/ 

DSTATUS disk_initialize (
    BYTE pdrv    /* Physical drive nmuber to identify the drive */ 
) 
{ 
    if (Stat & STA_NODISK) 
     return Stat; /* No card in the socket? */ 

    //SLOW 

    uint8_t ty = 0; 
    ty = SD_CARD_InitialiseCard(); 

    CardType = ty; 

    if(ty) 
     Stat &= ~STA_NOINIT; 

    return Stat; 
} 



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

DRESULT disk_read (
    BYTE pdrv,  /* Physical drive nmuber to identify the drive */ 
    BYTE *buff,  /* Data buffer to store read data */ 
    DWORD sector, /* Start sector in LBA */ 
    UINT count  /* Number of sectors to read */ 
) 
{ 
    //DRESULT res; 
    //int result; 
    if(pdrv || !count) 
     return RES_PARERR; 
    if (Stat & STA_NOINIT) 
     return RES_NOTRDY; 

    if(!(CardType & SDCARD_BLOCK)) 
     sector *= 512; 

    if(count == 1) 
    { 
     if((SD_CARD_Cmd(READ_SINGLE_BLOCK, sector) == 0x00) && SD_CARD_Read(buff, 512)) 
      count = 0; 
    } 
    else 
    { 
     if(SD_CARD_Cmd(READ_MULTIPLE_BLOCKS, sector) == 0) 
     { 
      do 
      { 
       if(!SD_CARD_Read(buff, 512)) 
        break; 
       buff += 512; 
      } 
      while(--count); 
      SD_CARD_Cmd(STOP_TRANSMISSION, 0); 
     } 
    } 

    return count ? RES_ERROR : RES_OK; 
} 



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

DRESULT disk_write (
    BYTE pdrv,   /* Physical drive nmuber to identify the drive */ 
    const BYTE *buff, /* Data to be written */ 
    DWORD sector,  /* Start sector in LBA */ 
    UINT count   /* Number of sectors to write */ 
) 
{ 
    //DRESULT res; 
    //int result; 

    if (pdrv || !count) 
     return RES_PARERR; 
    if (Stat & STA_NOINIT) 
     return RES_NOTRDY; 
    if (Stat & STA_PROTECT) 
     return RES_WRPRT; 

    if(!(CardType & SDCARD_BLOCK)) 
     sector *= 512; 

    if(count == 1) 
    { 
     if((SD_CARD_Cmd(WRITE_SINGLE_BLOCK, sector) == 0x00) && SD_CARD_Write(buff, 0xFE)) 
      count = 0; 
    } 
    else 
    { 
     if (CardType & SDCARD_SDC) 
      SD_CARD_Cmd(SET_WR_BLOCK_ERASE_COUNT, count); 

     if(SD_CARD_Cmd(WRITE_MULTIPLE_BLOCKS, sector) == 0) 
     { 
      do 
      { 
       if(!SD_CARD_Write(buff, 0xFC)) 
        break; 

       buff += 512; 
      } 
      while(--count); 

      if (!SD_CARD_Write(0, 0xFD)) /* STOP_TRAN token */ 
       count = 1; 
     } 
    } 

    return count ? RES_ERROR : RES_OK; 
} 



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

DRESULT disk_ioctl (
    BYTE pdrv,  /* Physical drive nmuber (0..) */ 
    BYTE cmd,  /* Control code */ 
    void *buff  /* Buffer to send/receive control data */ 
) 
{ 
    //DRESULT res; 
    //int result; 

    //NOT NEEDED AT THE MOMENT 

    return RES_PARERR; 
} 

DWORD get_fattime (void) 
{ 
    /* Pack date and time into a DWORD variable */ 
    return ((DWORD)(2017 - 1980) << 25) 
      | ((DWORD)1 << 21) 
      | ((DWORD)1 << 16) 
      | ((DWORD)0 << 11) 
      | ((DWORD)0 << 5) 
      | ((DWORD)0 >> 1); 
} 

SD_CARD.c:

#include "SD_CARD.h" 

/* 
SPI1(GPIOA): - Type: - SD CARD: 
Pin4   - CS  - Pin2 
Pin5   - SCLK - Pin5 
Pin6   - MISO - Pin7 
Pin7   - MOSI - Pin3 
*/ 
uint8_t SD_CARD_InitialiseCard() 
{ 
    INT i = 0; 

    SPI1ENABLE(); 

    ChipSelect(SPI1, HIGH); 
    for(i = 0;i < 16;i++) 
     SPI_Send(SPI1, 0xFF); 

    for(i = 0;i < 0xFFFF;i++); 

    while(SD_CARD_Cmd(GO_IDLE_STATE, 0) != R1_IDLE_STATE); //CMD0 

    uint32_t r = SD_CARD_Cmd(SEND_IF_COND, 0x1AA); //CMD8 
    if(r == 0x1AA) 
     return SD_CARD_InitialiseCardV2(); 
    else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) 
     return SD_CARD_InitialiseCardV1(); 
    else 
     return SDCARD_FAIL; 
} 

uint8_t SD_CARD_WriteRead(INT arg) 
{ 
    SPI_Send(SPI1, arg); 
    uint8_t test = SPI_Read(SPI1); 
    return test; 
} 

uint8_t SD_CARD_InitialiseCardV1() 
{ 
    uint8_t cmd; 
    INT i = 0; 

    if(SD_CARD_Cmd(SD_SEND_OP_COND, 0x40040000) <= 1) //ACMD41 - set to 3V, use 0x40200000 for 3V3 
     cmd = SD_SEND_OP_COND; 
    else 
     cmd = SEND_OP_COND; 

    for(i = 0; i < SD_COMMAND_TIMEOUT;i++) 
    { 
     if(SD_CARD_Cmd(cmd, 0) == 0) //CMD1 or ACMD41 
     { 
      // Set block length to 512 (CMD16) 
      if(SD_CARD_Cmd(SET_BLOCKLEN, 512) != 0) //CMD16 
       return SDCARD_FAIL; 

      //Init: SEDCARD_V1 
      if(cmd == SD_SEND_OP_COND) 
       return SDCARD_V1; 
      else 
       return SDCARD_MMCV3; 
     } 
    } 

    //Timeout waiting for v1.x card 
    return SDCARD_FAIL; 
} 

uint8_t SD_CARD_InitialiseCardV2() 
{ 
    INT i = 0; 
    INT j = 0; 

    for(i = 0;i < SD_COMMAND_TIMEOUT;i++) 
    { 
     for(j = 0;j < 0xFF;j++); 
     if(SD_CARD_Cmd(SD_SEND_OP_COND, 0x40040000) == 0) //ACMD41 - set to 3V, use 0x40200000 for 3V3 
     { 
      uint32_t ocr = SD_CARD_Cmd(READ_OCR, 0); //CMD58 
      return (ocr & 0x40000000) ? SDCARD_V2 | SDCARD_BLOCK : SDCARD_V2; 
     } 
    } 

    //Timed out waiting for v2.x card 
    return SDCARD_FAIL; 
} 

uint32_t SD_CARD_Cmd(INT cmd, INT arg) 
{ 
    struct command_fields com; 
    com.start_bit = 0; 
    com.transmitter_bit = 1; 
    com.index = cmd; 
    com.argument = arg; 
    if(cmd == GO_IDLE_STATE) 
     com.crc = 0x4A; 
    else if(cmd == SEND_IF_COND) 
     com.crc = 0x43; 
    else 
     com.crc = 0x7F; 
    com.end_bit = 1; 

    if(cmd == SD_STATUS | cmd == SET_WR_BLOCK_ERASE_COUNT | cmd == SD_SEND_OP_COND) //ACMDx 
     SD_CARD_Cmd(APP_CMD, 0); //CMD55 

    SD_CARD_WriteCom(&com); 

    if(cmd == SEND_IF_COND) 
     return SD_CARD_RecieveR7(); 
    else if(cmd == READ_OCR) 
     return SD_CARD_RecieveR3(); 
    else 
     return SD_CARD_RecieveR1(); 
} 

void SD_CARD_WriteCom(struct command_fields *com) 
{ 

    ChipSelect(SPI1, LOW); 
    SPI_Send(SPI1, 0xFF); 
    SPI_Send(SPI1, (0xFF & ((com->start_bit << 7) | (com->transmitter_bit << 6) | com->index))); 
    SPI_Send(SPI1, (0xFF & (com->argument >> 24))); 
    SPI_Send(SPI1, (0xFF & (com->argument >> 16))); 
    SPI_Send(SPI1, (0xFF & (com->argument >> 8))); 
    SPI_Send(SPI1, (0xFF & com->argument)); 
    SPI_Send(SPI1, (0xFF & ((com->crc << 1) | com->end_bit))); 
} 

INT SD_CARD_Write(const BYTE *buffer, BYTE token) 
{ 
    INT i = 0; 
    ChipSelect(SPI1, LOW); 

    while(SD_CARD_WriteRead(0xFF) != 0xFF); 

    // indicate start of block 
    SPI_Send(SPI1, token); 

    if(token != 0xFD) 
    { 
     // write the data 
     for(i = 0;i < 512;i++) 
     { 
      SPI_Send(SPI1, *buffer); 
      buffer++; 
     } 

     // write the checksum 
     SPI_Send(SPI1, 0xFF); 
     SPI_Send(SPI1, 0xFF); 

     // check the repsonse token 
     if(((SD_CARD_WriteRead(0xFF)) & 0x1F) != 0x05) 
     { 
      ChipSelect(SPI1, HIGH); 
      SPI_Send(SPI1, 0xFF); 
      return SUCCESS; 
     } 
    } 

    // wait for write to finish 
    while(SD_CARD_WriteRead(0xFF) != 0xFF); 

    ChipSelect(SPI1, HIGH); 
    SPI_Send(SPI1, 0xFF); 
    return ERROR; 
} 

INT SD_CARD_Read(BYTE *buffer, INT length) 
{ 
    INT i = 0; 
    ChipSelect(SPI1, LOW); 

    for(i = 0; i < SD_COMMAND_TIMEOUT;i++) 
    { 
     // read until start byte (0xFF) 
     if(SD_CARD_WriteRead(0xFF) == 0xFE) 
     { 
      // read data 
      for(i = 0;i < length;i++) 
       buffer[i] = SD_CARD_WriteRead(0xFF); 

      SPI_Send(SPI1, 0xFF); // checksum 
      SPI_Send(SPI1, 0xFF); 

      ChipSelect(SPI1, HIGH); 
      SPI_Send(SPI1, 0xFF); 
      return SUCCESS; 
     } 
    } 

    return ERROR; 
} 

uint8_t SD_CARD_RecieveR1() 
{ 
    INT i; 
    uint8_t response = 0xFF; 
    for(i = 0;i < SD_COMMAND_TIMEOUT;i++) 
    { 
     response = SD_CARD_WriteRead(0xFF); 
     if((response == 0x00) || (response == 0x01)) 
     { 
      ChipSelect(SPI1, HIGH); 
      SPI_Send(SPI1, 0xFF); 
      return response; 
     } 
    } 
    ChipSelect(SPI1, HIGH); 
    SPI_Send(SPI1, 0xFF); 
    return 0xFF; 
} 

uint32_t SD_CARD_RecieveR7() 
{ 
    INT i = 0, j = 0; 
    for(i = 0;i < (SD_COMMAND_TIMEOUT * 1000);i++) 
    { 
     uint8_t response[5]; 
     response[0] = SD_CARD_WriteRead(0xFF); 
     if(!(response[0] & 0x80)) 
     { 
       for(j = 1;j < 5;j++) 
       { 
        response[j] = SD_CARD_WriteRead(0xFF); 
       } 
       ChipSelect(SPI1, HIGH); 
       SPI_Send(SPI1, 0xFF); 
       return ((response[1] << 24) | (response[2] << 16) | (response[3] << 8) | response[4]); 
     } 
    } 
    ChipSelect(SPI1, HIGH); 
    SPI_Send(SPI1, 0xFF); 
    return 0xFFFFFFFF; // timeout 
} 

uint32_t SD_CARD_RecieveR3() 
{ 
    uint32_t ocr = 0; 
    INT response; 
    for(int i=0; i < SD_COMMAND_TIMEOUT; i++) 
    { 
     response = SD_CARD_WriteRead(0xFF); 
     if(!(response & 0x80)) 
     { 
      ocr = SD_CARD_WriteRead(0xFF) << 24; 
      ocr |= SD_CARD_WriteRead(0xFF) << 16; 
      ocr |= SD_CARD_WriteRead(0xFF) << 8; 
      ocr |= SD_CARD_WriteRead(0xFF); 
      ChipSelect(SPI1, HIGH); 
      SPI_Send(SPI1, 0xFF); 
      return ocr; 
     } 
    } 
    ChipSelect(SPI1, HIGH); 
    SPI_Send(SPI1, 0xFF); 
    return 0xFFFFFFFF; // timeout 
} 

INT SD_CARD_InitialiseDisk() 
{ 
    if(SD_CARD_InitialiseCard() == SDCARD_FAIL) 
     return SDCARD_FAIL; 

    SPI_SetSpeed(SPI1, SPI_SPEED_1300KHz); 
    return SUCCESS; 
} 

SPI.c:

#include "SPI.h" 

void SPI1ENABLE() 
{ 
    GPIO_InitTypeDef GPIO_InitStruct; 
    SPI_InitTypeDef SPI_InitStruct; 
    static uint8_t SPI1_ENABLED = 0; 
    if(SPI1_ENABLED) 
     return; 

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); 

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); 
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); 
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); 

    GPIO_InitStruct.GPIO_Pin = SPI1_SCLK | SPI1_MISO | SPI1_MOSI; 
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; 
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; 
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; 
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL; 
    GPIO_Init(GPIOA, &GPIO_InitStruct); 

    GPIO_InitStruct.GPIO_Pin = SPI1_CS; 
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; 
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN; 
    GPIO_Init(GPIOA, &GPIO_InitStruct); 

    SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 
    SPI_InitStruct.SPI_Mode = SPI_Mode_Master; 
    SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; 
    SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; 
    SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; 
    SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; 
    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; 
    SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB; 
    SPI_Init(SPI1, &SPI_InitStruct); 

    SPI_Cmd(SPI1, ENABLE); 

    SPI1_ENABLED = 1; 
} 

uint8_t SPI_Read(SPI_TypeDef* SPIx) 
{ 
    while(SPI1->SR & SPI_I2S_FLAG_BSY);   // wait until SPI is not busy anymore 
    while(!(SPI1->SR & SPI_I2S_FLAG_RXNE)); // wait until receive complete 
    return SPI_ReceiveData(SPIx); 
} 

void SPI_Send(SPI_TypeDef* SPIx, unsigned char Data) 
{ 
    while(SPI1->SR & SPI_I2S_FLAG_BSY);   // wait until SPI is not busy anymore 
    while(!(SPI1->SR & SPI_I2S_FLAG_TXE)); // wait until transmit complete 
    SPI_SendData(SPIx, Data); 
    while(!(SPI1->SR & SPI_I2S_FLAG_RXNE)); // wait until receive complete 
} 
+1

Ich denke, es ist besser, dass Sie in http://electronics.stackexchange.com/ Ihre Frage senden –

+0

Danke tun! – AlphaBetaWhisky

Antwort

0

So fand ich mein Problem heraus. So blöd wie ich bin, habe ich in meiner Schreibfunktion vergessen, Erfolg beim Senden von STOP_TRANs Token zurückzugeben. So sieht die Schreibfunktion nach der Bearbeitung aus.

INT SD_CARD_Write(const BYTE *buffer, BYTE token) 
{ 
    INT i = 0; 
    ChipSelect(SPI1, LOW); 

    while(SD_CARD_WriteRead(0xFF) != 0xFF); 

    // indicate start of block 
    SPI_Send(SPI1, token); 

    if(token != 0xFD) 
    { 
     // write the data 
     for(i = 0;i < 512;i++) 
     { 
      SPI_Send(SPI1, *buffer); 
      buffer++; 
     } 

     // write the checksum 
     SPI_Send(SPI1, 0xFF); 
     SPI_Send(SPI1, 0xFF); 

     // check the repsonse token 
     uint8_t resp = 0x00; 
     do 
     { 
      resp = SD_CARD_WriteRead(0xFF); 
     } 
     while(resp == 0x00); 

     if((resp & 0x1F) != 0x05) 
     { 
      // wait for write to finish 
      while(SD_CARD_WriteRead(0xFF) != 0xFF); 

      SPI_Send(SPI1, 0xFF); 
      ChipSelect(SPI1, HIGH); 
      SPI_Send(SPI1, 0xFF); 

      return SUCCESS; 
     } 
    } 

    // wait for write to finish 
    while(SD_CARD_WriteRead(0xFF) != 0xFF); 

    SPI_Send(SPI1, 0xFF); 
    ChipSelect(SPI1, HIGH); 
    SPI_Send(SPI1, 0xFF); 

    if(token == 0xFD) 
     return SUCCESS; 

    return ERROR; 
} 
Verwandte Themen