AT24Cxx移植第三方库到裸机中使用

简介

MCU : STM32F103C8T6
库: HAL库裸机开发
EEPROM : AT24C02, 256Byte容量,I2C接口

电路图

AT24C02 电路图

电路图引用
在这里插入图片描述

裸机直接读写

// 写入数据到 EEPROM
HAL_StatusTypeDef EEPROM_WriteByte(uint16_t MemAddress, uint8_t Data)
{// 发送数据uint8_t dataToSend[2] = { (uint8_t)(MemAddress & 0xFF), Data };return HAL_I2C_Master_Transmit(&hi2c1, (EEPROM_I2C_ADDRESS << 1), dataToSend, 2, 100);
}// 读取数据从 EEPROM
HAL_StatusTypeDef EEPROM_ReadByte(uint16_t MemAddress, uint8_t *Data)
{// 发送存储地址uint8_t addressToSend = (uint8_t)(MemAddress & 0xFF);if (HAL_I2C_Master_Transmit(&hi2c1, (EEPROM_I2C_ADDRESS << 1), &addressToSend, 1, 100) != HAL_OK){return HAL_ERROR;}// 读取数据return HAL_I2C_Master_Receive(&hi2c1, (EEPROM_I2C_ADDRESS << 1), Data, 1, 100);
}// 调用
uint8_t dat = 100;EEPROM_WriteByte(0, dat);
HAL_Delay(10);
EEPROM_ReadByte(0&dat);

移植第三方AT24Cxx库

引用库

AT24CXX库源码
AT24CXX系列读写算法

修改库

只需要 _24cxx_dev.c 和 _24cxx_dev.h即可

  1. 将代码中的地址修改如下
    slave_addr = pdev->slave_addr | (addr>>8);
    改为
    slave_addr = pdev->slave_addr << 1;

  2. 增加写pageBuffer

/*24cxx eeprom devcie struct*/
typedef struct 
{int (*i2c_send_thend_recv)(uint8_t slave_addr, const void *send_buff, 	/* i2c bus fun */uint32_t send_size, void *recv_buff, uint32_t recv_size);int (*i2c_send_thend_send)(uint8_t slave_addr, const void *send_buff1,	/* i2c bus fun */uint32_t send_size1,const void *send_buff2, uint32_t send_size2);uint8_t	slave_addr;	/*eeprom i2c addr*///uint8_t	type;		/*eeprom type, 0:eeprom;1:fram*/_24_model_t	model;		/*eeprom model*/void(*wp)(uint8_t ctrl);		/*protect of write function*/void(*page_write_delay)(void);	/*there is a delay in continuous writin for EEPROM,FRAM not need*/uint8_t *pageBuffer;
}_24cxx_dev_t;/*extern function*/
extern void __24cxx_dev_init(_24cxx_dev_t *pdev) ;
  1. pageBuffer 初始化
void __24cxx_dev_init(_24cxx_dev_t *pdev)
{uint16_t ee_page_size = get_eeprom_pagesize(pdev->model);if (pdev->model > _24C16_E)pdev->pageBuffer = (uint8_t*)malloc(ee_page_size+2);elsepdev->pageBuffer = (uint8_t*)malloc(ee_page_size+1);
}
  1. 将写的部分合并之后发送
    写时序的问题,不合并无法正常写
/*** @brief  write one page. * @param  pdev pointer to the eeprom device struct.* @param  addr the address of write to.* @param  pbuf the data to write.* @param  size number of bytes to write..* @retval return 0 if 0k,anything else is considered an error.*/
static int16_t _24cxx_write_page(_24cxx_dev_t *pdev, uint32_t addr, uint8_t *pbuf, uint32_t size)
{
//	uint8_t	buf[2];
//	uint8_t	buf_size = 0;uint8_t slave_addr = 0;uint16_t ee_page_size = 0;int16_t	ret = 0;if (pdev == 0){return _24CXX_ERR_DEV_NONE;}ee_page_size = get_eeprom_pagesize(pdev->model);	if (((addr % ee_page_size) + size) > ee_page_size) /*the over flow of page size*/{return _24CXX_ERR_PAGE_SIZE;}if (pdev->model > _24C16_E){/*24c32-24c1024*/slave_addr = pdev->slave_addr;
//		buf[0] = (addr >>8)& 0xff;
//		buf[1] = addr & 0xff;pdev->pageBuffer[0] = (addr >>8)& 0xff;pdev->pageBuffer[1] = addr & 0xff;memcpy(&pdev->pageBuffer[2], pbuf, size);size += 2;}else{/*24c01-24c16*/slave_addr = pdev->slave_addr << 1;
//		buf[0] = addr & 0xff;pdev->pageBuffer[0] = addr & 0xff;memcpy(&pdev->pageBuffer[1], pbuf, size);size += 1;}if (pdev->wp)		/*release write protect*/{pdev->wp(0);}//	ret = pdev->i2c_send_thend_send(slave_addr, buf, buf_size, pbuf, size);ret = pdev->i2c_send_thend_send(slave_addr, pdev->pageBuffer, size, 0, 0);if (pdev->wp){pdev->wp(1);	/*write protect*/}return ret;
}
  1. 新增
.h 中新增
extern uint16_t _24cxx_pages(_24cxx_dev_t *pdev); // 设备有多少页
extern int16_t _24cxx_erase_page(_24cxx_dev_t *pdev, uint16_t pageNum, uint8_t val); // 按页擦除, val是写入值
extern int16_t _24cxx_erase(_24cxx_dev_t *pdev, uint8_t val); // 全部擦除int16_t _24cxx_erase(_24cxx_dev_t *pdev, uint8_t val)
{uint16_t pages = 0;int16_t ret = 0;if (pdev == 0){return _24CXX_ERR_DEV_NONE;}pages = _24cxx_pages(pdev);for (int i = 0; i < pages; ++i){ret = _24cxx_erase_page(pdev, i, val);if (_24CXX_OK != ret)break ;if (pdev->page_write_delay){pdev->page_write_delay();		/*eeprom need wait*/}}return ret;
}
int16_t _24cxx_erase_page(_24cxx_dev_t *pdev, uint16_t pageNum, uint8_t val)
{uint16_t pages = 0;uint16_t page_size = 0;int16_t ret = 0;uint16_t slave_addr = 0;uint32_t addr = 0;uint32_t size = 0;if (pdev == 0){return _24CXX_ERR_DEV_NONE;}pages = _24cxx_pages(pdev);page_size = get_eeprom_pagesize(pdev->model);addr = pageNum * page_size;size = page_size;if (pages <= pageNum){return _24CXX_ERR_CHIP_SIZE;}if (pdev->model > _24C16_E){/*24c32-24c1024*/slave_addr = pdev->slave_addr;size += 2;memset(pdev->pageBuffer, val, size);pdev->pageBuffer[0] = (addr >>8)& 0xff;pdev->pageBuffer[1] = addr & 0xff;}else{/*24c01-24c16*/slave_addr = pdev->slave_addr << 1;size += 1;memset(pdev->pageBuffer, val, size);pdev->pageBuffer[0] = addr & 0xff;}ret = pdev->i2c_send_thend_send(slave_addr, pdev->pageBuffer, size, 0, 0);return ret;
}
  1. 代码使用
int hw_i2c_send_then_recv(uint8_t slave_addr, const void *send_buff, uint32_t send_size, void *recv_buff, uint32_t recv_size)
{// 发送数据if (HAL_OK != HAL_I2C_Master_Transmit(&hi2c1, slave_addr, (uint8_t*)send_buff, send_size, 10)){return _24CXX_ERR_I2C_WR;	}if (HAL_OK != HAL_I2C_Master_Receive(&hi2c1, slave_addr, (uint8_t*)recv_buff, recv_size, 1000)){return _24CXX_ERR_I2C_WR;	}return _24CXX_OK;
}int hw_i2c_send_then_send(uint8_t slave_addr, const void *send_buff1, uint32_t send_size1,const void *send_buff2, uint32_t send_size2)
{if (HAL_OK != HAL_I2C_Master_Transmit(&hi2c1, slave_addr, (uint8_t*)send_buff1, send_size1, 2000)){return _24CXX_ERR_I2C_WR;	}if (0 != send_size2){if (HAL_OK != HAL_I2C_Master_Transmit(&hi2c1, slave_addr, (uint8_t*)send_buff2, send_size2, 1000)){return _24CXX_ERR_I2C_WR;	}}return _24CXX_OK;
}static void page_write_delay(void) 
{uint16_t i;i = 0xFFFF;while(i--);
}_24cxx_dev_t at24cxx_dev =
{.i2c_send_thend_recv=hw_i2c_send_then_recv,.i2c_send_thend_send=hw_i2c_send_then_send,.slave_addr=0x51,						/* eeprom address */.model=_24C02_E,					.wp=0,					/* no write protect */.page_write_delay=page_write_delay,
};uint8_t buffer[256];
uint16_t size = 0;
uint8_t readBuffer[256];
uint16_t readSize = 256;
void readWriteBufferInit()
{int writeSize = 256;for (int i = 0; i < writeSize; ++i){buffer[i] = 255-i;}size = readSize = writeSize;memset(readBuffer, 0, sizeof(readBuffer));
}/* USER CODE END 0 *//*** @brief  The application entry point.* @retval int*/
int main(void)
{/* USER CODE BEGIN 1 */static int ret = _24CXX_OK;/* 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();__24cxx_dev_init(&at24cxx_dev);/* USER CODE BEGIN 2 */readWriteBufferInit();ret = _24cxx_write(&at24cxx_dev, 0, (uint8_t*)buffer, size); if (ret != _24CXX_OK){}else{}HAL_Delay(100);ret = _24cxx_read(&at24cxx_dev, 0, (uint8_t*)readBuffer, readSize); if (ret != _24CXX_OK){}else{}
//for (int i = 0; i < size; ++i)
//{
//		ret = EEPROM_WriteByte(i, buffer[i]);
//	HAL_Delay(5);
//}
//	HAL_Delay(50);
//for (int i = 0; i < size; ++i)
//{
//		ret = EEPROM_ReadByte(i, &readBuffer[i]);
//	HAL_Delay(5);
//}/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */
}

注意

1. HAL函数

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout) 
及
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
中的Timeout需要根据你的Tick时间来设置, 系统默认是1ms, 但是你如果修改了就需要重新设置;

2. 关于读写的Timeout

  1. 按照数据手册, 写是按字节写/按页写, 所以超时时间按照页进行设置, 5+(写周期时间)~10ms;
  2. 读是可以连续读的,所以需要按照需求进行设置,如果一次性读取太多设置的Timeout少的话,导致接收超时, 会失败, 这里需要注意;

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

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

相关文章

算法刷题记录——LeetCode篇(1.3) [第21~30题](持续更新)

更新时间&#xff1a;2025-03-29 LeetCode题解专栏&#xff1a;实战算法解题 (专栏)技术博客总目录&#xff1a;计算机技术系列目录页 优先整理热门100及面试150&#xff0c;不定期持续更新&#xff0c;欢迎关注&#xff01; 21. 合并两个有序链表 将两个升序链表合并为一个…

常用数据库

模式的定义于删除 1.定义模式 CREATE SCHEMA [ <模式名> ] AUTHORIZATION < 用户名 >;要创建模式&#xff0c;调用该命令的用户必须拥有数据库管理员权限&#xff0c;或者获得了DBA授权 eg:为用户WANG定义一个模式S-C-SC CREATE SCHEMA "S-C-SC" AUT…

Processor System Reset IP 核 v5.0(vivado)

这个IP的作用&#xff0c;我的理解是&#xff0c;比普通按键复位更加高效灵活&#xff0c;可以配置多个复位输出&#xff0c;可以配置复位周期。 1、输入信号&#xff1a; 重要的信号有时钟clk信号&#xff0c;一般连接到系统时钟&#xff1b;输入复位信号&#xff0c;一般是外…

3月29日星期六今日早报简报微语报早读

3月29日星期六&#xff0c;农历三月初一&#xff0c;早报#微语早读。 1、全国公立医疗机构自3月31日起全面停止收取门诊预交金&#xff1b; 2、永辉超市“胖东来调改店”已达47家店 一线员工薪酬涨幅50%以上&#xff1b; 3、两孩家庭补10万&#xff0c;三孩家庭补20万&#…

pyinstaller 对 pyexecjs模块打包老会有终端框闪烁

解决办法&#xff1a; 修改 execjs 源代码 具体步骤 1. 在 execjs 源文件中&#xff0c;找到 _external_runtime.py 文件中的以下代码 p Popen(cmd, startupinfostartupinfo, stdinPIPE, stdoutPIPE, stderrPIPE, cwdself._cwd,universal_newlinesTrue)2. 修改为&#xff…

代码随想录day2 数组总结

1.二分查找 2.快慢 双指针 代码随想录day1-CSDN博客 3.滑动窗口 滑动窗口就是有一个起始位置&#xff0c;一个终止位置&#xff0c;通过调节起始位置和终止位置得到我们想要的结果。 外面一层for循环 用来更新终止位置 不满足条件 终止位置右移 里面一层while循环 …

MAC安装docker 后提示com.docker.vmnetd”将对您的电脑造成伤害

出现“com.docker.vmnetd”将对您的电脑造成伤害的提示&#xff0c;通常是由于文件签名问题导致 macOS 的安全系统误判 Docker 为恶意软件。以下是解决方法&#xff1a; 停止相关服务并删除文件 运行以下命令停止相关服务并删除有问题的文件 停止 Docker 服务 sudo pkill ‘…

Redis-常用命令

目录 1、Redis数据结构 2、命令简介 2.1、通用命令 DEL EXISTS EXPIRE 2.2、String命令 SET和GET MSET和MGET INCR和INCRBY和DECY SETNX SETEX 2.3、Key的层级结构 2.4、Hash命令 HSET和HGET HMSET和HMGET HGETALL HKEYS和HVALS HINCRBY HSETNX 2.5、List命…

每日一题之既约分数

题目描述 本题为填空题&#xff0c;只需要算出结果后&#xff0c;在代码中使用输出语句将所填结果输出即可。 如果一个分数的分子和分母的最大公约数是 1&#xff0c;这个分数称为既约分数。 例如 3/4,1/8,7/1​&#xff0c; 都是既约分数。 请问&#xff0c;有多少个既约分…

Java 图片压缩:高效压缩方案解析

目录 一、基于OpenCV的智能尺寸压缩(一)代码示例(二)技术亮点(三)适用场景二、WebP高效格式转换(一)代码示例(二)核心优势(三)性能对比三、基于Thumbnailator的简单压缩(一)代码示例(二)技术亮点(三)适用场景四、方案选型建议一、基于OpenCV的智能尺寸压缩 …

鸿蒙Next-集成HmRouter的路由模式

第一步&#xff1a;全局安装hmrouter依赖 ohpm install hadss/hmrouter第二步&#xff1a;修改全局的hvigor-config.json5(加入hm-router插件) hvigor/hvigor-config.json5 {"modelVersion": "5.0.1","dependencies": {"hadss/hmrouter-…

uni-app:指引蒙层

组件说明 指引蒙层组件: 通过id标签,突出对应id中的模块; 可以自定义提示词。 点击任意位置关闭蒙层 效果展示和使用示例 切换id之后的效果: 代码实现 <template><view class="guide-mask" v-if="showMask" @click="hideMask"&g…

基于Java与Go的下一代DDoS防御体系构建实战

引言:混合云时代的攻防对抗新格局 2024年某金融平台遭遇峰值2.3Tbps的IPv6混合攻击,传统WAF方案在新型AI驱动攻击面前全面失效。本文将以Java与Go为技术栈,揭示如何构建具备智能决策能力的防御系统。 一、攻击防御技术矩阵重构 1.1 混合攻击特征识别 攻击类型Java检测方案…

大数据Spark(五十五):Spark框架及特点

文章目录 Spark框架及特点 一、Spark框架介绍 二、Spark计算框架具备以下特点 Spark框架及特点 一、Spark框架介绍 Apache Spark 是一个专为大规模数据处理而设计的快速、通用的计算引擎。最初由加州大学伯克利分校的 AMP 实验室&#xff08;Algorithms, Machines, and Pe…

ubuntu 升级补丁,备份备份备份

一、常规软件包更新&#xff08;安全补丁和软件升级&#xff09; 更新软件包列表 从软件源服务器获取最新的软件包信息&#xff1a; sudo apt update升级已安装的软件包 安装所有可用的更新&#xff08;安全补丁、功能更新&#xff09;&#xff1a; sudo apt upgrade处理依赖…

CubeMx——串口与 printf 打印

CubeMx 配置 fputc 实现 /* USER CODE BEGIN 0 */ #include <stdio.h> /* USER CODE END 0 *//* USER CODE BEGIN 1 */ int fputc(int ch, FILE *f) {/* Place your implementation of fputc here *//* e.g. write a character to the USART */uint8_t send_data ch;HA…

多线程 -- Thread类

Thread 的常见构造方法 最后一个构造方法中的 ThreadGroup 线程组是 Java 中的概念&#xff0c;和系统内核中的线程组不是一个东西。我们自己创建的线程&#xff0c;默认是按照 Thread- 0 1 2 3 4...命名。但我们也可以给不同的线程&#xff0c;起不同的名字&#xff08;不同的…

Java基础关键_032_反射(二)

目 录 一、反射 Class 的 Method 1.反编译 String 类的方法签名 2.通过反射调用方法 3.反编译 String 类的构造方法签名 4.通过反射调用构造方法 二、类加载过程 1.装载&#xff08;Loading&#xff09; &#xff08;1&#xff09;说明 &#xff08;2&#xff09;双亲委…

《数据结构:单链表》

“希望就像星星&#xff0c;或许光芒微弱&#xff0c;但永不熄灭。” 博主的个人gitee&#xff1a;https://gitee.com/friend-a188881041351 一.概念与结构 链表是一种物理存储上非连续、非顺序的存储结构&#xff0c;数据元素的顺序逻辑是通过链表中的指针链接次序实现的。 单…

蓝桥杯 - 中等 - 绝美宋词

介绍 “今宵酒醒何处&#xff0c;杨柳岸晓风残月”&#xff0c;“蓦然回首&#xff0c;那人却在灯火阑珊处”&#xff0c;“试问闲愁都几许&#xff1f;一川烟草&#xff0c;满城风絮&#xff0c;梅子黄时雨” ...... 宋词可谓是古代文学桂冠上一颗璀璨的明珠&#xff0c;本题…