ESP32 操作AT24C32或AT24C64

  • AT24C32或AT24C64两款芯片容量不一样,其他都一样。程序无法动态识别容量
  • AT24C32容量32K,地址范围0x~0x7FFF.
  • AT24C64容量64K,地址范围0x~0xFFFF

电气参数

  • 电压2.7V-5.5V

  • IIC通信

  • 有引脚控制数据保护

  • 有引脚可以配置IIC的地址。
    在这里插入图片描述

  • 每个page 32字节

  • 1百万次写入

  • 100年存放

  • 容量有两个型号AT24C32/64 提供32,768/65,536 bits ,也就是4096字节(4k字节)或8192字节(8K字节)

  • 使用16bit来确定存储的地址

  • 设备地址,如果引脚A0~A2都接地,则IIC地址为0x50.

操作步骤

写入
分为两种

  • 按字节写入
  • 按page写入,一次最多写入32字节

读取
分为3种

  • 当前地址读取
  • 随机地址读取
  • 连续读取,连续读取可以一直读

EEPROM和flash有个最大的区别:
EEPROM在写入前不需要擦除page,直接写入就行
Flash 在写入前,需要擦除,且擦除是按照page进行的。比如spi flash。

时序

写入时序
按1个字节写入时序
在这里插入图片描述按page写入时序
在这里插入图片描述在这里插入图片描述

读取时序
在当前位置读取时序
在这里插入图片描述随机读取时序
在这里插入图片描述顺序读取时序
在这里插入图片描述
在这里插入图片描述

附上完整代码

AT24CXX_driver.c

#include <stdio.h>
#include "esp_log.h"
#include "AT24CXX_driver.h"
#include "driver/i2c.h"
#include <string.h>static const char *TAG = "AT24CXX-driver";#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data  */
#define I2C_MASTER_NUM 0                        /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
#define I2C_MASTER_FREQ_HZ 100000               /*!< I2C master clock frequency */
#define I2C_MASTER_TX_BUF_DISABLE 0             /*!< I2C master doesn't need buffer */
#define I2C_MASTER_RX_BUF_DISABLE 0             /*!< I2C master doesn't need buffer */
#define I2C_MASTER_TIMEOUT_MS 1000#define AT24CXX_I2C_ADDR 0x50 /*!< Slave address of the MPU9250 sensor */esp_err_t at24cxx_init(void)
{int ret;// 初始化iicint i2c_master_port = I2C_MASTER_NUM;i2c_config_t conf = {.mode = I2C_MODE_MASTER,.sda_io_num = I2C_MASTER_SDA_IO,.scl_io_num = I2C_MASTER_SCL_IO,.sda_pullup_en = GPIO_PULLUP_ENABLE,.scl_pullup_en = GPIO_PULLUP_ENABLE,.master.clk_speed = I2C_MASTER_FREQ_HZ,};i2c_param_config(i2c_master_port, &conf);ret = i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);ESP_LOGI(TAG, "I2C initialized successfully");return ret;
}/*** 读取当前位置的数据*/
esp_err_t at24cxx_read_current(uint8_t *data, uint32_t len)
{int ret;// 开始读取数据ret = i2c_master_read_from_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);ESP_LOGI(TAG, "READ current DATA:");for (uint32_t i = 0; i < len; i++){printf("%x ", data[i]);}return ret;
}/*** 随机读取一个字节**/
esp_err_t at24cxx_random_read_byte(uint16_t address, uint8_t *data)
{int ret;uint8_t write_buf[2] = {address >> 8, address & 0xff};// 开始读取数据ret = i2c_master_write_read_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, write_buf, 2,data, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);ESP_LOGI(TAG, "at24cxx_random_read_byte:%x", *data);return ret;
}/*** 随机读取一个字节**/
esp_err_t at24cxx_random_read(uint16_t address, uint8_t *data, uint32_t len)
{int ret;if (len == 0){return 0;}// 开始读取数据at24cxx_random_read_byte(address, data);vTaskDelay(30 / portTICK_PERIOD_MS);if (len > 1){at24cxx_read_current(data + 1, len - 1);}ESP_LOGI(TAG, "random READ DATA:");for (uint32_t i = 0; i < len; i++){printf("%x ", data[i]);}return ret;
}void at24cxx_dump(void)
{uint8_t data[4096], write_buf[2] = {0, 0};// 开始读取数据i2c_master_write_read_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, write_buf, 2,data, 4096, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);ESP_LOGI(TAG, "READ DATA:");printf("   ");for (uint8_t i = 0; i < 16; i++){printf("%2x ", i);}printf("\r\n00 ");for (uint32_t i = 0; i < 4096; i++){printf("%2x ", data[i]);if (((i + 1) % 16 == 0) && (i != 0)){printf("\r\n%2lx ", i / 16);}}
}/*** @brief 按字节写入*/
esp_err_t at24cxx_write_byte(uint16_t address, uint8_t data)
{int ret = 0;uint8_t write_buf[3] = {address >> 8, address & 0xFF, data};ret = i2c_master_write_to_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, write_buf, 3, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);return ret;
}/*** @brief 按字节写入* @param page_index 第几个page*/
esp_err_t at24cxx_write_page(uint16_t page_index, at24c_page pg)
{int ret = 0;// 算出page对应的地址uint16_t address = page_index * 32;uint8_t write_buf[2 + 32] = {address >> 8, address & 0xFF};memcpy(write_buf + 2, &pg, 32);ret = i2c_master_write_to_device(I2C_MASTER_NUM, AT24CXX_I2C_ADDR, write_buf, 2 + 32, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);return ret;
}

AT24CXX_driver.h

#ifndef __DS1307_H_
#define __DS1307_H_#include "driver/i2c.h"typedef struct
{union{uint8_t value[32];uint32_t value_32[32 / 4];};
} at24c_page; // 秒esp_err_t at24cxx_init(void);
esp_err_t at24cxx_write_byte(uint16_t address, uint8_t data);
esp_err_t at24cxx_write_page(uint16_t page_index, at24c_page pg);
esp_err_t at24cxx_read_current(uint8_t *data, uint32_t len);
esp_err_t at24cxx_random_read_byte(uint16_t address, uint8_t *data);
esp_err_t at24cxx_random_read(uint16_t address, uint8_t *data, uint32_t len);
void at24cxx_dump(void);#endif

AT24CXX_main.c

#include <stdio.h>
#include "esp_log.h"
#include "AT24CXX_driver.h"static const char *TAG = "AT24CXX_main";void app_main(void)
{at24c_page pg;uint8_t eeprom_data[10], *p = (uint8_t *)&pg;ESP_ERROR_CHECK(at24cxx_init());/* Read the MPU9250 WHO_AM_I register, on power up the register should have the value 0x71 */for (uint8_t i = 0; i < 32; i++){p[i] = i;}ESP_LOGI(TAG, "test at24cxx_write_byte");at24cxx_write_byte(9,0xAA);//在下标9的地址处写入数据0xAAESP_LOGI(TAG, "test at24cxx_write_page");at24cxx_write_page(1, pg);vTaskDelay(300 / portTICK_PERIOD_MS);//这个函数可能会造成爆栈,主要是里面有个很大的数组。实际代码要优化这个位置,比如边读变输出,或使用动态内存// at24cxx_dump();ESP_LOGI(TAG, "test at24cxx_read_current");ESP_ERROR_CHECK(at24cxx_read_current(eeprom_data, 10));ESP_LOGI(TAG, "test at24cxx_random_read");ESP_ERROR_CHECK(at24cxx_random_read(1,eeprom_data,5));ESP_LOGI(TAG, "test finish");
}

i2cget -c 0x50 -r 0 -l 10

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

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

相关文章

二叉树计算 - 华为OD统一考试

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 给出一个二叉树如下图所示&#xff1a; 6 / \ 7 9 \ / -2 6 请由该二叉树生成一个新的二叉树&#xff0c;它满足其树中的每个节点将包含原始树中的左子树和右子树…

30岁以就业为目标学前端,快歇着吧;反之50岁都不晚。

Hi&#xff0c;我是贝格前端工场&#xff0c;首先声明声明我们不搞前端培训&#xff0c;有很多老铁在留言中问我关于前端学习的问题&#xff0c;最普遍的一个问题就是30岁以后学前端晚了吗&#xff1f;今天借着此篇文章回答一下。 一、30岁学前端的三种人 首先抛开年龄不说&am…

【EI会议征稿通知】第三届能源、电力与电气国际学术会议(ICEPET 2024)

第三届能源、电力与电气国际学术会议&#xff08;ICEPET 2024&#xff09; 2024 3rd International Conference on Energy, Power and Electrical Technology 第三届能源、电力与电气国际学术会议&#xff08;ICEPET 2024&#xff09;由西华大学主办&#xff0c;西华大学能源…

C语言系列-浮点数在内存中的存储

&#x1f308;个人主页: 会编程的果子君 ​&#x1f4ab;个人格言:“成为自己未来的主人~” 目录 浮点数在内存中的存储 浮点数的存储 浮点数存的过程 浮点数取的过程 题目解析 浮点数在内存中的存储 常见的浮点数&#xff1a;3.14159.1E10等&#xff0c;浮点数家族包括&…

Linux文本三剑客---grep

grep&#xff08;从文本或字符串种过滤特定内容。&#xff09; 格式&#xff1a;Usage: grep [OPTION]... PATTERNS [FILE]... 常用选项&#xff1a; -E 等价于 egrep 扩展正则 -i 忽略大小写 -w 匹配单词 -o 仅显示匹配内容 -r 递归匹配 -c 统计匹配的行数 -v 取反 -n 行号 -A…

仰暮计划|“老师说我其实很聪明,就是家里太穷了没条件,不然我现在也是……”

吴桂荣老人回忆录 在我外婆家的时候&#xff0c;我跟几位老奶奶坐在门口一起聊天&#xff0c;我询问她们是否能帮助我完成一份作业&#xff0c;她们笑着答应了&#xff0c;最后我选择了其中的一位老奶奶作为了解对象&#xff0c;她邀请我去家中交谈。通过了解&#xff0c;我得知…

HCIA学习第四天:静态路由与动态路由

静态路由&#xff1a; 选路原则&#xff1a;尽量选择路径最短的路由条目 扩展配置&#xff1a; 1、负载均衡&#xff1a;当路由器访问同一个目标且目标且目标具有多条开销相似的路径时&#xff0c;可以让设备将流量拆分后延多条路径同时进行传输&#xff0c;以达到叠加带宽的…

(七)springboot实战——springboot3集成R2DBC实现webflux响应式编程服务案例

前言 本节主要内容是关于使用新版springboot3集成响应式数据库R2DBC,完成响应式web服务案例。需要注意的是&#xff0c;此次项目使用的JDK版本是JDK17&#xff0c;springboot版本使用3.2.2版本&#xff0c;数据库使用关系型数据库mysql。WebFlux 是一个基于响应式编程模型的框…

K8s-持久化(持久卷,卷申明,StorageClass,StatefulSet持久化)

POD 卷挂载 apiVersion: v1 kind: Pod metadata:name: random-number spec:containers:- image: alpinename: alpinecommand: ["/bin/sh","-c"]args: ["shuf -i 0-100 -n 1 >> /opt/number.out;"]volumeMounts:- mountPath: /optname: da…

华为机考入门python3--(3)牛客3-明明的随机数

分类&#xff1a;集合、排序 知识点&#xff1a; 集合添加元素 set.add(element) 集合转列表 list(set) 列表排序 list.sort() 题目来自【牛客】 N int(input().strip()) nums set()for i in range(N):nums.add(int(input().strip()))# 集合转列表 nums_list l…

眼底增强型疾病感知蒸馏模型 FDDM:无需配对,fundus 指导 OCT 分类

眼底增强型疾病感知蒸馏模型 FDDM&#xff1a;fundus 指导 OCT 分类 核心思想设计思路训练和推理 效果总结子问题: 疾病特定特征的提取与蒸馏子问题: 类间关系的理解与建模 核心思想 论文&#xff1a;https://arxiv.org/pdf/2308.00291.pdf 代码&#xff1a;https://github.c…

【笔试常见编程题02】字符串中找出连续最长的数字串、数组中出现次数超过一半的数字、计算糖果、进制转换

1. 字符串中找出连续最长的数字串 读入一个字符串str&#xff0c;输出字符串str中的连续最长的数字串 输入描述 个测试输入包含1个测试用例&#xff0c;一个字符串str&#xff0c;长度不超过255。 输出描述 在一行内输出str中里连续最长的数字串。 示例 1 输入 abcd12345ed125s…

java数据结构与算法刷题-----LeetCode328. 奇偶链表

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 将链表按奇偶顺序&#xff0c;分成两个链表。最后将偶数链表放在…

计算机网络-编制与调制(基带信号 基带传输 宽度信号 宽度传输 编码 调制 )

文章目录 基带信号与宽带信号编码与调制数字数据编码为数字信号数字数据调制为模拟信号模拟数据编码为数字信号模拟数据调制为模拟信号小结 基带信号与宽带信号 信道上传输的信号除了可以分为数字信号和模拟信号&#xff0c;也可以分为基带信号和宽带信号&#xff0c;只是分类…

【每日一题】最大合金数

文章目录 Tag题目来源解题思路方法一&#xff1a;二分枚举答案 写在最后 Tag 【二分枚举答案】【数组】【2024-01-27】 题目来源 2861. 最大合金数 解题思路 方法一&#xff1a;二分枚举答案 思路 如果我们可以制造 x 块合金&#xff0c;那么一定也可以制造 x-1 块合金。于…

支持下一代网络IpV6的串口服务器,IpV6串口485接口转网口

和IPv4比较&#xff0c;IPv6有两个极具吸引力的特点&#xff1a;一个是IPv6采用的128位地址格式&#xff0c;而IPv4采用32位的地址格式&#xff0c;因此IPv6使地址空间增大了296&#xff1b;另一个是IPv6物联网数据业务具有更强的支持能力&#xff0c;成为未来物联网的重要协议…

Ps:创建基于饱和度的蒙版

能够区分图像上哪些区域的饱和度高&#xff0c;哪些区域的饱和度低&#xff0c;在调色过程中是相当有用的。 比如&#xff0c;使得饱和度高的区域更加饱和&#xff0c;可增加图像色彩反差&#xff0c;让画面更引人注目。 或者&#xff0c;使得饱和度区域趋于饱和&#xff0c;让…

技术书评和笔记【01】脑机接口-电路与系统 【2020版】

前言: 荷兰作者,Amir Zjajo博士,毕业于荷兰代尔夫特理工大学,方向 面向移动健康的低功耗混合型号电路与系统,以及,面向认知的神经形态电路。 ,脑机接口 - 电路与系统一书,系统介绍了,脑机接口电路与系统的实现技术,尤其,提到了量产和设计的问题,难能可贵,摘录如…

JVM篇----第九篇

系列文章目录 文章目录 系列文章目录前言一、分代收集算法二、新生代与复制算法三、老年代与标记复制算法前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一、分代…

MySQL-删除重复数据

在实际应用中&#xff0c;遇到一个这样的问题&#xff0c;MySQL中存储的数据为资讯类数据&#xff0c;在页面展示时会出现多个平台的新闻报导相同的内容&#xff0c;导致页面会出现重复数据。因为数据是每天定期更新&#xff0c;所以最快捷有效的方式是在更新完数据后增加一个去…