最近在做毕设,为了兼容PIX的固件,硬件选用了PIX的FMUV5传感器组合:
ICM20689
IST8310
MS5611
主控是STM32F407
其他的驱动都好移植 ICM20689 SPI读取 使用42M速度时会出错 改成4分频到21M后正常每1MS读取一次没问题
但是移植到FM25V01时出现了卡顿 和普通的W25QXX不一样,这个芯片在写数据前不需要擦除,尽管写,高达10^14次方读写寿命
FM25V01硬件原理图:

驱动程序:
#include "Drv_fm25v01.h"
#include "stdio.h"
#define DUMMY_BYTE 0xFF
flash_info_t flash_info;
jedec_id_t flash_id;
static uint8_t Flash_SendByte ( uint8_t byte );
static uint8_t Flash_ReadID ( jedec_id_t *id );
static void Flash_WriteEnable ( void );
//static void Flash_WriteDisable ( void );
void Flash_Init( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
//SPI GPIO Configuration
GPIO_PinAFConfig ( GPIOB, GPIO_PinSource13, GPIO_AF_SPI2 );
GPIO_PinAFConfig ( GPIOB, GPIO_PinSource14, GPIO_AF_SPI2 );
GPIO_PinAFConfig ( GPIOB, GPIO_PinSource15, GPIO_AF_SPI2 );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init ( GPIOB, &GPIO_InitStructure );
//flash SPI CS
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT ; //推挽输出
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init ( GPIOB, &GPIO_InitStructure );
//SPI configuration
SPI_I2S_DeInit ( SPI2 );
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//42/4=22
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init ( SPI2, &SPI_InitStructure );
SPI_Cmd ( SPI2, ENABLE );
FM25VXX_CS_HIGH();
/* Select the FLASH: Chip Select low */
FM25VXX_CS_LOW();
/* Send "0xff " instruction */
Flash_SendByte ( DUMMY_BYTE );
FM25VXX_CS_HIGH();
/* read flash id */
Flash_ReadID ( &flash_id );
flash_info.initialized = 1;
}
static uint8_t Flash_SendByte ( uint8_t byte )
{
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET){}
SPI_I2S_SendData(SPI2, byte);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET){}
return SPI_I2S_ReceiveData(SPI2);
}
u8 FM25V01_RDSR(void)//寄存器配置内容读取
{
u8 Reg_Status;
FM25VXX_CS_LOW();
Flash_SendByte(RDSR);
Reg_Status = Flash_SendByte(0x00);
FM25VXX_CS_HIGH();
return(Reg_Status);
}
static void Flash_WriteEnable ( void )
{
/* Select the FLASH: Chip Select low */
FM25VXX_CS_LOW();
/* Send Write Enable instruction */
Flash_SendByte ( WREN );
/* Deselect the FLASH: Chip Select high */
FM25VXX_CS_HIGH();
}
uint8_t Flash_ReadID ( jedec_id_t *id )
{
uint8_t *recv_buffer = ( uint8_t* ) id;
/* Select the FLASH: Chip Select low */
FM25VXX_CS_LOW();
/* Send "RDID " instruction */
Flash_SendByte ( RDID );
/* Read a byte from the FLASH */
*recv_buffer++ = Flash_SendByte ( DUMMY_BYTE );
/* Read a byte from the FLASH */
*recv_buffer++ = Flash_SendByte ( DUMMY_BYTE );
/* Read a byte from the FLASH */
*recv_buffer++ = Flash_SendByte ( DUMMY_BYTE );
/* Deselect the FLASH: Chip Select high */
FM25VXX_CS_HIGH();
return id->Manufacturer;
}
/**
* @brief Reads a block of data from the FLASH.
* @param buffer : pointer to the buffer that receives the data read
* from the FLASH.
* @param address : FLASH's internal address to read from.
* @param lenght : number of bytes to read from the FLASH.
* @retval : None
*/
void Flash_PageRead ( uint32_t address, uint8_t* buffer, uint32_t lenght )
{
/* Select the FLASH: Chip Select low */
FM25VXX_CS_LOW();
/* Send "Read from Memory " instruction */
Flash_SendByte ( READ );
/* Send ReadAddr high nibble address byte to read from */
Flash_SendByte ( ( address & 0xFF0000 ) >> 16 );
/* Send ReadAddr medium nibble address byte to read from */
Flash_SendByte ( ( address & 0xFF00 ) >> 8 );
/* Send ReadAddr low nibble address byte to read from */
Flash_SendByte ( address & 0xFF );
while ( lenght-- ) /* while there is data to be read */
{
/* Read a byte from the FLASH */
*buffer++ = Flash_SendByte ( DUMMY_BYTE );
/* Point to the next location where the byte read will be saved */
}
/* Deselect the FLASH: Chip Select high */
FM25VXX_CS_HIGH();
}
/**
* @brief Writes more than one byte to the FLASH with a single WRITE
* cycle(Page WRITE sequence). The number of byte can't exceed
* the FLASH page size.
* @param pBuffer : pointer to the buffer containing the data to be
* written to the FLASH.
* @param WriteAddr : FLASH's internal address to write to.
* @param NumByteToWrite : number of bytes to write to the FLASH,
* must be equal or less than "SPI_FLASH_PageSize" value.
* @retval : None
*/
void Flash_PageWrite ( uint32_t address, uint8_t* buffer, uint32_t lenght )
{
/* Select the FLASH: Chip Select low */
FM25VXX_CS_LOW();
Flash_WriteEnable();
/* Select the FLASH: Chip Select low */
FM25VXX_CS_HIGH();
Delay_us(2);
/* Select the FLASH: Chip Select low */
FM25VXX_CS_LOW();
/* Send "Write to Memory " instruction */
Flash_SendByte ( WRITE );
/* Send WriteAddr high nibble address byte to write to */
Flash_SendByte ( ( address & 0xFF0000 ) >> 16 );
/* Send WriteAddr medium nibble address byte to write to */
Flash_SendByte ( ( address & 0xFF00 ) >> 8 );
/* Send WriteAddr low nibble address byte to write to */
Flash_SendByte ( address & 0xFF );
/* while there is data to be written on the FLASH */
while ( lenght-- )
{
/* Send the current byte */
Flash_SendByte ( *buffer++ );
/* Point on the next byte to be written */
//buffer;
}
/* Deselect the FLASH: Chip Select high */
FM25VXX_CS_HIGH();
while (0x01 == (FM25V01_RDSR() & 0x01));
Flash_SendByte(WRDI);
}
flash_info_t *Flash_GetInfo ( void )
{
return &flash_info;
}
头文件:
#ifndef _FM25V01_H
#define _FM25V01_H
#include "stm32f4xx.h"
#include "include.h"
#define BANK0 0x00000
#define BANK1 0x20000
#define BANK2 0x30000
#define BANK01 0x01000
#define BANK02 0x00200
#define BANK03 0x00030
// FM25H20 Control Command
#define WREN 0x06 // Set Write Enable Latch
#define WRDI 0x04 // Write Disable
#define RDSR 0x05 // Read Status Register
#define WRSR 0x01 // Write Status Register
#define READ 0x03 // Read Memory Data.
#define FSTRD 0x0B // Fast Read Memory Data.
#define WRITE 0x02 // Write Memory Data
#define SLEEP 0xB9 // Enter Sleep Mode.
#define RDID 0x9F // Read Device ID.
#define SNR 0xC3 // Read S/N.
#define FM25VXX_CS_LOW() GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_RESET)
#define FM25VXX_CS_HIGH() GPIO_WriteBit(GPIOB,GPIO_Pin_12,Bit_SET)
typedef struct
{
u8 initialized;
u16 sector_size;
u16 sector_count;
u32 capacity;
} flash_info_t;
typedef struct
{
uint8_t Manufacturer; /* Manufacturer ID */
uint8_t Memory; /* Density Code */
uint8_t Capacity; /* Family Code */
uint8_t rev;
} jedec_id_t;
/* ========================= FUNCTION PROTOTYPES =========================== */
// private
void Flash_Init( void );
void Flash_SectorErase(uint32_t address,uint8_t state);
void Flash_PageRead(uint32_t address,uint8_t* buffer, uint32_t lenght);
void Flash_PageWrite(uint32_t address,uint8_t* buffer, uint32_t lenght);
extern jedec_id_t flash_id;
extern flash_info_t flash_info;
#endif
读写的时候只需要对应BANK直接读和写即可:
Flash_PageWrite ( BANK0, &Parame[0], 255 );
Flash_PageRead ( BANK0, &Parame[0], 255 );