MB85RC16铁电存储器stm32HAL库例程

该存储器主要应用于需要多次存储的场景,其他存储器有效次是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)
  {			
	
  }
}

上述代码就是完整代码,可以一个字节存储,也可以写成数组进行多个字节存储

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值