关于STM8S使用硬件SPI收发问题

来源:互联网 发布:网络黑侠 编辑:程序博客网 时间:2024/06/11 20:12

在调试STM8S的SPI时候,由于在学习板上飞线,然后发现每次读SPI FLASH的设备ID等都是不对的.

在21IC发帖求救http://bbs.21ic.com/forum.php?mod=viewthread&tid=788880&epclose=1

总体来说是怀疑硬件飞线的干扰.于是今天又飞了一块板子,发现仍然有这样的问题.

好吧,真的只能打板了.

自己想想会不会在读取数据前SPI的硬件BUFFER中就存在有数据啊.

嗯,有可能, 于是在读数据前,先将SPI的数据先读出,清空缓存,具体代码如下

/* --Common functions *//* * Function:       Wait_Flash_WarmUp * Arguments:      None. * Description:    Wait some time until flash read / write enable. * Return Message: None. */void Wait_Flash_WarmUp(){    uint32 time_cnt = FlashFullAccessTime;    while( time_cnt > 0 )    {        time_cnt--;    }}/* * Function:       Initial_Spi * Arguments:      None * Description:    Initial spi flash state and wait flash warm-up *                 (enable read/write). * Return Message: None */void Initial_Spi(){#ifdef GPIO_SPI    WPn = 1;        // Write potected initial high    SI = 0;         // Flash input data    SCLK = 1;       // Flash input clock    CSn = 1;        // Chip Select#endifGPIO_Init(CS_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);GPIO_Init(SPI_SCK_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);GPIO_Init(SPI_MOSI_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);GPIO_Init(SPI_MISO_PIN,GPIO_MODE_IN_PU_NO_IT);SPI_DeInit();SPI_Init(SPI_FIRSTBIT_MSB,SPI_BAUDRATEPRESCALER_2,SPI_MODE_MASTER,SPI_CLOCKPOLARITY_HIGH,\SPI_CLOCKPHASE_2EDGE,SPI_DATADIRECTION_2LINES_FULLDUPLEX,SPI_NSS_SOFT,0x07);SPI_Cmd(TRUE);// Wait flash warm-up    Wait_Flash_WarmUp();}/* * Function:       CS_Low, CS_High * Arguments:      None. * Description:    Chip select go low / high. * Return Message: None. */void CS_Low(){#ifdef GPIO_SPI    CSn = 0;#else    //--- insert your chip select code here. ---//    GPIO_WriteLow(CS_PIN);#endif}void CS_High(){#ifdef GPIO_SPI    CSn = 1;    WPn = 1;#else    //--- insert your chip select code here. ---//    GPIO_WriteHigh(CS_PIN);#endif}/* * Function:       InsertDummyCycle * Arguments:      dummy_cycle, number of dummy clock cycle * Description:    Insert dummy cycle of SCLK * Return Message: None. */void InsertDummyCycle( uint8 dummy_cycle ){#ifdef GPIO_SPI    uint8 i;    for( i=0; i < dummy_cycle; i=i+1 )    {        SCLK = 0;        SCLK = 1;    }#else    //--- insert your code here. ---//    uint8 i;    for( i=0; i < dummy_cycle / 8 ; i=i+1 )    {SPI_SendData(DUMMY_BYTE);    }#endif}/* * Function:       SendByte * Arguments:      byte_value, data transfer to flash *                 transfer_type, select different type of I/O mode. *                 Seven mode: *                 SIO, single IO *                 DIO, dual IO *                 QIO, quad IO *                 PIO, parallel *                 DTSIO, double transfer rate SIO *                 DTDIO, double transfer rate DIO *                 DTQIO, double transfer rate QIO * Description:    Send one byte data to flash * Return Message: None. */void SendByte( uint8 byte_value, uint8 transfer_type ){while(SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);SPI_SendData(byte_value);#ifdef GPIO_SPI    uint16 i;    uint8 cycle_cnt;    switch( transfer_type )    {#ifdef SIO    case SIO: // single I/O        cycle_cnt = 8;        for( i= 0; i < cycle_cnt; i++ )        {            if ( (byte_value & IO_MASK) == 0x80 ){                SI = 1;            }            else{                SI = 0;            }            SCLK = 0;            byte_value = byte_value << 1;            SCLK = 1;        }        break;#endif#ifdef DIO    case DIO: // dual I/O        cycle_cnt = 4;        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);            byte_value = byte_value << 2;            SCLK = 1;        }        break;#endif#ifdef QIO    case QIO: // quad I/O        cycle_cnt = 2;        for( i= 0; i < cycle_cnt; i++ )        {            P1 = (byte_value & 0xf0);  // CS# and SCLK must be zero at this phase            byte_value = byte_value << 4;            SCLK = 1;        }        break;#endif#ifdef PIO    case PIO: //  Parallel I/O        SCLK = 0;        PO7 = ( (byte_value & IO_MASK)  == IO_MASK )?1:0;        PO6 = ( (byte_value & 0x40)  == 0x40 )?1:0;        P3 = (byte_value & 0x3f) | (P3 & 0xc0);        SCLK = 1;        break;#endif#ifdef DTSIO    case DTSIO: //  Double transfer rate single I/O        cycle_cnt = 4;         for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            SI = ( (byte_value & IO_MASK) == IO_MASK )?1:0;            byte_value = byte_value << 1;            SCLK = 1;            SI = ( (byte_value & IO_MASK) == IO_MASK )?1:0;            byte_value = byte_value << 1;        }        break;#endif#ifdef DTDIO    case DTDIO: //  Double transfer rate dual I/O        cycle_cnt = 2;        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);            byte_value = byte_value << 2;            SCLK = 1;            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);            byte_value = byte_value << 2;        }        break;#endif#ifdef DTQIO    case DTQIO: //  Double transfer rate quad I/O        SCLK = 0;        P1 = (byte_value & 0xf0);        SCLK = 1;        byte_value = byte_value << 4;        P1 = (byte_value & 0xf0);  // CS# and SCLK must be zero at this phase        break;#endif    default:        break;    }#else    switch( transfer_type )    {#ifdef SIO    case SIO: // Single I/O        //--- insert your code here for single IO transfer. ---//        break;#endif#ifdef DIO    case DIO: // Dual I/O        //--- insert your code here for dual IO transfer. ---//        break;#endif#ifdef QIO    case QIO: // Quad I/O        //--- insert your code here for quad IO transfer. ---//        break;#endif#ifdef PIO    case PIO: // Parallel I/O        //--- insert your code here for parallel IO transfer. ---//        break;#endif#ifdef DTSIO    case DTSIO: // Double transfer rate Single I/O        //--- insert your code here for DT single IO transfer. ---//        break;#endif#ifdef DTDIO    case DTDIO: // Double transfer rate Dual I/O        //--- insert your code here for DT dual IO transfer. ---//        break;#endif#ifdef DTQIO    case DTQIO: // Double transfer rate Quad I/O        //--- insert your code here for DT quad IO transfer. ---//        break;#endif    default:        break;    }#endif  /* End of GPIO_SPI */}/* * Function:       GetByte * Arguments:      byte_value, data receive from flash *                 transfer_type, select different type of I/O mode. *                 Seven mode: *                 SIO, single IO *                 DIO, dual IO *                 QIO, quad IO *                 PIO, parallel IO *                 DTSIO, double transfer rate SIO *                 DTDIO, double transfer rate DIO *                 DTQIO, double transfer rate QIO * Description:    Get one byte data to flash * Return Message: 8 bit data */uint8 GetByte( uint8 transfer_type ){    uint8 data_buf;data_buf = SPI_ReceiveData();//必须先读取一下,防止接收缓存中存有数据SendByte( DUMMY_BYTE, SIO );while(SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET);data_buf = SPI_ReceiveData();#ifdef GPIO_SPI    uint16 i;    uint8 cycle_cnt;    data_buf = 0;    cycle_cnt = 8 >> transfer_type;    switch( transfer_type )    {#ifdef SIO    case SIO: // single I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SO = 1;        // End VIP 8051 GPIO        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            if ( SO == 1 ){                data_buf = (data_buf | (0x80 >> i));            }            SCLK = 1;        }        break;#endif#ifdef DIO    case DIO: // dual I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SIO0 = 1;        SIO1 = 1;        // End VIP 8051 GPIO        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            data_buf = data_buf << 2;            data_buf = ( data_buf | ((P1 & 0x30) >> 4 ) );            SCLK = 1;        }        break;#endif#ifdef QIO    case QIO: // quad I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SIO0 = 1;        SIO1 = 1;        SIO2 = 1;        SIO3 = 1;        // End VIP 8051 GPIO        SCLK = 0;        data_buf = P1 & 0xf0;        SCLK = 1;        SCLK = 0;        data_buf = ((P1 & 0xf0)>> 4)| data_buf;        SCLK = 1;        break;#endif#ifdef PIO    case PIO: //  Parallel I/O        // Set VIP 8051 GPIO as input ( need pull to high )        PO7 = 1;        PO6 = 1;        PO5 = 1;        PO4 = 1;        PO3 = 1;        PO2 = 1;        PO1 = 1;        PO0 = 1;        // End VIP 8051 GPIO        SCLK = 0;        data_buf = (( P1 & 0x20 )<< 2) | ((P1 & 0x02 ) << 5) | (P3 & 0x3f );        SCLK = 1;        break;#endif#ifdef DTSIO    case DTSIO: //  Double transfer rate Single I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SO = 1;        // End VIP 8051 GPIO        cycle_cnt = 4;        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            if ( SO == 1 ){                data_buf = (data_buf | ( 0x80 >> (i*2) ));            }            SCLK = 1;            if ( SO == 1 ){                data_buf = (data_buf | (0x80 >> ((i*2) + 1) ));            }        }        break;#endif#ifdef DTDIO    case DTDIO: //  Double transfer rate Dual I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SIO0 = 1;        SIO1 = 1;        // End VIP 8051 GPIO        cycle_cnt = 2;        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            data_buf = data_buf << 2;            data_buf = ( data_buf  | ( (P1 & 0x30) >> 4 ) );            SCLK = 1;            data_buf = data_buf << 2;            data_buf = ( data_buf  | ( (P1 & 0x30) >> 4 ) );        }        break;#endif#ifdef DTQIO    case DTQIO: //  DTR qual I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SIO0 = 1;        SIO1 = 1;        SIO2 = 1;        SIO3 = 1;        // End VIP 8051 GPIO        SCLK = 0;        data_buf = P1 & 0xf0;        SCLK = 1;        data_buf = ( (P1 & 0xf0) >> 4 )| data_buf;        break;#endif    default:        break;    }#else    switch( transfer_type )    {#ifdef SIO    case SIO: // Single I/O        //--- insert your code here for single IO receive. ---//        break;#endif#ifdef DIO    case DIO: // Dual I/O        //--- insert your code here for dual IO receive. ---//        break;#endif#ifdef QIO    case QIO: // Quad I/O        //--- insert your code here for qual IO receive. ---//        break;#endif#ifdef PIO    case PIO: // Parallel I/O        //--- insert your code here for parallel IO receive. ---//        break;#endif#ifdef DTSIO    case DTSIO: // Double transfer rate Single I/O        //--- insert your code here for DT single IO receive. ---//        break;#endif#ifdef DTDIO    case DTDIO: // Double transfer rate Dual I/O        //--- insert your code here for DT dual IO receive. ---//        break;#endif#ifdef DTQIO    case DTQIO: // Double transfer rate Qual I/O        //--- insert your code here for DT quad IO receive. ---//#endif    default:        break;    }#endif  /* End of GPIO_SPI */    return data_buf;}/* * Function:       WaitFlashReady * Arguments:      ExpectTime, expected time-out value of flash operations. *                 No use at non-synchronous IO mode. * Description:    Synchronous IO: *                 If flash is ready return TRUE. *                 If flash is time-out return FALSE. *                 Non-synchronous IO: *                 Always return TRUE * Return Message: TRUE, FALSE */BOOL WaitFlashReady( uint32 ExpectTime ){#ifndef NON_SYNCHRONOUS_IO    uint32 temp = 0;    while( IsFlashBusy() )    {        if( temp > ExpectTime )        {            return FALSE;        }        temp = temp + 1;    }       return TRUE;#else    return TRUE;#endif}/* * Function:       WaitRYBYReady * Arguments:      ExpectTime, expected time-out value of flash operations. *                 No use at non-synchronous IO mode. * Description:    Synchronous IO: *                 If flash is ready return TRUE. *                 If flash is time-out return FALSE. *                 Non-synchronous IO: *                 Always return TRUE * Return Message: TRUE, FALSE */BOOL WaitRYBYReady( uint32 ExpectTime ){#ifndef NON_SYNCHRONOUS_IO    uint32 temp = 0;#ifdef GPIO_SPI    while( SO == 0 )#else    // Insert your code for waiting RYBY (SO) pin ready#endif    {        if( temp > ExpectTime )        {            return FALSE;        }        temp = temp + 1;    }    return TRUE;#else    return TRUE;#endif}/* * Function:       IsFlashBusy * Arguments:      None. * Description:    Check status register WIP bit. *                 If  WIP bit = 1: return TRUE ( Busy ) *                             = 0: return FALSE ( Ready ). * Return Message: TRUE, FALSE */BOOL IsFlashBusy( void ){    uint8  gDataBuffer;    CMD_RDSR( &gDataBuffer );    if( (gDataBuffer & FLASH_WIP_MASK)  == FLASH_WIP_MASK )        return TRUE;    else        return FALSE;}/* * Function:       IsFlashQIO * Arguments:      None. * Description:    If flash QE bit = 1: return TRUE *                                 = 0: return FALSE. * Return Message: TRUE, FALSE */BOOL IsFlashQIO( void ){#ifdef FLASH_NO_QE_BIT    return TRUE;#else    uint8  gDataBuffer;    CMD_RDSR( &gDataBuffer );    if( (gDataBuffer & FLASH_QE_MASK) == FLASH_QE_MASK )        return TRUE;    else        return FALSE;#endif}/* * Function:       IsFlash4Byte * Arguments:      None * Description:    Check flash address is 3-byte or 4-byte. *                 If flash 4BYTE bit = 1: return TRUE *                                    = 0: return FALSE. * Return Message: TRUE, FALSE */BOOL IsFlash4Byte( void ){#ifdef FLASH_CMD_RDSCUR    #ifdef FLASH_4BYTE_ONLY        return TRUE;    #elif FLASH_3BYTE_ONLY        return FALSE;    #else        uint8  gDataBuffer;        CMD_RDSCUR( &gDataBuffer );        if( (gDataBuffer & FLASH_4BYTE_MASK) == FLASH_4BYTE_MASK )            return TRUE;        else            return FALSE;    #endif#else    return FALSE;#endif}/* * Function:       SendFlashAddr * Arguments:      flash_address, 32 bit flash memory address *                 io_mode, I/O mode to transfer address *                 addr_4byte_mode, * Description:    Send flash address with 3-byte or 4-byte mode. * Return Message: None */void SendFlashAddr( uint32 flash_address, uint8 io_mode, uint8 addr_4byte_mode ){    /* Check flash is 3-byte or 4-byte mode.       4-byte mode: Send 4-byte address (A31-A0)       3-byte mode: Send 3-byte address (A23-A0) */    if( addr_4byte_mode == TRUE ){        SendByte( (flash_address >> 24), io_mode ); // A31-A24    }    /* A23-A0 */    SendByte( (flash_address >> 16), io_mode );    SendByte( (flash_address >> 8), io_mode );    SendByte( (flash_address), io_mode );}/* * ID Command *//* * Function:       CMD_RDID * Arguments:      Identification, 32 bit buffer to store id * Description:    The RDID instruction is to read the manufacturer ID *                 of 1-byte and followed by Device ID of 2-byte. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RDID( uint32 *Identification ){    uint32 temp;    uint8  gDataBuffer[3];    // Chip select go low to start a flash command    CS_Low();    // Send command    SendByte( FLASH_CMD_RDID, SIO );    // Get manufacturer identification, device identification    gDataBuffer[0] = GetByte( SIO );    gDataBuffer[1] = GetByte( SIO );    gDataBuffer[2] = GetByte( SIO );    // Chip select go high to end a command    CS_High();    // Store identification    temp =  (u32)(gDataBuffer[0]);    temp =  (u32)((temp << 8) | gDataBuffer[1]);    *Identification =  (u32)((temp << 8) | gDataBuffer[2]);    return FlashOperationSuccess;}/* * Function:       CMD_RES * Arguments:      ElectricIdentification, 8 bit buffer to store electric id * Description:    The RES instruction is to read the Device *                 electric identification of 1-byte. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RES( uint8 *ElectricIdentification ){    // Chip select go low to start a flash command    CS_Low();    // Send flash command and insert dummy cycle    SendByte( FLASH_CMD_RES, SIO );    InsertDummyCycle( 24 );    // Get electric identification    *ElectricIdentification = GetByte( SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_REMS * Arguments:      REMS_Identification, 16 bit buffer to store id *                 fsptr, pointer of flash status structure * Description:    The REMS instruction is to read the Device *                 manufacturer ID and electric ID of 1-byte. * Return Message: FlashOperationSuccess */ReturnMsg CMD_REMS( uint16 *REMS_Identification, FlashStatus *fsptr ){    uint8  gDataBuffer[2];    // Chip select go low to start a flash command    CS_Low();    // Send flash command and insert dummy cycle ( if need )    // ArrangeOpt = 0x00 will output the manufacturer's ID first    //            = 0x01 will output electric ID first    SendByte( FLASH_CMD_REMS, SIO );    InsertDummyCycle( 16 );    SendByte( fsptr->ArrangeOpt, SIO );    // Get ID    gDataBuffer[0] = GetByte( SIO );    gDataBuffer[1] = GetByte( SIO );    // Store identification informaion    *REMS_Identification = (gDataBuffer[0] << 8) | gDataBuffer[1];    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Register  Command *//* * Function:       CMD_RDSR * Arguments:      StatusReg, 8 bit buffer to store status register value * Description:    The RDSR instruction is for reading Status Register Bits. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RDSR( uint8 *StatusReg ){    uint8  gDataBuffer;    // Chip select go low to start a flash command    CS_Low();    // Send command    SendByte( FLASH_CMD_RDSR, SIO );    gDataBuffer = GetByte( SIO );    // Chip select go high to end a flash command    CS_High();    *StatusReg = gDataBuffer;    return FlashOperationSuccess;}/* * Function:       CMD_WRSR * Arguments:      UpdateValue, 8/16 bit status register value to updata * Description:    The WRSR instruction is for changing the values of *                 Status Register Bits (and configuration register) * Return Message: FlashIsBusy, FlashTimeOut, FlashOperationSuccess */#ifdef SUPPORT_WRSR_CRReturnMsg CMD_WRSR( uint16 UpdateValue )#elseReturnMsg CMD_WRSR( uint8 UpdateValue )#endif{    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    // Send command and update value    SendByte( FLASH_CMD_WRSR, SIO );    SendByte( UpdateValue, SIO );#ifdef SUPPORT_WRSR_CR    SendByte( UpdateValue >> 8, SIO );    // write configuration register#endif    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( WriteStatusRegCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Function:       CMD_RDSCUR * Arguments:      SecurityReg, 8 bit buffer to store security register value * Description:    The RDSCUR instruction is for reading the value of *                 Security Register bits. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RDSCUR( uint8 *SecurityReg ){    uint8  gDataBuffer;    // Chip select go low to start a flash command    CS_Low();    //Send command    SendByte( FLASH_CMD_RDSCUR, SIO );    gDataBuffer = GetByte( SIO );    // Chip select go high to end a flash command    CS_High();    *SecurityReg = gDataBuffer;    return FlashOperationSuccess;}/* * Function:       CMD_WRSCUR * Arguments:      None. * Description:    The WRSCUR instruction is for changing the values of *                 Security Register Bits. * Return Message: FlashIsBusy, FlashOperationSuccess, FlashWriteRegFailed, *                 FlashTimeOut */ReturnMsg CMD_WRSCUR( void ){    uint8  gDataBuffer;    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    // Write WRSCUR command    SendByte( FLASH_CMD_WRSCUR, SIO );    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( WriteSecuRegCycleTime ) ){        CMD_RDSCUR( &gDataBuffer );        // Check security register LDSO bit        if( (gDataBuffer & FLASH_LDSO_MASK) == FLASH_LDSO_MASK )                return FlashOperationSuccess;        else                return FlashWriteRegFailed;    }    else        return FlashTimeOut;}/* * Read Command *//* * Function:       CMD_READ * Arguments:      flash_address, 32 bit flash memory address *                 target_address, buffer address to store returned data *                 byte_length, length of returned data in byte unit * Description:    The READ instruction is for reading data out. * Return Message: FlashAddressInvalid, FlashOperationSuccess */ReturnMsg CMD_READ( uint32 flash_address, uint8 *target_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Chip select go low to start a flash command    CS_Low();    // Write READ command and address    SendByte( FLASH_CMD_READ, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    // Set a loop to read data into buffer    for( index=0; index < byte_length; index++ )    {        // Read data one byte at a time        *(target_address + index) = GetByte( SIO );    }    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_DREAD * Arguments:      flash_address, 32 bit flash memory address *                 target_address, buffer address to store returned data *                 byte_length, length of returned data in byte unit * Description:    The DREAD instruction enable double throughput of Serial *                 Flash in read mode * Return Message: FlashAddressInvalid, FlashOperationSuccess */ReturnMsg CMD_DREAD( uint32 flash_address, uint8 *target_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;    // 4-byte mode    else        addr_4byte_mode = FALSE;   // 3-byte mode    // Chip select go low to start a flash command    CS_Low();    // Write 2-I/O Read command and address    SendByte( FLASH_CMD_DREAD, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    InsertDummyCycle( 8 );                    // Wait 8 dummy cycle    // Set a loop to read data into data buffer    for( index=0; index < byte_length; index++ )    {        *(target_address + index) = GetByte( DIO );    }    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_FASTREAD * Arguments:      flash_address, 32 bit flash memory address *                 target_address, buffer address to store returned data *                 byte_length, length of returned data in byte unit * Description:    The FASTREAD instruction is for quickly reading data out. * Return Message: FlashAddressInvalid, FlashOperationSuccess */ReturnMsg CMD_FASTREAD( uint32 flash_address, uint8 *target_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Chip select go low to start a flash command    CS_Low();    // Write Fast Read command, address and dummy cycle    SendByte( FLASH_CMD_FASTREAD, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    InsertDummyCycle ( 8 );          // Wait dummy cycle    // Set a loop to read data into data buffer    for( index=0; index < byte_length; index++ )    {        *(target_address + index) = GetByte( SIO );    }    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_RDSFDP * Arguments:      flash_address, 32 bit flash memory address *                 target_address, buffer address to store returned data *                 byte_length, length of returned data in byte unit * Description:    RDSFDP can retrieve the operating characteristics, structure *                 and vendor-specified information such as identifying information, *                 memory size, operating voltages and timinginformation of device * Return Message: FlashAddressInvalid, FlashOperationSuccess */ReturnMsg CMD_RDSFDP( uint32 flash_address, uint8 *target_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Chip select go low to start a flash command    CS_Low();    // Write Read SFDP command    SendByte( FLASH_CMD_RDSFDP, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    InsertDummyCycle ( 8 );        // Insert dummy cycle    // Set a loop to read data into data buffer    for( index=0; index < byte_length; index++ )    {        *(target_address + index) = GetByte( SIO );    }    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Program Command *//* * Function:       CMD_WREN * Arguments:      None. * Description:    The WREN instruction is for setting *                 Write Enable Latch (WEL) bit. * Return Message: FlashOperationSuccess */ReturnMsg CMD_WREN( void ){    // Chip select go low to start a flash command    CS_Low();    // Write Enable command = 0x06, Setting Write Enable Latch Bit    SendByte( FLASH_CMD_WREN, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_WRDI * Arguments:      None. * Description:    The WRDI instruction is to reset *                 Write Enable Latch (WEL) bit. * Return Message: FlashOperationSuccess */ReturnMsg CMD_WRDI( void ){    // Chip select go low to start a flash command    CS_Low();    // Write Disable command = 0x04, resets Write Enable Latch Bit    SendByte( FLASH_CMD_WRDI, SIO );    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_PP * Arguments:      flash_address, 32 bit flash memory address *                 source_address, buffer address of source data to program *                 byte_length, byte length of data to programm * Description:    The PP instruction is for programming *                 the memory to be "0". *                 The device only accept the last 256 byte ( or 32 byte ) to program. *                 If the page address ( flash_address[7:0] ) reach 0xFF, it will *                 program next at 0x00 of the same page. *                 Some products have smaller page size ( 32 byte ) * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess, *                 FlashTimeOut */ReturnMsg CMD_PP( uint32 flash_address, uint8 *source_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    // Write Page Program command    SendByte( FLASH_CMD_PP, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    // Set a loop to down load whole page data into flash's buffer    // Note: only last 256 byte ( or 32 byte ) will be programmed    for( index=0; index < byte_length; index++ )    {        SendByte( *(source_address + index), SIO );    }    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( PageProgramCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Erase Command *//* * Function:       CMD_SE * Arguments:      flash_address, 32 bit flash memory address * Description:    The SE instruction is for erasing the data *                 of the chosen sector (4KB) to be "1". * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess, *                 FlashTimeOut */ReturnMsg CMD_SE( uint32 flash_address ){    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    //Write Sector Erase command = 0x20;    SendByte( FLASH_CMD_SE, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( SectorEraseCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Function:       CMD_BE * Arguments:      flash_address, 32 bit flash memory address * Description:    The BE instruction is for erasing the data *                 of the chosen sector (64KB) to be "1". * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess, *                 FlashTimeOut */ReturnMsg CMD_BE( uint32 flash_address ){    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    //Write Block Erase command = 0xD8;    SendByte( FLASH_CMD_BE, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( BlockEraseCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Function:       CMD_CE * Arguments:      None. * Description:    The CE instruction is for erasing the data *                 of the whole chip to be "1". * Return Message: FlashIsBusy, FlashOperationSuccess, FlashTimeOut */ReturnMsg CMD_CE( void ){    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    //Write Chip Erase command = 0x60;    SendByte( FLASH_CMD_CE, SIO );    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( ChipEraseCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Mode setting Command *//* * Function:       CMD_DP * Arguments:      None. * Description:    The DP instruction is for setting the *                 device on the minimizing the power consumption. * Return Message: FlashOperationSuccess */ReturnMsg CMD_DP( void ){    // Chip select go low to start a flash command    CS_Low();    // Deep Power Down Mode command    SendByte( FLASH_CMD_DP, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_RDP * Arguments:      None. * Description:    The Release from RDP instruction is *                 putting the device in the Stand-by Power mode. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RDP( void ){    // Chip select go low to start a flash command    CS_Low();    // Deep Power Down Mode command    SendByte( FLASH_CMD_RDP, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_ENSO * Arguments:      None. * Description:    The ENSO instruction is for entering the secured OTP mode. * Return Message: FlashOperationSuccess */ReturnMsg CMD_ENSO( void ){    // Chip select go low to start a flash command    CS_Low();    // Write ENSO command    SendByte( FLASH_CMD_ENSO, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_EXSO * Arguments:      None. * Description:    The EXSO instruction is for exiting the secured OTP mode. * Return Message: FlashOperationSuccess */ReturnMsg CMD_EXSO( void ){    // Chip select go low to start a flash command    CS_Low();    // Write EXSO command = 0xC1    SendByte( FLASH_CMD_EXSO, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Reset setting Command *//* * Security Command */

注意在uint8 GetByte( uint8 transfer_type )函数的这句话

data_buf = SPI_ReceiveData();//必须先读取一下,防止接收缓存中存有数据

好了,调试一下,果然成功获取该SPI FLASH的值.

 那我用IO方式验证一下.代码如下:

/* --Common functions *//* * Function:       Wait_Flash_WarmUp * Arguments:      None. * Description:    Wait some time until flash read / write enable. * Return Message: None. */void Wait_Flash_WarmUp(){    uint32 time_cnt = FlashFullAccessTime;    while( time_cnt > 0 )    {        time_cnt--;    }}/* * Function:       Initial_Spi * Arguments:      None * Description:    Initial spi flash state and wait flash warm-up *                 (enable read/write). * Return Message: None */void Initial_Spi(){#ifdef GPIO_SPI    WPn = 1;        // Write potected initial high    SI = 0;         // Flash input data    SCLK = 1;       // Flash input clock    CSn = 1;        // Chip Select#endifGPIO_Init(CS_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);GPIO_Init(SPI_SCK_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);GPIO_Init(SPI_MOSI_PIN,GPIO_MODE_OUT_PP_HIGH_FAST);GPIO_Init(SPI_MISO_PIN,GPIO_MODE_IN_PU_NO_IT);//SPI_DeInit();//SPI_Init(SPI_FIRSTBIT_MSB,SPI_BAUDRATEPRESCALER_2,SPI_MODE_MASTER,SPI_CLOCKPOLARITY_HIGH,\//SPI_CLOCKPHASE_2EDGE,SPI_DATADIRECTION_2LINES_FULLDUPLEX,SPI_NSS_SOFT,0x07);//SPI_Cmd(TRUE);// Wait flash warm-up    Wait_Flash_WarmUp();}/* * Function:       CS_Low, CS_High * Arguments:      None. * Description:    Chip select go low / high. * Return Message: None. */void CS_Low(){#ifdef GPIO_SPI    CSn = 0;#else    //--- insert your chip select code here. ---//    GPIO_WriteLow(CS_PIN);#endif}void CS_High(){#ifdef GPIO_SPI    CSn = 1;    WPn = 1;#else    //--- insert your chip select code here. ---//    GPIO_WriteHigh(CS_PIN);#endif}/* * Function:       InsertDummyCycle * Arguments:      dummy_cycle, number of dummy clock cycle * Description:    Insert dummy cycle of SCLK * Return Message: None. */void InsertDummyCycle( uint8 dummy_cycle ){#ifdef GPIO_SPI    uint8 i;    for( i=0; i < dummy_cycle; i=i+1 )    {        SCLK = 0;        SCLK = 1;    }#else    //--- insert your code here. ---//    uint8 i;    #if 0    for( i=0; i < dummy_cycle / 8 ; i=i+1 )    {SPI_SendData(DUMMY_BYTE);    }#else    for( i=0; i < dummy_cycle; i=i+1 )    {GPIO_WriteLow(SPI_SCK_PIN);GPIO_WriteHigh(SPI_SCK_PIN);    }#endif#endif}/* * Function:       SendByte * Arguments:      byte_value, data transfer to flash *                 transfer_type, select different type of I/O mode. *                 Seven mode: *                 SIO, single IO *                 DIO, dual IO *                 QIO, quad IO *                 PIO, parallel *                 DTSIO, double transfer rate SIO *                 DTDIO, double transfer rate DIO *                 DTQIO, double transfer rate QIO * Description:    Send one byte data to flash * Return Message: None. */void SendByte( uint8 byte_value, uint8 transfer_type ){    uint16 i;    uint8 cycle_cnt;#if 0while(SPI_GetFlagStatus(SPI_FLAG_TXE) == RESET);SPI_SendData(byte_value);#else        cycle_cnt = 8;        for( i= 0; i < cycle_cnt; i++ )        {            if ( (byte_value & IO_MASK) == 0x80 ){GPIO_WriteHigh(SPI_MOSI_PIN);            }            else{GPIO_WriteLow(SPI_MOSI_PIN);            }GPIO_WriteLow(SPI_SCK_PIN);            byte_value = byte_value << 1;GPIO_WriteHigh(SPI_SCK_PIN);        }#endif#ifdef GPIO_SPI    switch( transfer_type )    {#ifdef SIO    case SIO: // single I/O        cycle_cnt = 8;        for( i= 0; i < cycle_cnt; i++ )        {            if ( (byte_value & IO_MASK) == 0x80 ){                SI = 1;            }            else{                SI = 0;            }            SCLK = 0;            byte_value = byte_value << 1;            SCLK = 1;        }        break;#endif#ifdef DIO    case DIO: // dual I/O        cycle_cnt = 4;        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);            byte_value = byte_value << 2;            SCLK = 1;        }        break;#endif#ifdef QIO    case QIO: // quad I/O        cycle_cnt = 2;        for( i= 0; i < cycle_cnt; i++ )        {            P1 = (byte_value & 0xf0);  // CS# and SCLK must be zero at this phase            byte_value = byte_value << 4;            SCLK = 1;        }        break;#endif#ifdef PIO    case PIO: //  Parallel I/O        SCLK = 0;        PO7 = ( (byte_value & IO_MASK)  == IO_MASK )?1:0;        PO6 = ( (byte_value & 0x40)  == 0x40 )?1:0;        P3 = (byte_value & 0x3f) | (P3 & 0xc0);        SCLK = 1;        break;#endif#ifdef DTSIO    case DTSIO: //  Double transfer rate single I/O        cycle_cnt = 4;         for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            SI = ( (byte_value & IO_MASK) == IO_MASK )?1:0;            byte_value = byte_value << 1;            SCLK = 1;            SI = ( (byte_value & IO_MASK) == IO_MASK )?1:0;            byte_value = byte_value << 1;        }        break;#endif#ifdef DTDIO    case DTDIO: //  Double transfer rate dual I/O        cycle_cnt = 2;        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);            byte_value = byte_value << 2;            SCLK = 1;            P1 = (( byte_value & 0xc0 ) >> 2) | (P1 & 0xcf);            byte_value = byte_value << 2;        }        break;#endif#ifdef DTQIO    case DTQIO: //  Double transfer rate quad I/O        SCLK = 0;        P1 = (byte_value & 0xf0);        SCLK = 1;        byte_value = byte_value << 4;        P1 = (byte_value & 0xf0);  // CS# and SCLK must be zero at this phase        break;#endif    default:        break;    }#else    switch( transfer_type )    {#ifdef SIO    case SIO: // Single I/O        //--- insert your code here for single IO transfer. ---//        break;#endif#ifdef DIO    case DIO: // Dual I/O        //--- insert your code here for dual IO transfer. ---//        break;#endif#ifdef QIO    case QIO: // Quad I/O        //--- insert your code here for quad IO transfer. ---//        break;#endif#ifdef PIO    case PIO: // Parallel I/O        //--- insert your code here for parallel IO transfer. ---//        break;#endif#ifdef DTSIO    case DTSIO: // Double transfer rate Single I/O        //--- insert your code here for DT single IO transfer. ---//        break;#endif#ifdef DTDIO    case DTDIO: // Double transfer rate Dual I/O        //--- insert your code here for DT dual IO transfer. ---//        break;#endif#ifdef DTQIO    case DTQIO: // Double transfer rate Quad I/O        //--- insert your code here for DT quad IO transfer. ---//        break;#endif    default:        break;    }#endif  /* End of GPIO_SPI */}/* * Function:       GetByte * Arguments:      byte_value, data receive from flash *                 transfer_type, select different type of I/O mode. *                 Seven mode: *                 SIO, single IO *                 DIO, dual IO *                 QIO, quad IO *                 PIO, parallel IO *                 DTSIO, double transfer rate SIO *                 DTDIO, double transfer rate DIO *                 DTQIO, double transfer rate QIO * Description:    Get one byte data to flash * Return Message: 8 bit data */uint8 GetByte( uint8 transfer_type ){    uint8 data_buf;uint16 i;    uint8 cycle_cnt;    data_buf = 0;#if 0data_buf = SPI_ReceiveData();SendByte( DUMMY_BYTE, SIO );while(SPI_GetFlagStatus(SPI_FLAG_RXNE) == RESET);data_buf = SPI_ReceiveData();#else    cycle_cnt = 8;    for( i= 0; i < cycle_cnt; i++ )    {GPIO_WriteLow(SPI_SCK_PIN);        if ( GPIO_ReadInputPin(SPI_MISO_PIN) == 1 ){            data_buf = (data_buf | (0x80 >> i));        }GPIO_WriteHigh(SPI_SCK_PIN);    }#endif#ifdef GPIO_SPI    cycle_cnt = 8 >> transfer_type;    switch( transfer_type )    {#ifdef SIO    case SIO: // single I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SO = 1;        // End VIP 8051 GPIO        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            if ( SO == 1 ){                data_buf = (data_buf | (0x80 >> i));            }            SCLK = 1;        }        break;#endif#ifdef DIO    case DIO: // dual I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SIO0 = 1;        SIO1 = 1;        // End VIP 8051 GPIO        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            data_buf = data_buf << 2;            data_buf = ( data_buf | ((P1 & 0x30) >> 4 ) );            SCLK = 1;        }        break;#endif#ifdef QIO    case QIO: // quad I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SIO0 = 1;        SIO1 = 1;        SIO2 = 1;        SIO3 = 1;        // End VIP 8051 GPIO        SCLK = 0;        data_buf = P1 & 0xf0;        SCLK = 1;        SCLK = 0;        data_buf = ((P1 & 0xf0)>> 4)| data_buf;        SCLK = 1;        break;#endif#ifdef PIO    case PIO: //  Parallel I/O        // Set VIP 8051 GPIO as input ( need pull to high )        PO7 = 1;        PO6 = 1;        PO5 = 1;        PO4 = 1;        PO3 = 1;        PO2 = 1;        PO1 = 1;        PO0 = 1;        // End VIP 8051 GPIO        SCLK = 0;        data_buf = (( P1 & 0x20 )<< 2) | ((P1 & 0x02 ) << 5) | (P3 & 0x3f );        SCLK = 1;        break;#endif#ifdef DTSIO    case DTSIO: //  Double transfer rate Single I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SO = 1;        // End VIP 8051 GPIO        cycle_cnt = 4;        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            if ( SO == 1 ){                data_buf = (data_buf | ( 0x80 >> (i*2) ));            }            SCLK = 1;            if ( SO == 1 ){                data_buf = (data_buf | (0x80 >> ((i*2) + 1) ));            }        }        break;#endif#ifdef DTDIO    case DTDIO: //  Double transfer rate Dual I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SIO0 = 1;        SIO1 = 1;        // End VIP 8051 GPIO        cycle_cnt = 2;        for( i= 0; i < cycle_cnt; i++ )        {            SCLK = 0;            data_buf = data_buf << 2;            data_buf = ( data_buf  | ( (P1 & 0x30) >> 4 ) );            SCLK = 1;            data_buf = data_buf << 2;            data_buf = ( data_buf  | ( (P1 & 0x30) >> 4 ) );        }        break;#endif#ifdef DTQIO    case DTQIO: //  DTR qual I/O        // Set VIP 8051 GPIO as input ( need pull to high )        SIO0 = 1;        SIO1 = 1;        SIO2 = 1;        SIO3 = 1;        // End VIP 8051 GPIO        SCLK = 0;        data_buf = P1 & 0xf0;        SCLK = 1;        data_buf = ( (P1 & 0xf0) >> 4 )| data_buf;        break;#endif    default:        break;    }#else    switch( transfer_type )    {#ifdef SIO    case SIO: // Single I/O        //--- insert your code here for single IO receive. ---//        break;#endif#ifdef DIO    case DIO: // Dual I/O        //--- insert your code here for dual IO receive. ---//        break;#endif#ifdef QIO    case QIO: // Quad I/O        //--- insert your code here for qual IO receive. ---//        break;#endif#ifdef PIO    case PIO: // Parallel I/O        //--- insert your code here for parallel IO receive. ---//        break;#endif#ifdef DTSIO    case DTSIO: // Double transfer rate Single I/O        //--- insert your code here for DT single IO receive. ---//        break;#endif#ifdef DTDIO    case DTDIO: // Double transfer rate Dual I/O        //--- insert your code here for DT dual IO receive. ---//        break;#endif#ifdef DTQIO    case DTQIO: // Double transfer rate Qual I/O        //--- insert your code here for DT quad IO receive. ---//#endif    default:        break;    }#endif  /* End of GPIO_SPI */    return data_buf;}/* * Function:       WaitFlashReady * Arguments:      ExpectTime, expected time-out value of flash operations. *                 No use at non-synchronous IO mode. * Description:    Synchronous IO: *                 If flash is ready return TRUE. *                 If flash is time-out return FALSE. *                 Non-synchronous IO: *                 Always return TRUE * Return Message: TRUE, FALSE */BOOL WaitFlashReady( uint32 ExpectTime ){#ifndef NON_SYNCHRONOUS_IO    uint32 temp = 0;    while( IsFlashBusy() )    {        if( temp > ExpectTime )        {            return FALSE;        }        temp = temp + 1;    }       return TRUE;#else    return TRUE;#endif}/* * Function:       WaitRYBYReady * Arguments:      ExpectTime, expected time-out value of flash operations. *                 No use at non-synchronous IO mode. * Description:    Synchronous IO: *                 If flash is ready return TRUE. *                 If flash is time-out return FALSE. *                 Non-synchronous IO: *                 Always return TRUE * Return Message: TRUE, FALSE */BOOL WaitRYBYReady( uint32 ExpectTime ){#ifndef NON_SYNCHRONOUS_IO    uint32 temp = 0;#ifdef GPIO_SPI    while( SO == 0 )#else    // Insert your code for waiting RYBY (SO) pin ready#endif    {        if( temp > ExpectTime )        {            return FALSE;        }        temp = temp + 1;    }    return TRUE;#else    return TRUE;#endif}/* * Function:       IsFlashBusy * Arguments:      None. * Description:    Check status register WIP bit. *                 If  WIP bit = 1: return TRUE ( Busy ) *                             = 0: return FALSE ( Ready ). * Return Message: TRUE, FALSE */BOOL IsFlashBusy( void ){    uint8  gDataBuffer;    CMD_RDSR( &gDataBuffer );    if( (gDataBuffer & FLASH_WIP_MASK)  == FLASH_WIP_MASK )        return TRUE;    else        return FALSE;}/* * Function:       IsFlashQIO * Arguments:      None. * Description:    If flash QE bit = 1: return TRUE *                                 = 0: return FALSE. * Return Message: TRUE, FALSE */BOOL IsFlashQIO( void ){#ifdef FLASH_NO_QE_BIT    return TRUE;#else    uint8  gDataBuffer;    CMD_RDSR( &gDataBuffer );    if( (gDataBuffer & FLASH_QE_MASK) == FLASH_QE_MASK )        return TRUE;    else        return FALSE;#endif}/* * Function:       IsFlash4Byte * Arguments:      None * Description:    Check flash address is 3-byte or 4-byte. *                 If flash 4BYTE bit = 1: return TRUE *                                    = 0: return FALSE. * Return Message: TRUE, FALSE */BOOL IsFlash4Byte( void ){#ifdef FLASH_CMD_RDSCUR    #ifdef FLASH_4BYTE_ONLY        return TRUE;    #elif FLASH_3BYTE_ONLY        return FALSE;    #else        uint8  gDataBuffer;        CMD_RDSCUR( &gDataBuffer );        if( (gDataBuffer & FLASH_4BYTE_MASK) == FLASH_4BYTE_MASK )            return TRUE;        else            return FALSE;    #endif#else    return FALSE;#endif}/* * Function:       SendFlashAddr * Arguments:      flash_address, 32 bit flash memory address *                 io_mode, I/O mode to transfer address *                 addr_4byte_mode, * Description:    Send flash address with 3-byte or 4-byte mode. * Return Message: None */void SendFlashAddr( uint32 flash_address, uint8 io_mode, uint8 addr_4byte_mode ){    /* Check flash is 3-byte or 4-byte mode.       4-byte mode: Send 4-byte address (A31-A0)       3-byte mode: Send 3-byte address (A23-A0) */    if( addr_4byte_mode == TRUE ){        SendByte( (flash_address >> 24), io_mode ); // A31-A24    }    /* A23-A0 */    SendByte( (flash_address >> 16), io_mode );    SendByte( (flash_address >> 8), io_mode );    SendByte( (flash_address), io_mode );}/* * ID Command *//* * Function:       CMD_RDID * Arguments:      Identification, 32 bit buffer to store id * Description:    The RDID instruction is to read the manufacturer ID *                 of 1-byte and followed by Device ID of 2-byte. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RDID( uint32 *Identification ){    uint32 temp;    uint8  gDataBuffer[3];    // Chip select go low to start a flash command    CS_Low();    // Send command    SendByte( FLASH_CMD_RDID, SIO );    // Get manufacturer identification, device identification    gDataBuffer[0] = GetByte( SIO );    gDataBuffer[1] = GetByte( SIO );    gDataBuffer[2] = GetByte( SIO );    // Chip select go high to end a command    CS_High();    // Store identification    temp =  (u32)(gDataBuffer[0]);    temp =  (u32)((temp << 8) | gDataBuffer[1]);    *Identification =  (u32)((temp << 8) | gDataBuffer[2]);    return FlashOperationSuccess;}/* * Function:       CMD_RES * Arguments:      ElectricIdentification, 8 bit buffer to store electric id * Description:    The RES instruction is to read the Device *                 electric identification of 1-byte. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RES( uint8 *ElectricIdentification ){    // Chip select go low to start a flash command    CS_Low();    // Send flash command and insert dummy cycle    SendByte( FLASH_CMD_RES, SIO );    InsertDummyCycle( 24 );    // Get electric identification    *ElectricIdentification = GetByte( SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_REMS * Arguments:      REMS_Identification, 16 bit buffer to store id *                 fsptr, pointer of flash status structure * Description:    The REMS instruction is to read the Device *                 manufacturer ID and electric ID of 1-byte. * Return Message: FlashOperationSuccess */ReturnMsg CMD_REMS( uint16 *REMS_Identification, FlashStatus *fsptr ){    uint8  gDataBuffer[2];    // Chip select go low to start a flash command    CS_Low();    // Send flash command and insert dummy cycle ( if need )    // ArrangeOpt = 0x00 will output the manufacturer's ID first    //            = 0x01 will output electric ID first    SendByte( FLASH_CMD_REMS, SIO );    InsertDummyCycle( 16 );    SendByte( fsptr->ArrangeOpt, SIO );    // Get ID    gDataBuffer[0] = GetByte( SIO );    gDataBuffer[1] = GetByte( SIO );    // Store identification informaion    *REMS_Identification = (gDataBuffer[0] << 8) | gDataBuffer[1];    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Register  Command *//* * Function:       CMD_RDSR * Arguments:      StatusReg, 8 bit buffer to store status register value * Description:    The RDSR instruction is for reading Status Register Bits. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RDSR( uint8 *StatusReg ){    uint8  gDataBuffer;    // Chip select go low to start a flash command    CS_Low();    // Send command    SendByte( FLASH_CMD_RDSR, SIO );    gDataBuffer = GetByte( SIO );    // Chip select go high to end a flash command    CS_High();    *StatusReg = gDataBuffer;    return FlashOperationSuccess;}/* * Function:       CMD_WRSR * Arguments:      UpdateValue, 8/16 bit status register value to updata * Description:    The WRSR instruction is for changing the values of *                 Status Register Bits (and configuration register) * Return Message: FlashIsBusy, FlashTimeOut, FlashOperationSuccess */#ifdef SUPPORT_WRSR_CRReturnMsg CMD_WRSR( uint16 UpdateValue )#elseReturnMsg CMD_WRSR( uint8 UpdateValue )#endif{    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    // Send command and update value    SendByte( FLASH_CMD_WRSR, SIO );    SendByte( UpdateValue, SIO );#ifdef SUPPORT_WRSR_CR    SendByte( UpdateValue >> 8, SIO );    // write configuration register#endif    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( WriteStatusRegCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Function:       CMD_RDSCUR * Arguments:      SecurityReg, 8 bit buffer to store security register value * Description:    The RDSCUR instruction is for reading the value of *                 Security Register bits. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RDSCUR( uint8 *SecurityReg ){    uint8  gDataBuffer;    // Chip select go low to start a flash command    CS_Low();    //Send command    SendByte( FLASH_CMD_RDSCUR, SIO );    gDataBuffer = GetByte( SIO );    // Chip select go high to end a flash command    CS_High();    *SecurityReg = gDataBuffer;    return FlashOperationSuccess;}/* * Function:       CMD_WRSCUR * Arguments:      None. * Description:    The WRSCUR instruction is for changing the values of *                 Security Register Bits. * Return Message: FlashIsBusy, FlashOperationSuccess, FlashWriteRegFailed, *                 FlashTimeOut */ReturnMsg CMD_WRSCUR( void ){    uint8  gDataBuffer;    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    // Write WRSCUR command    SendByte( FLASH_CMD_WRSCUR, SIO );    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( WriteSecuRegCycleTime ) ){        CMD_RDSCUR( &gDataBuffer );        // Check security register LDSO bit        if( (gDataBuffer & FLASH_LDSO_MASK) == FLASH_LDSO_MASK )                return FlashOperationSuccess;        else                return FlashWriteRegFailed;    }    else        return FlashTimeOut;}/* * Read Command *//* * Function:       CMD_READ * Arguments:      flash_address, 32 bit flash memory address *                 target_address, buffer address to store returned data *                 byte_length, length of returned data in byte unit * Description:    The READ instruction is for reading data out. * Return Message: FlashAddressInvalid, FlashOperationSuccess */ReturnMsg CMD_READ( uint32 flash_address, uint8 *target_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Chip select go low to start a flash command    CS_Low();    // Write READ command and address    SendByte( FLASH_CMD_READ, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    // Set a loop to read data into buffer    for( index=0; index < byte_length; index++ )    {        // Read data one byte at a time        *(target_address + index) = GetByte( SIO );    }    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_DREAD * Arguments:      flash_address, 32 bit flash memory address *                 target_address, buffer address to store returned data *                 byte_length, length of returned data in byte unit * Description:    The DREAD instruction enable double throughput of Serial *                 Flash in read mode * Return Message: FlashAddressInvalid, FlashOperationSuccess */ReturnMsg CMD_DREAD( uint32 flash_address, uint8 *target_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;    // 4-byte mode    else        addr_4byte_mode = FALSE;   // 3-byte mode    // Chip select go low to start a flash command    CS_Low();    // Write 2-I/O Read command and address    SendByte( FLASH_CMD_DREAD, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    InsertDummyCycle( 8 );                    // Wait 8 dummy cycle    // Set a loop to read data into data buffer    for( index=0; index < byte_length; index++ )    {        *(target_address + index) = GetByte( DIO );    }    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_FASTREAD * Arguments:      flash_address, 32 bit flash memory address *                 target_address, buffer address to store returned data *                 byte_length, length of returned data in byte unit * Description:    The FASTREAD instruction is for quickly reading data out. * Return Message: FlashAddressInvalid, FlashOperationSuccess */ReturnMsg CMD_FASTREAD( uint32 flash_address, uint8 *target_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Chip select go low to start a flash command    CS_Low();    // Write Fast Read command, address and dummy cycle    SendByte( FLASH_CMD_FASTREAD, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    InsertDummyCycle ( 8 );          // Wait dummy cycle    // Set a loop to read data into data buffer    for( index=0; index < byte_length; index++ )    {        *(target_address + index) = GetByte( SIO );    }    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_RDSFDP * Arguments:      flash_address, 32 bit flash memory address *                 target_address, buffer address to store returned data *                 byte_length, length of returned data in byte unit * Description:    RDSFDP can retrieve the operating characteristics, structure *                 and vendor-specified information such as identifying information, *                 memory size, operating voltages and timinginformation of device * Return Message: FlashAddressInvalid, FlashOperationSuccess */ReturnMsg CMD_RDSFDP( uint32 flash_address, uint8 *target_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Chip select go low to start a flash command    CS_Low();    // Write Read SFDP command    SendByte( FLASH_CMD_RDSFDP, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    InsertDummyCycle ( 8 );        // Insert dummy cycle    // Set a loop to read data into data buffer    for( index=0; index < byte_length; index++ )    {        *(target_address + index) = GetByte( SIO );    }    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Program Command *//* * Function:       CMD_WREN * Arguments:      None. * Description:    The WREN instruction is for setting *                 Write Enable Latch (WEL) bit. * Return Message: FlashOperationSuccess */ReturnMsg CMD_WREN( void ){    // Chip select go low to start a flash command    CS_Low();    // Write Enable command = 0x06, Setting Write Enable Latch Bit    SendByte( FLASH_CMD_WREN, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_WRDI * Arguments:      None. * Description:    The WRDI instruction is to reset *                 Write Enable Latch (WEL) bit. * Return Message: FlashOperationSuccess */ReturnMsg CMD_WRDI( void ){    // Chip select go low to start a flash command    CS_Low();    // Write Disable command = 0x04, resets Write Enable Latch Bit    SendByte( FLASH_CMD_WRDI, SIO );    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_PP * Arguments:      flash_address, 32 bit flash memory address *                 source_address, buffer address of source data to program *                 byte_length, byte length of data to programm * Description:    The PP instruction is for programming *                 the memory to be "0". *                 The device only accept the last 256 byte ( or 32 byte ) to program. *                 If the page address ( flash_address[7:0] ) reach 0xFF, it will *                 program next at 0x00 of the same page. *                 Some products have smaller page size ( 32 byte ) * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess, *                 FlashTimeOut */ReturnMsg CMD_PP( uint32 flash_address, uint8 *source_address, uint32 byte_length ){    uint32 index;    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    // Write Page Program command    SendByte( FLASH_CMD_PP, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    // Set a loop to down load whole page data into flash's buffer    // Note: only last 256 byte ( or 32 byte ) will be programmed    for( index=0; index < byte_length; index++ )    {        SendByte( *(source_address + index), SIO );    }    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( PageProgramCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Erase Command *//* * Function:       CMD_SE * Arguments:      flash_address, 32 bit flash memory address * Description:    The SE instruction is for erasing the data *                 of the chosen sector (4KB) to be "1". * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess, *                 FlashTimeOut */ReturnMsg CMD_SE( uint32 flash_address ){    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    //Write Sector Erase command = 0x20;    SendByte( FLASH_CMD_SE, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( SectorEraseCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Function:       CMD_BE * Arguments:      flash_address, 32 bit flash memory address * Description:    The BE instruction is for erasing the data *                 of the chosen sector (64KB) to be "1". * Return Message: FlashAddressInvalid, FlashIsBusy, FlashOperationSuccess, *                 FlashTimeOut */ReturnMsg CMD_BE( uint32 flash_address ){    uint8  addr_4byte_mode;    // Check flash address    if( flash_address > FlashSize ) return FlashAddressInvalid;    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Check 3-byte or 4-byte mode    if( IsFlash4Byte() )        addr_4byte_mode = TRUE;  // 4-byte mode    else        addr_4byte_mode = FALSE; // 3-byte mode    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    //Write Block Erase command = 0xD8;    SendByte( FLASH_CMD_BE, SIO );    SendFlashAddr( flash_address, SIO, addr_4byte_mode );    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( BlockEraseCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Function:       CMD_CE * Arguments:      None. * Description:    The CE instruction is for erasing the data *                 of the whole chip to be "1". * Return Message: FlashIsBusy, FlashOperationSuccess, FlashTimeOut */ReturnMsg CMD_CE( void ){    // Check flash is busy or not    if( IsFlashBusy() )    return FlashIsBusy;    // Setting Write Enable Latch bit    CMD_WREN();    // Chip select go low to start a flash command    CS_Low();    //Write Chip Erase command = 0x60;    SendByte( FLASH_CMD_CE, SIO );    // Chip select go high to end a flash command    CS_High();    if( WaitFlashReady( ChipEraseCycleTime ) )        return FlashOperationSuccess;    else        return FlashTimeOut;}/* * Mode setting Command *//* * Function:       CMD_DP * Arguments:      None. * Description:    The DP instruction is for setting the *                 device on the minimizing the power consumption. * Return Message: FlashOperationSuccess */ReturnMsg CMD_DP( void ){    // Chip select go low to start a flash command    CS_Low();    // Deep Power Down Mode command    SendByte( FLASH_CMD_DP, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_RDP * Arguments:      None. * Description:    The Release from RDP instruction is *                 putting the device in the Stand-by Power mode. * Return Message: FlashOperationSuccess */ReturnMsg CMD_RDP( void ){    // Chip select go low to start a flash command    CS_Low();    // Deep Power Down Mode command    SendByte( FLASH_CMD_RDP, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_ENSO * Arguments:      None. * Description:    The ENSO instruction is for entering the secured OTP mode. * Return Message: FlashOperationSuccess */ReturnMsg CMD_ENSO( void ){    // Chip select go low to start a flash command    CS_Low();    // Write ENSO command    SendByte( FLASH_CMD_ENSO, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Function:       CMD_EXSO * Arguments:      None. * Description:    The EXSO instruction is for exiting the secured OTP mode. * Return Message: FlashOperationSuccess */ReturnMsg CMD_EXSO( void ){    // Chip select go low to start a flash command    CS_Low();    // Write EXSO command = 0xC1    SendByte( FLASH_CMD_EXSO, SIO );    // Chip select go high to end a flash command    CS_High();    return FlashOperationSuccess;}/* * Reset setting Command *//* * Security Command */


验证结果也正确的.


博文来自:http://blog.csdn.net/lan120576664?viewmode=contents

1 0
原创粉丝点击