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 *)&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);

FM25V20A使用记录相关推荐

  1. mysql建立联合索引,mysql建立唯一键,mysql如何解决重复记录联合索引

    在项目中,常常要用到联合唯一   在一些配置表中,一些列的组合成为一条记录.   比如,在游戏中,游戏的分区和用户id会形成一条记录.(比如,一个qq用户可以在艾欧尼亚.德玛西亚创建两个账号) 添加联 ...

  2. 实现 连续15签到记录_MySQL和Redis实现用户签到,你喜欢怎么实现?

    现在的网站和app开发中,签到是一个很常见的功能 如微博签到送积分,签到排行榜 微博签到 如移动app ,签到送流量等活动, 移动app签到 用户签到是提高用户粘性的有效手段,用的好能事半功倍! 下面 ...

  3. 记录一次http请求失败的问题分析

    问题背景 当前我有一个基于Flask编写的Restful服务,由于业务的需求,我需要将该服务打包成docker 镜像进行离线部署,原始服务的端口是在6661端口进行开启,为了区分,在docker中启动 ...

  4. Pytorch学习记录-torchtext和Pytorch的实例( 使用神经网络训练Seq2Seq代码)

    Pytorch学习记录-torchtext和Pytorch的实例1 0. PyTorch Seq2Seq项目介绍 1. 使用神经网络训练Seq2Seq 1.1 简介,对论文中公式的解读 1.2 数据预 ...

  5. LeetCode简单题之学生出勤记录 I

    题目 给你一个字符串 s 表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤.迟到.到场).记录中只含下面三种字符: 'A':Absent,缺勤 'L':Late,迟到 'P':Pre ...

  6. 关于TVM的点滴记录

    关于TVM的点滴记录

  7. MySql数据库Update批量更新与批量更新多条记录的不同值实现方法

    批量更新 mysql更新语句很简单,更新一条数据的某个字段,一般这样写: UPDATE mytable SET myfield = 'value' WHERE other_field = 'other ...

  8. 记录篇,自己在项目中使用过的。

    图片选择器,6.0已经适配过,类似qq空间上传 点击打开链接_胡小牧记录 下面是效果图: PictureSelector PhotoPicker 类似qq空间发布心情. 点击打开链接 BubbleSe ...

  9. HTML5与CSS3权威指南之CSS3学习记录

    title: HTML5与CSS3权威指南之CSS3学习记录 toc: true date: 2018-10-14 00:06:09 学习资料--<HTML5与CSS3权威指南>(第3版) ...

最新文章

  1. html支持了3种类型的按钮即,第3章HTML5.ppt
  2. Unable to execute dex: Multiple dex files define Lcom/myapp/R$array;
  3. 【网络】HTTP2.0新特性
  4. 山东春考计算机专科学校排名,山东春考本科专科学校有哪些
  5. 浅谈数据中心集成的优势
  6. Hadoop安装过程
  7. Spark SQL之queryExecution运行流程解析Logical Plan(三)
  8. Dropbox 官方中文版!最优秀实用的免费跨平台文件网络同步网盘云存储服务
  9. 用w32tm设置服务器时间同步
  10. 命令行插入时显示不存在_成年人的世界里,不存在“容易”两个字没人心疼时自己要学会坚强...
  11. vue 一个组件内多个弹窗_使用vue实现各类弹出框组件
  12. 微软语音识别技术屡破世界纪录的秘密都在这里了
  13. Centos7安装官方JDK
  14. 易筋SpringBoot 2.1 | 第三十三篇:SpringBoot Reactor响应式编程实战二 Redis Lettuce
  15. 咸鱼の软构实验感想(1)
  16. orcale中like用法详解
  17. Micro-expression recognition with supervised contrastive learning基于对比监督学习的微表情识别
  18. S71200西门子PLC一个设计的接线图
  19. Auto.js网盘下载加打包插件
  20. 设计实现信用卡用户定时还款功能

热门文章

  1. 工业机器人编程语言c,非常实用的工业机器人编程语言有哪些?这些编程好用吗?...
  2. redis集群密码设置
  3. linux下adb传输文件,使用adb在电脑和手机间传文件,adb手机传文件
  4. 蜡烛人游戏第1-4关应该怎么通关呢?
  5. 一款小众、免费但好用的音量控制软件:EarTrumpet
  6. 排序二叉树,平衡二叉树和红黑树的概念以及相关的操作讲解
  7. 设置手动翻译,浏览器英文页面
  8. sqlsessionfactory和sqlsession
  9. 基于FireBeetle 2 ESP32-E开发板的LVGL移植及传感器显示(Arduino+TFT_eSPI+LVGL)
  10. 不是管理员计划任务不执行_为执行任务而不是老板