关于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
- 关于STM8S使用硬件SPI收发问题
- stm8s开发(七) SPI的使用:SPI主机通信!
- 关于使用BJX-LINK-001调试stm8s系列主控问题
- STM32 SPI 收发数据 ---规则 + 问题解析
- 记录使用stm8s的一些问题
- STM32F4使用硬件SPI驱动ADS8322
- STM8L151 使用硬件SPI驱动W25Q16 Flash
- STM32 3个硬件SPI的使用
- STM8S105K4使用硬件SPI来读取LSM9DS1
- 关于收发数据的问题
- stm32 SPI 收发数据
- stm8s 开发SPI的两种方法
- STM8S学习01——SPI&IIC
- STM8s使用中遇到的死机问题的排除
- stm8s使用问题总结2——AD转换
- 使用STVD+COSMIX编译STM8S工程问题汇总
- 关于SPI的小问题
- STM8S 定时器的使用
- Spring : 调度任务 (Maven版本)
- DISTINCT关键字,常量字段
- 【2777】小P的故事——神奇的换零钱 (sdut)
- [POJ 3596] Illuminated Planet [计算几何]
- 广义表的基本操作
- 关于STM8S使用硬件SPI收发问题
- Java并发编程系列博文目录
- 在Unity中使用Direct2D
- 理解 Linux 的硬链接与软链接(一)
- Android短信与电话:简易实例
- 用Storyboard构建标签栏多页面应用程序UI
- android scale 动画效果
- bzoj1800: [Ahoi2009]fly 飞行棋 统计直径
- mac下tomcat的安装与配置