1.芯片简介
铁电存储器F-RAM,2Mbit(256K * 8) SPI(Up to 40 MHz)
项目有用到,做个mark,有错误请指正。
开发环境STM32F407
存储器地址范围00000H~3FFFFH,共2Mbit (256k * 8)bit,
其中256k即为 256 * 1024 = 262144 个byte(0x4 00 00,因此存储器最后字节为0x3 ff ff)
即 2Mbit
=(256 * 1024) * 8 个bit
= 262144 byte * 8bit
= 2097152 bit 即2Mbit
2.引脚定义及接线
引脚较少,具体可参考datasheet中引脚定义和接线注意事项。
其中WP为写入保护,我没有用到,因此拉高。
CS为片选。
HOLD用来在CPU芯片需要中断当前铁电操作,进入其他任务时使用。未使用,拉高。
3.寄存器相关配置
3.1 命令码
使用SPI发送相应命令码,来进行相关操作
3.2 状态寄存器
3.3 存储器地址范围
3.4 读写操作注意事项
MSB先写入或读取。
写入及读取操作不做详细叙述,多看datasheet。
3.驱动代码
3.1 FM25V20.H
#ifndef _FM25V20_H_
#define _FM25V20_H_#include "stm32f4xx.h"#define FM_CS_1 GPIO_SetBits(GPIOA, GPIO_Pin_4);//片选高
#define FM_CS_0 GPIO_ResetBits(GPIOA, GPIO_Pin_4);//片选低#define FMStartAddr 0x0000C //自定义开始使用的地址#define WREN 0x06 //使能写
#define WRDI 0x04 //失能写
#define RDSR 0x05 //读状态寄存器
#define WRSR 0x01 //写状态寄存器
#define READ 0x03 //读数据
#define FSTRD 0x0B //快速读数据
#define WRITE 0x02 //写数据
#define RDID 0x9F //读设备ID
#define DUMMY_BYTE 0xFF //虚拟字节void FMGetId(void);
void FM25V20_Init(void);
void FMWrite(uint8_t *buf,uint16_t size,uint32_t addr);
void FMRead(uint8_t *databuffer,uint16_t datasize,uint32_t address);#endif
3.2 FM25V20.C
void FM25V20_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;/*Enable GPIOA 片选*/RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉GPIO_Init(GPIOA, &GPIO_InitStructure);/*SPI初始化*/SPI1_Init();/*拉高片选,等待命令*/FM_CS_1; //Chip DeSelect
}//获取ID 9个字节
/* 71-16(56bits) Manufacturer ID15-13(3 bits) Family12-08(5 bits) Density07-06(2 bits) Sub05-03(3 bits) Rev02-00(3 bits) Rsvd */
uint8_t FMID[8];//设备ID
void FMGetId(void)
{uint8_t i;FM_CS_0; //置CS低选中SPI1_ReadWriteByte(RDID); //读ID功能码for(i = 0; i < 8; i ++){FMID[i] = SPIReadByte();}FM_CS_1; //置CS高取消选中
}
/******************************************
** 函数名称:uint8 FMReadStatus(void)
** 功能描述:查询FM25V20状态
** 参数说明:无
** 参数返回:返回状态字节
******************************************/
static uint8_t FMReadStatus(void)
{uint8_t status;FM_CS_0; //置CS低选中SPI1_ReadWriteByte(RDSR);status = SPI1_ReadWriteByte(DUMMY_BYTE);FM_CS_1; //置CS高取消选中return status;
}
/******************************************
** 函数名称:FMWriteEnable
** 功能描述:写使能
** 参数说明:无
** 参数返回:1-成功 0-失败
*******************************************/
static void FMWriteEnable(void)
{FM_CS_0; //置CS低选中SPI1_ReadWriteByte(WREN);//发送写使能FM_CS_1; //置CS高取消选中
}
/******************************************
** 函数名称:FMWriteDisable
** 功能描述:写禁能
** 参数说明:无
** 参数返回:1-成功 0-失败
*******************************************/
static void FMWriteDisable(void)
{FM_CS_0; //置CS低选中SPI1_ReadWriteByte(WRDI);FM_CS_1; //置CS高取消选中
}
/******************************************************************************
** 函数名称:FMWrite
** 功能描述:向指定地址写入指定数量的字节
** 参数说明:数据缓存区,字节数,起始地址
** 参数返回:无
******************************************************************************/
void FMWrite(uint8_t *buf, uint16_t size, uint32_t addr)
{uint16_t waittimes = 0;FMWriteEnable();//写使能delayus(20);//延时,采用计数法粗略延时即可if(FMReadStatus() & 0x02)//¼ì²éÊÇ·ñ³É¹¦Ê¹ÄÜд bit1-WEL 0ΪдʧÄÜ£¬1ΪдʹÄÜ{if(buf != 0){FM_CS_0; //置CS低选中SPI1_ReadWriteByte(WRITE);SPI1_ReadWriteByte((uint8_t)(addr >> 16));SPI1_ReadWriteByte((uint8_t)(addr >> 8));SPI1_ReadWriteByte((uint8_t) addr);while(size--){SPI1_ReadWriteByte(*buf++);}while(waittimes<1000) //等待器件写完{waittimes++;} FM_CS_1; //置CS高取消选中 }}FMWriteDisable();//写禁能
}/*****************************************************************
** 函数名称:FMRead
** 功能描述:从指定地址读取指定数量的字节
** 参数说明:数据缓存区,字节数,起始地址
** 参数返回:无
******************************************************************/
void FMRead(uint8_t *buf, uint16_t size, uint32_t addr)
{uint16_t i;if(buf != 0){FM_CS_0;SPI1_ReadWriteByte(READ);//读功能码SPI1_ReadWriteByte((uint8_t)(addr >> 16));//发送高位地址SPI1_ReadWriteByte((uint8_t)(addr >> 8));SPI1_ReadWriteByte((uint8_t)addr);for(i = 0; i < size; i++){buf[i] = SPI1_ReadWriteByte(DUMMY_BYTE);}FM_CS_1; //置CS高取消选中 }
}
/*****************************************************************
** 函数名称:FMFastRead
** 功能描述:快速从指定地址读取指定数量的字节
** 参数说明:数据缓存区,字节数,起始地址
** 参数返回:无
******************************************************************/
uint8_t FMFastRead(uint8_t *buf, uint16_t size, uint32_t addr)
{uint16_t i;if(buf != 0){FM_CS_0;SPI1_ReadWriteByte(FSTRD);//快速读功能码SPI1_ReadWriteByte((uint8_t)(addr >> 16));//发送高位地址SPI1_ReadWriteByte((uint8_t)(addr >> 8));SPI1_ReadWriteByte((uint8_t)addr);SPI1_ReadWriteByte(DUMMY_BYTE);//虚拟字节for(i = 0; i < size; i++){buf[i] = SPI1_ReadWriteByte(DUMMY_BYTE);}FM_CS_1; //置CS高取消选中 return 1;}return 0;
}
3.3 SPI.H
#ifndef _SPI_H_
#define _SPI_H_#include "stm32f4xx.h"void SPI1_Init(void);
uint8_t SPI1_ReadWriteByte(uint8_t TxData);#endif
3.4 SPI.C
//SPI1初始化
void SPI1_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//使能SPI1时钟//复用GPIO_PinAFConfig(GPIOA , GPIO_PinSource5, GPIO_AF_SPI1);GPIO_PinAFConfig(GPIOA , GPIO_PinSource6, GPIO_AF_SPI1);GPIO_PinAFConfig(GPIOA , GPIO_PinSource7, GPIO_AF_SPI1);//GPIOA 5 6 7 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;//PA5 6 7GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOSPI_I2S_DeInit(SPI1);SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;//全双工 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;//STM32为主机SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟空闲状态为低电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第1个跳变沿采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;//波特率分频值SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //MSB位开始传输SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC计算的多项式SPI_Init(SPI1, &SPI_InitStructure); //初始化SPI_Cmd(SPI1, ENABLE); //使能
}
/*****************************************
**函数名称:SPI1_ReadWriteByte
**功能描述:SPIx读写一个字节
**参数说明:写入字节
**参数返回:读取到的字节
*****************************************/
uint8_t SPI1_ReadWriteByte(uint8_t TxData)
{uint8_t returnData;while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET){}//等待发送区空SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个byte数据while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET){} //等待接收完一个bytereturnData = SPI_I2S_ReceiveData(SPI1);return returnData;//返回读取到的值
}
4.示例
4.1 写入
将变量 uint8_t param1 = 0x01 写入到存储器0x00002字节位置
FMWrite((uint8_t *)¶m1 , 1, 0x00002);
将变量 uint16_t param2 = 0x1122 写入到存储器0x00000开始的两个字节(及0x00000~0x00001)
FMWrite((uint8_t *)¶m2 , 2, 0x00000);
4.2 读取
读取0x00000开始的3个字节到 uint8_t parambuf[3]
FMRead(parambuf, 3, 0x00000);