该存储器主要应用于需要多次存储的场景,其他存储器有效次是10万次,而该存储器的存储次数是10的10次方次,可以有效的解决频繁存储的问题。
以下是,c文件:
#include "I2C_FRAM.h"
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
u8 FRAM_ADDRESS;
/* Private function prototypes -----------------------------------------------*/
#define I2C_Speed 100000
#define I2C1_SLAVE_ADDRESS7 0xA0
#define I2C_PageSize 256
void FramSdaInputInit(void);
void FramSdaOutputInit(void);
u8 I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite);
u8 I2C_FRAM_BufferRead(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead);
/* Private functions ---------------------------------------------------------*/
/**/
/**
* @brief 初始化FRAM端口
* @param None
* @retval : None
*/
void Fram_GpioInitial(void)
{
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
//设置SDA为输出
FramSdaOutputInit();
//写保护禁止
FRAM_WP_Disable();
}
/**
* @brief 初始化FRAM_SDA端口为输入
* @param None
* @retval : None
*/
void FramSdaInputInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
/**
* @brief 初始化FRAM_SDA端口为输出
* @param None
* @retval : None
*/
void FramSdaOutputInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
/**
* @brief 延时函数
* @param None
* @retval : None
*/
void I2C_delay(void)
{
u32 i=0xf; //这里可以优化速度,经测试最低到5还能写入
// delay_us(50);
while(i)
{
i--;
}
}
void I2C_Start(void)
{
FRAM_SCL_HIGH();
FRAM_SDA_HIGH();
I2C_delay();
FRAM_SDA_LOW();
I2C_delay();
FRAM_SCL_LOW();
I2C_delay();
}
void I2C_Stop(void)
{
FRAM_SCL_HIGH();
FRAM_SDA_LOW();
I2C_delay();
FRAM_SDA_HIGH();
I2C_delay();
FRAM_SCL_LOW();
}
void I2C_Ack(void)
{
FRAM_SCL_LOW();
I2C_delay();
FRAM_SDA_LOW();//ACK
FRAM_SCL_HIGH();
I2C_delay();
FRAM_SCL_LOW();
I2C_delay();
}
void I2C_NoAck(void)
{
FRAM_SCL_LOW();
I2C_delay();
FRAM_SDA_HIGH();//NoACK
I2C_delay();
FRAM_SCL_HIGH();
I2C_delay();
FRAM_SCL_LOW();
I2C_delay();
}
u8 I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
{
FRAM_SCL_LOW();
I2C_delay();
FRAM_SCL_HIGH();
I2C_delay();
if(RD_FRAM_SDA())
{
FRAM_SCL_LOW();
I2C_delay();
return 0;
}
else
{
FRAM_SCL_LOW();
I2C_delay();
return 1;
}
}
void I2C_SendByte(u8 SendByte) //数据从高位到低位//
{
u8 i=8;
FRAM_SCL_LOW();
I2C_delay();
while(i--)
{
if(SendByte&0x80)
FRAM_SDA_HIGH();
else
FRAM_SDA_LOW();
FRAM_SCL_HIGH();
I2C_delay();
FRAM_SCL_LOW();
I2C_delay();
SendByte<<=1;
}
}
u8 I2C_ReceiveByte(void) //数据从高位到低位//
{
u8 i=8;
u8 ReceiveByte=0;
while(i--)
{
ReceiveByte<<=1;
FRAM_SCL_LOW();
I2C_delay();
FRAM_SCL_HIGH();
I2C_delay();
if(RD_FRAM_SDA())
{
ReceiveByte|=0x01;
}
}
FRAM_SCL_LOW();
I2C_delay();
return ReceiveByte;
}
/**
* @brief 写FRAM
* @param pBuffer 准备写入的数据缓冲地址
* WriteAddr 准备写入FRAM地址
* NumByteToWrite 准备写入长度
* @retval 0-正确,1-错误
*/
u8 I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite)
{
u8 Addr = 0, count = 0;
Addr = WriteAddr / I2C_PageSize;
count = WriteAddr % I2C_PageSize;
FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7;
//开始信号
FramSdaOutputInit();
I2C_Start();
//发送写命令
FramSdaOutputInit();
I2C_SendByte(FRAM_ADDRESS);
FramSdaInputInit();
if(!I2C_WaitAck())
return 1;
//设置FRAM地址高8位
FramSdaOutputInit();
I2C_SendByte(Addr);
FramSdaInputInit();
if(!I2C_WaitAck())
return 1;
//设置FRAM地址低8位
FramSdaOutputInit();
I2C_SendByte(count);
FramSdaInputInit();
if(!I2C_WaitAck())
return 1;
//发送数据
while(NumByteToWrite--)
{
FramSdaOutputInit();
I2C_SendByte(* pBuffer);
FramSdaInputInit();
if(!I2C_WaitAck())
return 1;
pBuffer++;
}
//停止信号
FramSdaOutputInit();
I2C_Stop();
return 0;
}
/**
* @brief 读FRAM
* @param pBuffer 存储读出数据缓冲地址
* WriteAddr 准备读出FRAM地址
* NumByteToWrite 准备读出长度
* @retval 0-正确,1-错误
*/
u8 I2C_FRAM_BufferRead(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead)
{
u8 Addr = 0, count = 0;
Addr = ReadAddr / I2C_PageSize;
count = ReadAddr % I2C_PageSize;
FRAM_ADDRESS = I2C1_SLAVE_ADDRESS7;
//开始信号
FramSdaOutputInit();
I2C_Start();
//发送写命令
FramSdaOutputInit();
I2C_SendByte(FRAM_ADDRESS);
FramSdaInputInit();
if(!I2C_WaitAck())
return 1;
//设置FRAM地址高8位
FramSdaOutputInit();
I2C_SendByte(Addr);
FramSdaInputInit();
if(!I2C_WaitAck())
return 1;
//设置FRAM地址低8位
FramSdaOutputInit();
I2C_SendByte(count);
FramSdaInputInit();
if(!I2C_WaitAck())
return 1;
//停止信号
FramSdaOutputInit();
I2C_Stop();
//开始信号
FramSdaOutputInit();
I2C_Start();
//发送读命令
FramSdaOutputInit();
I2C_SendByte(FRAM_ADDRESS | 0x01);//ReadCOM
FramSdaInputInit();
if(!I2C_WaitAck())
return 1;
//读数据
while(NumByteToRead)
{
FramSdaInputInit();
*pBuffer = I2C_ReceiveByte();
FramSdaOutputInit();
if(NumByteToRead == 1)
I2C_NoAck();
else
I2C_Ack();
NumByteToRead--;
pBuffer++;
}
//停止信号
FramSdaOutputInit();
I2C_Stop();
return 0;
}
以下是.h文件
#ifndef __i2C_FRAM_H
#define __i2C_FRAM_H
#include "main.h"
#define FRAM_WP_Disable() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET)
#define FRAM_WP_Enable() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET)
#define FRAM_SCL_LOW() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET)
#define FRAM_SCL_HIGH() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET)
#define FRAM_SDA_LOW() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_RESET)
#define FRAM_SDA_HIGH() HAL_GPIO_WritePin(GPIOD, GPIO_PIN_0, GPIO_PIN_SET)
#define RD_FRAM_SDA() HAL_GPIO_ReadPin(GPIOD,GPIO_PIN_0)
void Fram_GpioInitial(void);
u8 I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite);
u8 I2C_FRAM_BufferRead(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead);
#endif /* __BD2013_FRAM_H */
以下是主程序:
#include "main.h"
#include "I2C_FRAM.h"
//void Fram_GpioInitial(void);
//u8 I2C_FRAM_BufferWrite(u8* pBuffer, u16 WriteAddr, u16 NumByteToWrite);
//u8 I2C_FRAM_BufferRead(u8* pBuffer, u16 ReadAddr, u16 NumByteToRead);
u8 test='1';
u8 test1=0;
//系统初始化
void SystemInit(void)
{
HAL_Init(); //复位所有系统外设,初始化FLASH接口和系统心跳时钟
SystemClock_Config(); //初始化系统时钟,所有时钟都是24MHZ
delay_init(); //延迟函数初始化
//UART
MX_IWDG_Init(); //看门狗初始化
//USART1初始化 9600 N 8 1 RS485对外通讯
MX_GPIO_Init(); //系统IO口初始化
MX_TIM6_Init(); //500MS通用定时器初始化
Fram_GpioInitial();
I2C_FRAM_BufferWrite(&test,0xA1,1);
I2C_FRAM_BufferRead(&test1,0xA1,1);
//读取CPU内部EEPROM系统默认参数
}
u16 xxxxxxxxxxx=0;
int main(void)
{
SystemInit();
while (1)
{
}
}
上述代码就是完整代码,可以一个字节存储,也可以写成数组进行多个字节存储