STM32存储左右互搏 I2C总线读写FRAM MB85RC16

news2024/11/25 2:29:44

STM32存储左右互搏 I2C总线读写FRAM MB85RC16

在较低容量存储领域,除了EEPROM的使用,还有铁电存储器FRAM的使用,相对于EEPROM, 同样是非易失性存储单元,FRAM支持更高的访问速度, 其主要优点为没有EEPROM持续写操作跨页地址需要变换的要求,没有写之后的延时等待要求。MB85RC16是2K Byte(16K bit)的FRAM,能够按字节进行写入且没有写入等待时间。其管脚功能兼容相应容量的EEPOM:
在这里插入图片描述
I2C总线访问的FRAM更大容量的型号还有MB85RC128及MB85RC256等。
这里介绍STM32访问FRAM MB85RC16的例程。采用STM32CUBEIDE开发平台,以STM32F401CCU6芯片为例,通过STM32 I2C硬件电路实现读写操作,通过USB虚拟串口进行控制。

STM32工程配置

首先建立基本工程并设置时钟:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置硬件I2C接口,STM32F401CCU6的I2C快速模式只支持400KHz速率:
在这里插入图片描述
在这里插入图片描述

中断不用开:
在这里插入图片描述

然后配置USB虚拟串口:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
保存并生成初始工程代码:
在这里插入图片描述

STM32工程代码

USB虚拟串口的使用参考:STM32 USB VCOM和HID的区别,配置及Echo功能实现(HAL)

这里的测试逻辑比较简单,当USB虚拟串口收到任何数据时,STM32在内部对MB85RC16写入从USB虚拟串口收到的数据,然后再回读出来,通过USB虚拟串口发送出去。

USB接收数据的代码:
在这里插入图片描述

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
	extern uint8_t cmd;
	extern uint8_t * RData;
	extern uint32_t RDataLen;

	RData = Buf;
	RDataLen = *Len;
	cmd = 1;

  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

MB85RC16的设备默认访问地址为0xA0, MB85RC16的存储单元地址访问略为特殊,11位地址分为两部分,高位的3位放置于I2C设备默认访问地址的第3~第1位,I2C设备默认访问地址第0位仍然为读写控制位,由于采用硬件I2C控制,库函数自行通过识别调用的是发送还是接收函数对第0位进行发送前设置,因此,不管是调用库函数的I2C写操作还是读操作,提供的地址相同。11位地址的低8位通过在发送设备地址后的作为跟随的第一个字节发送。

完成的main.c文件代码如下:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
//Written by Pegasus Yu in 2023
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usb_device.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <string.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t cmd=0;          //for status control
uint8_t * RData;        //USB rx data pointer
uint32_t RDataLen;      //USB rx data length
uint8_t * TData;        //USB tx data pointer
uint32_t TDataLen;      //USB tx data length

uint16_t MB85RC16_Access_Addr = 0;   //FRAM MB85RC16 access address (11-bit)

#define MB85RC16_Default_I2C_Addr 0xA0


void MB85RC16_Write(uint32_t addr, uint8_t * data, uint32_t len)
{
	uint8_t MB85RC16_I2C_Addr;

	MB85RC16_I2C_Addr = MB85RC16_Default_I2C_Addr | ((addr>>8)<<1); //high 3-bit access address placed into I2C address

	uint8_t TD[len+1];
	TD[0] = addr & 0x00FF;  //low 8-bit access address placed into I2C first data

	memcpy(TD+1, data, len);
	HAL_I2C_Master_Transmit(&hi2c1, MB85RC16_I2C_Addr, TD, len+1, 2700);  //Write data
}

void MB85RC1M_Read(uint32_t addr, uint8_t * data, uint32_t len)
{
	uint8_t MB85RC16_I2C_Addr;

	MB85RC16_I2C_Addr = MB85RC16_Default_I2C_Addr | ((addr>>8)<<1); //high 3-bit access address placed into I2C address

	uint8_t RA[1];
	RA[0] = addr & 0x00FF;  //low 8-bit access address placed into I2C first data

	HAL_I2C_Master_Transmit(&hi2c1, MB85RC16_I2C_Addr, &RA[0], 1, 2700); //Write address for read
	HAL_I2C_Master_Receive(&hi2c1, MB85RC16_I2C_Addr, data, len, 2700); //Read data

}
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	if(cmd==1)
	{
		cmd=0;
		MB85RC16_Access_Addr = 0;  //Set FRAM access address here

		MB85RC16_Write(MB85RC16_Access_Addr, RData, RDataLen);

		TDataLen = RDataLen;
		uint8_t TD[TDataLen];
		TData = TD;
		MB85RC1M_Read(MB85RC16_Access_Addr, TData , TDataLen);

		CDC_Transmit_FS(TData, TDataLen);

	}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */


STM32范例测试

上述范例的测试效果如下:
在这里插入图片描述

STM32例程下载

STM32F401CCU6 I2C总线读写FRAM MB85RC16例程

–End–

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/970265.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

支付宝商户池

随着社会的发展&#xff0c;第三方支付公司的规章制度越来越完善&#xff0c;支付产品的迭代更新速度也越来越快。华北、白条等贷款工具的出现使信用卡失去了大部分的市场份额。我还记得盛大一卡通、俊旺一卡通等流行的常用卡产品现在逐渐被在线微信支付宝产品所取代。 “支付…

深入浅出AXI协议(4)——猝发传输

一、前言 在之前的文章中&#xff0c;我们着重介绍了关于AXI4的握手协议它可以使得传输的双方都可以自如地控制传输的速率&#xff0c;我们主要介绍了握手协议出现的3种可能情况。然后对于AXI4交易通信的握手信号的关系做出了介绍&#xff1a;&#xff08;1&#xff09;在AXI4互…

软件产品登记测试

1. 服务流程 2. 服务内容 对功能性、易用性、可移植性三个特性、五个子特性进行测试。通过测试检测表明软件功能基本实现&#xff0c;运行基本稳定&#xff0c;操作方便&#xff0c;用户手册描述完整正确&#xff0c;是否达到软件产品登记测试规范的要求。 3. 周期 实施测试…

Docker安装部署ElasticSearch(ES)

文章目录 安装前准备创建挂载目录授权相关权限创建elasticsearch.yml文件 拉取镜像运行容器查看运行情况测试 安装前准备 创建挂载目录 用于在宿主机挂载日志&#xff0c;数据等内容 创建/opt/es/data目录 创建/opt/es/logs目录 创建/opt/es/plugins目录 创建/opt/es/conf目录…

三维模型OBJ格式轻量化压缩处理重难点分析

三维模型OBJ格式轻量化压缩处理重难点分析 三维模型的OBJ格式轻量化压缩处理是一个复杂且具有挑战性的任务&#xff0c;涉及到多个重难点。以下是对三维模型OBJ格式轻量化压缩处理的重难点进行分析&#xff1a; 1、保持视觉质量&#xff1a; 在进行轻量化压缩的过程中&#x…

抖音书单视频怎么制作?这些方法很简单

抖音作为一款热门的短视频应用程序&#xff0c;已经成为了一个广泛传播知识和信息的平台。其中&#xff0c;抖音书单视频是一种很受欢迎的形式&#xff0c;可以通过它分享自己的阅读经验和心得&#xff0c;同时也可以向别人推荐好书。以下是一些关于如何制作抖音书单视频的方法…

Java当中实现分片上传

Java当中实现分片上传 文章目录 Java当中实现分片上传一&#xff1a;背景二&#xff1a;解决方案1、整体方案2、代码实例3、说明4、FileUtil中的方法 一&#xff1a;背景 Web端实现大文件上传下载的需求&#xff0c;要求将文件上传到对象存储当中&#xff0c;大文件上传有以下…

苹果手机微信记录如何备份到电脑?微信聊天记录怎么恢复?

求助&#xff01;手机上的微信聊天记录太多了&#xff0c;导致手机内存严重不足&#xff0c;但是又不舍得把聊天记录全部删除。请问有哪些快速备份微信聊天记录的方法吗&#xff1f;提前感谢大家&#xff01; 随着使用微信时间的增长&#xff0c;微信所保存的照片、视频、音频、…

Golang专题精进

Golang专题精进 Golang单元测试Golang错误处理Golang正则表达式Golang反射Golang验证码Golang日期时间处理库CarbonGolang发送邮件库emailGolang log日志Golang log日志框架logrusGolang加密和解密应用Golang访问权限控制框架casbinGolang使用swagger生成api接口文档Golang jwt…

【Day-28慢就是快】代码随想录-二叉树-完全二叉树的节点个数

给出一个完全二叉树&#xff0c;求出该树的节点个数。 —————————————————————————————————————— 1. 普通二叉树的求法 递归法与求深度类似&#xff0c;但是深度是depth,而此题是计算nodeNum。 迭代法使用层序遍历&#xff0c;记录遍历…

SAP MM学习笔记26- SAP中 振替转记(转移过账)和 在库转送(库存转储)5 - 总结

SAP 中在库移动 不仅有入库&#xff08;GR&#xff09;&#xff0c;出库&#xff08;GI&#xff09;&#xff0c;也可以是单纯内部的转记或转送。 1&#xff0c;振替转记&#xff08;转移过账&#xff09; 具体查看我之前的文章。 SAP MM学习笔记26- SAP中 振替转记&#xff…

大数据可视化大屏实战项目(2)公司季度销售额度可视化展示—HTML+CSS+JS【源码在文末】(可用于比赛项目或者作业参考中)

大数据可视化大屏实战项目&#xff08;2&#xff09;公司季度销售额度可视化展示—HTMLCSSJS【源码在文末】&#xff08;可用于比赛项目或者作业参考中&#x1f415;&#x1f415;&#x1f415;&#xff09; 一&#xff0c;项目概览 ☞☞☞☞☞☞项目演示链接&#xff1a;htt…

Kerberos基础

一. Kerberos概述 Kerberos是一种计算机网络授权协议&#xff0c;用来在非安全网络中&#xff0c;对个人通信以安全的手段进行身份认证。这个词又指麻省理工学院为这个协议开发的一套计算机软件。软件设计上采用客户端/服务器结构&#xff0c;并且能够进行相互认证&#xff0c…

软件工程学术顶会——ESEC/FSE 2022 议题(网络安全方向)清单、摘要与总结

总结 本次会议中网络安全相关议题涵盖区块链、智能合约、符号执行、浏览器API模糊测试等不同研究领域。 热门研究方向: 1. 基于深度学习的漏洞检测与修复 2. 基于AI的自动漏洞修复 3. 模糊测试与漏洞发现 冷门研究方向: 1. 多语言代码的漏洞分析 2. 代码审查中的软件安全 3. 浏…

【类和对象】③友元类

文章目录 1.初始化列表2.static静态成员3.友元 1.初始化列表 我们知道在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。虽然调用构造函数之后&#xff0c;对象中已经有了一个初始值&#xff0c;但是不能将其称为对对象中成…

长胜证券:医药逐步走出疫情扰动 潜心静气迎接曙光

8月回顾&#xff1a;2023年8月医药生物板块跌落4.76%&#xff0c;同期沪深300跌落6.21%&#xff0c;医药板块跑赢沪深300约1.45%&#xff0c;位列31个子职业第11位。本月子板块医疗服务、中药、医药商业、化学制药、医疗器械、生物制品分别跌落1.47%、3.20%、3.97%、5.18%、7.2…

关于ChatGPT:4个维度讲透 ChatGPT 技术原理,揭开 ChatGPT 神秘技术黑盒!(文末送书福利5.0)

文章目录 &#x1f4cb;前言&#x1f3af;Tansformer架构模型&#x1f3af;ChatGPT原理&#x1f3af;提示学习与大模型能力的涌现&#x1f9e9;提示学习&#x1f9e9;上下文学习&#x1f9e9;思维链 &#x1f3af;行业参考建议&#xff08;关于本书&#xff09;&#x1f9e9;拥…

Python爬取天气数据并进行分析与预测

随着全球气候的不断变化&#xff0c;对于天气数据的获取、分析和预测显得越来越重要。本文将介绍如何使用Python编写一个简单而强大的天气数据爬虫&#xff0c;并结合相关库实现对历史和当前天气数据进行分析以及未来趋势预测。 1 、数据源选择 选择可靠丰富的公开API或网站作…

QT中闹钟的设置

.h文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPushButton> //按钮 #include <QTextEdit> //文本 #include <QLabel> //标签 #include <QLineEdit> //行编辑器#include <QTimerEvent> //定时器事件类头文件 #…

串联系统与并联系统可靠性计算

串联系统 计算串联系统可靠性&#xff0c;就将所有部分的可靠性相乘即可 并联系统 计算并联系统可靠性&#xff0c;就用每个部分的不可靠性相乘&#xff0c;得到系统的不可靠性&#xff0c;再用1-不可靠性&#xff0c;得到并联系统可靠性 串&#xff0c;并联系统 上图的系统可…