FM25V20A使用记录

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 ID
	15-13(3 bits) Family
	12-08(5 bits) Density
	07-06(2 bits) Sub
	05-03(3 bits) Rev
	02-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 7
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO

    SPI_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){} //等待接收完一个byte
    returnData = SPI_I2S_ReceiveData(SPI1);

	return returnData;//返回读取到的值
}

4.示例

4.1 写入

将变量   uint8_t param1 = 0x01  写入到存储器0x00002字节位置

FMWrite((uint8_t *)&param1 , 1, 0x00002);

 

将变量  uint16_t param2 = 0x1122  写入到存储器0x00000开始的两个字节(及0x00000~0x00001)

FMWrite((uint8_t *)&param2 , 2, 0x00000);

4.2 读取

读取0x00000开始的3个字节到 uint8_t parambuf[3]

FMRead(parambuf, 3, 0x00000);

 

 

 

 

 

 

 

  • 5
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
FM25V20是一种非易失性存储器,它具有容量为2M位的存储空间。下面是一个FM25V20读写的简单代码示例: 首先,我们需要定义一些必要的引脚和变量。FM25V20有8个引脚,包括CS(片选)、SCK(时钟)、SI(串行数据输入)、SO(串行数据输出)、WP(写保护)、HOLD(暂停)等引脚。我们还需要定义一个数据缓冲区来存储从FM25V20读取或写入的数据。 #include <SPI.h> // 定义引脚 #define CS_PIN 10 // 片选 #define SCK_PIN 13 // 时钟 #define SI_PIN 11 // 串行数据输入 #define SO_PIN 12 // 串行数据输出 #define WP_PIN 6 // 写保护 #define HOLD_PIN 7 // 暂停 // 定义缓冲区 byte dataBuffer[256]; 接下来,我们需要初始化SPI接口和定义FM25V20的一些特殊功能,如写保护和暂停。 void setup() { // 初始化SPI接口 SPI.begin(); SPI.setDataMode(SPI_MODE3); // 设置SPI模式为模式3(时钟空闲低电平,数据在上升沿采样) // 设置引脚模式 pinMode(CS_PIN, OUTPUT); pinMode(SCK_PIN, OUTPUT); pinMode(SI_PIN, OUTPUT); pinMode(SO_PIN, INPUT); pinMode(WP_PIN, OUTPUT); pinMode(HOLD_PIN, OUTPUT); // 解除写保护 digitalWrite(WP_PIN, HIGH); // 恢复暂停 digitalWrite(HOLD_PIN, HIGH); } 接下来,我们可以实现一些读写函数来操作FM25V20。 // 从FM25V20读取数据 void readData(int address, int length) { digitalWrite(CS_PIN, LOW); // 使能片选 // 发送读取命令和地址 SPI.transfer(0x03); // 发送读取命令 SPI.transfer((address >> 8) & 0xFF); // 发送地址高位 SPI.transfer(address & 0xFF); // 发送地址低位 // 读取数据 for (int i = 0; i < length; i++) { dataBuffer[i] = SPI.transfer(0x00); // 发送0x00获取数据 } digitalWrite(CS_PIN, HIGH); // 禁用片选 } // 向FM25V20写入数据 void writeData(int address, int length) { digitalWrite(CS_PIN, LOW); // 使能片选 // 发送写入命令和地址 SPI.transfer(0x02); // 发送写入命令 SPI.transfer((address >> 8) & 0xFF); // 发送地址高位 SPI.transfer(address & 0xFF); // 发送地址低位 // 写入数据 for (int i = 0; i < length; i++) { SPI.transfer(dataBuffer[i]); // 写入数据 } digitalWrite(CS_PIN, HIGH); // 禁用片选 } 这些是FM25V20读写的基本代码示例,你可以根据自己的需求进一步调整和优化。使用这些代码示例,你可以轻松实现对FM25V20存储器的读写操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值