无法使用STM32F407上的Chan FatFs库使用SPI写入SD卡文件

时间:2017-02-02 14:14:59

标签: c sd-card fat32 stm32f4

我正在使用带有STM32F407芯片的STM32F4开发板。为了与SD卡通信,我使用SPI1,并使用由Chan创建的FatFs库。

问题的关键在于我已成功设法在SD卡上创建文件,我能够从中读取。但是当我尝试写入文件时,它会破坏文件或打印像这样的垃圾数据" {46040EDD-C"。如果我看看memmory,我可以看到我写的东西,但不知怎的,它被写入错误的memmory地址。

我遇到的另一个问题是,第一次创建文件并尝试使用f_write写入文件时,我得到了回复FR_DISK_ERR。这个错误来自于尝试创建一个集群链,当我通过代码它运行正常时。所以可能会有一些延迟缺失。下次运行程序时,它可以工作,f_write返回FR_OK。

我不确定这些问题是否相关。我一直试图让它工作大约两个星期,并且会喜欢我能得到的任何帮助。谢谢。

代码:

的main.c

=Switch(Fields!Date.Value >= CDate("01/05/" & Str(Year(Parameters!StartDate.Value))) and Fields!Date.Value <= CDate("01/10/" & Str(Year(Parameters!EndDate.Value))) and
 count(lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime"))>= "8"
and lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime") = "100%",
"Green",
Fields!Date.Value >= CDate("01/11/" & Str(Year(Parameters!StartDate.Value))) and Fields!Date.Value <= CDate("30/04/" & Str(Year(Parameters!EndDate.Value))) and
count(lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime"))>= "4"
and lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime") = "100%",
"Green",
Fields!Date.Value >= CDate("01/05/" & Str(Year(Parameters!StartDate.Value))) and Fields!Date.Value <= CDate("01/10/" & Str(Year(Parameters!EndDate.Value))) and
count(lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value,Fields!SINFO.Value, "FullTime"))>= "6"
and lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime") = "75%",
"Green",
Fields!Date.Value >= CDate("01/11/" & Str(Year(Parameters!StartDate.Value))) and Fields!Date.Value <= CDate("30/04/" & Str(Year(Parameters!EndDate.Value))) and
count(lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime"))>= "3"
and lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime") = "75%",
"Green",

 Fields!Date.Value >= CDate("01/05/" & Str(Year(Parameters!StartDate.Value))) and Fields!Date.Value <= CDate("01/10/" & Str(Year(Parameters!EndDate.Value))) and
count(lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime"))>= "4"
and lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime") = "50%" ,
"Green",
Fields!Date.Value >= CDate("01/11/" & Str(Year(Parameters!StartDate.Value))) and Fields!Date.Value <= CDate("30/04/" & Str(Year(Parameters!EndDate.Value))) and
count(lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime"))>= "2"
and lookup(Fields!Assessors_Staff_ID.Value,Fields!EMPNO.Value, Fields!SINFO.Value, "FullTime") = "50%",
"Green",
true,"Red"
 )

我编辑的Chans diskio.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
}

SD_CARD.c:

#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);
}

SPI.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;
}

1 个答案:

答案 0 :(得分:0)

所以我发现了我的问题。像我一样愚蠢,在我的写函数中,我忘记在发送STOP_TRANs令牌时返回成功。以下是编辑后编写函数的样子。

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;
}