铁电存储器FM25CL64B简介及其驱动编写(基于STM32 hal库)
铁电存储器FM25CL64B简介及其驱动编写(基于STM32 hal库)
前言
FM25CL64B是赛普拉斯cypress出品的一款铁电存储器,这种存储器最大的优势是可以像RAM一样随机存储,和按字节写入,也可以像ROM一样掉电仍然可以保存数据,是一种相当优秀的新型存储器,但是容量不能做得很大,只适合保存一些重要数据。
一、FM25CL64B简介
FM25CL64B是一个串行F-RAM存储器。存储器阵列在逻辑上组织为8192×8位,并使用行业标准串行外围接口(SPI)总线进行访问。F-RAM的功能操作类似于串行闪存和串行EEPROM。FM25CL64B与具有相同引脚的串行闪存或EEPROM的主要区别在于F-RAM的卓越写入性能、高耐久性和低功耗。
①通信协议:
FM25CL64B可以由微控制器驱动,其SPI外围设备以以下两种模式之一运行,支持MSB格式,当通过将CS引脚设置为低电平来选择设备时,
设备会根据SCK引脚的状态检测SPI模式。
■ SPI Mode 0 (CPOL = 0, CPHA = 0)
■ SPI Mode 3 (CPOL = 1, CPHA = 1)
②数据读写:
■控制码:总线主控器可以向FM25CL64B发出六个操作码命令,这些操作码控制存储器执行的功能。
■读写状态寄存器:FM25CL64B的写保护功能是多层的,通过状态寄存器启用,状态寄存器位0和4-6固定为“0”;这些比特都不能被修改。位0是不必要的,因为F-RAM是实时写入的,从不繁忙,所以它读取为“0”。BP1和BP0控制软件写保护功能,是非易失性位。WEL标志表示写入启用锁存器的状态。尝试直接将WEL位写入状态寄存器对其状态没有影响。该位分别通过WREN和WRDI命令进行内部设置和清除。
初始化时候一般需要对状态寄存器写入0x00操作,但回读不一定0x00,回读为0x02为可写入。
■写数据:
1、在写入数据之前需要先发送8位写使能操作码(0x02),写使能是单向操作,芯片没有回应。
2、接下来的8位是地址码的高8位(低5位有效,由于本芯片是8K字节,也就是说,地址码的有效位是5+8=13位,所以本区段 只有低5位有效位。对于容量不同的芯片来说,有效位数不一样。
3、第3个8位,是地址码的低8位,均有效。
4、第4个8位,是数据位。具体时序如下
■读数据:
读数据和写数据时序一样,只不过先发送读操作码(0x03),接下来两个字节是13位地址码,然后从机返回对应地址的数据。具体时序如下
二、驱动代码
1.头文件
代码如下(示例):
#ifndef __FRAM_H__
#define __FRAM_H__
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
#include "spi_bsp.h"
//Status register X:be meaningless,0:default value
// BIT7 BIT6 BIT5 BIT4 BIT3 BIT2 BIT1 BIT0
// WPEN X(0) X(0) X(0) BP1 BP0 WEL X(0)
// WEL: 1 is write enable, 0 is prohibit write
// BP0,BP1: block protection
// WPEN:
#define FM25CL64_WREN_INST 0x06 //write enable(set WRSR bit),Before writing operations (WRSR and WRITE), this command must be issued first
#define FM25CL64_WRDI_INST 0x04 //write disable(clear WRSR bit),This operation will prohibit write operations (WRSR and WRITE), and even sending (WRSR and WRITE) thereafter will be invalid
#define FM25CL64_RDSR_INST 0x05 //read Status register
#define FM25CL64_WRSR_INST 0x01 //write Status register
#define FM25CL64_WRITE_INST 0x02 //write
#define FM25CL64_READ_INST 0x03 //read
#define FM25CL64_STATUS_REG 0x00
#define FM25CL64_INIT_INST 0x09
#define State 0x0200 //write data to Status register
//片选CS
#define FM25_Enable() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10, GPIO_PIN_RESET);
#define FM25_Disable() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10, GPIO_PIN_SET);
extern uint8_t fm25testdata[]; //spi read value
extern uint8_t fm25_bsp_Init();
extern uint8_t Read_FM25CL64_Byte(uint16_t addre);
extern uint8_t Write_FM25CL64_Byte(uint16_t addre, uint8_t dat);
extern uint8_t Read_FM25CL64_nByte(uint16_t addre, uint8_t *buff, uint16_t len);
extern void Write_FM25CL64_nByte(uint16_t addre, uint8_t *buff, uint16_t len);
#endif
2.c文件
代码如下(示例):
#include "fm25_bsp.h"
//测试数据
uint8_t fm25testdata[100] =
{
0x11, 0x00, 0x1D, 0x02, 0x6B, 0xE0, 0x0E, 0x0F, 0xBC, 0x00,
0x22, 0xF0, 0xAC, 0x3F, 0x0A, 0x0A, 0x07, 0x02, 0x65, 0x40,
0x33, 0x45, 0xEF, 0x0F, 0x11, 0x00, 0xFE, 0x00, 0xEC, 0x1B,
0x44, 0x8A, 0x10, 0x11, 0x25, 0xC3, 0x19, 0x02, 0x6F, 0x63,
0x55, 0x34, 0x01, 0x12, 0x6B, 0xFA, 0xFE, 0xF0, 0xAC, 0x0A,
0x66, 0xFE, 0x66, 0x7A, 0x44, 0x8A, 0x10, 0x11, 0x25, 0xE0,
0x77, 0xDA, 0x77, 0xF0, 0x55, 0x34, 0x01, 0x12, 0x6B, 0x0A,
0x88, 0x01, 0x88, 0x71, 0x66, 0xFE, 0x66, 0x7A, 0x1B, 0x00,
0x99, 0x86, 0x99, 0x93, 0x77, 0xDA, 0x77, 0xF0, 0x2F, 0xC3,
0xAA, 0x0E, 0xAA, 0xFE, 0x88, 0x01, 0x88, 0x71, 0x0B, 0xFA,
};
//1. read Status register
static uint8_t ReadState();
//2. ?????
static uint8_t Check_Start();
//3. ???
static void WriteEnable();
//4. ???
static void WriteState();
uint8_t fm25_bsp_Init()
{
//先对状态寄存器写入解锁,读出状态是否解锁写保护
WriteState();
if (ReadState() != 0x02)
{
return E_NOT_OK;
}
return E_OK;
}
//1. ???
static uint8_t ReadState()
{
uint8_t r;
uint8_t Rxbyte = 0;
WriteEnable();
FM25_Enable();
SPI_ReadWriteByte(SPI_2, FM25CL64_RDSR_INST, &Rxbyte);
SPI_ReadWriteByte(SPI_2, 0x00, &Rxbyte);
FM25_Disable();
return (Rxbyte);
}
//2. check read state
static uint8_t Check_Start()
{
uint8_t i = 0, r = 255;
do
{
r = ReadState();
i++;
}
while ((r & 0x01) && i < 254);
if (i >= 254)
{
return 1;
}
return 0;
}
//3. Write Enable
static void WriteEnable()
{
uint8_t r;
uint8_t Rxbyte = 0;
FM25_Enable();
r = SPI_ReadWriteByte(SPI_2, FM25CL64_WREN_INST, &Rxbyte);
FM25_Disable();
}
//4. Write Status register
void WriteState()
{
uint8_t r;
uint8_t Rxbyte = 0;
WriteEnable();
FM25_Enable();
SPI_ReadWriteByte(SPI_2, FM25CL64_WRSR_INST, &Rxbyte);
SPI_ReadWriteByte(SPI_2, FM25CL64_STATUS_REG, &Rxbyte);
FM25_Disable();
Check_Start();
}
//5. read a byte
uint8_t Read_FM25CL64_Byte(uint16_t addre)
{
uint8_t r;
uint8_t dat;
uint8_t Rxbyte = 0;
FM25_Enable();
SPI_ReadWriteByte(SPI_2, FM25CL64_READ_INST, &Rxbyte);
SPI_ReadWriteByte(SPI_2, (addre & 0xFF00) >> 8, &Rxbyte);
SPI_ReadWriteByte(SPI_2, (addre & 0x00FF), &Rxbyte);
SPI_ReadWriteByte(SPI_2, 0x00, &dat);
FM25_Disable();
return (dat);
}
//6. read n byte
uint8_t Read_FM25CL64_nByte(uint16_t addre, uint8_t *buff, uint16_t len)
{
uint8_t r;
uint8_t dat;
uint8_t Rxbyte = 0;
WriteEnable();
FM25_Enable();
SPI_ReadWriteByte(SPI_2, FM25CL64_READ_INST, &Rxbyte);
SPI_ReadWriteByte(SPI_2, (addre & 0xFF00) >> 8, &Rxbyte);
SPI_ReadWriteByte(SPI_2, (addre & 0x00FF), &Rxbyte);
for (int i = 0; i < len; i++)
{
SPI_ReadWriteByte(SPI_2, 0x00, &buff[i]);
}
FM25_Disable();
return (dat);
}
//7. Write a byte
uint8_t Write_FM25CL64_Byte(uint16_t addre, uint8_t dat)
{
uint8_t r;
uint8_t Rxbyte = 0;
WriteEnable();
FM25_Enable();
SPI_ReadWriteByte(SPI_2, FM25CL64_WRITE_INST, &Rxbyte);
SPI_ReadWriteByte(SPI_2, (addre & 0xFF00) >> 8, &Rxbyte);
SPI_ReadWriteByte(SPI_2, (addre & 0x00FF), &Rxbyte);
SPI_ReadWriteByte(SPI_2, dat, &Rxbyte);
FM25_Disable();
return (dat);
}
//8. Write n byte
void Write_FM25CL64_nByte(uint16_t addre, uint8_t *buff, uint16_t len)
{
uint8_t r;
uint8_t Rxbyte = 0;
WriteEnable();
FM25_Enable();
SPI_ReadWriteByte(SPI_2, FM25CL64_WRITE_INST, &Rxbyte);
SPI_ReadWriteByte(SPI_2, (addre & 0xFF00) >> 8, &Rxbyte);
SPI_ReadWriteByte(SPI_2, (addre & 0x00FF), &Rxbyte);
for (int i = 0; i < len; i++)
{
SPI_ReadWriteByte(SPI_2, buff[i], &Rxbyte);
}
FM25_Disable();
}
SPI_ReadWriteByte()函数是自己实现的SPI的收发单字节函数,参数分别为SPI设备号、发送字节内容和接收返回字节的变量的地址。
总结
FM25CL64B的时序和代码驱动实现相对比较简单,唯一需要注意的是需要先通过状态寄存器解锁写保护,否则无法写入。
原文地址:https://blog.csdn.net/Yin_w/article/details/144971150
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!