自学内容网 自学内容网

铁电存储器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)!