AT24C02学习笔记

看手册:

AT24Cxx xx代表能写入xxK bit=(xx K)/8 byte   

内部写周期很关键,代表每一次页写或字节写结束后时间要大于5ms(延时5ms确保完成写周期),否则时序会出错。

页写:型不同号每一页可能写入不同大小的字节数

AT24C02:         一页8字节,地址第一页可写地址0x00~0x07

AT24C04/08/16: 一页16字节,地址第一页可写地址0x00~0x0f

AT24C32/64:      一页32字节,地址第一页可写地址0x00~0x1f

基本的读写操作(字节读写,页写,随机读,序列读)芯片内部会自动递增地址,无需在代码里操作地址

芯片引脚

器件地址(7位):

AT24C02: 前四位固定1010,后3位根据芯片引脚接高低电平决定

AT24C04: 前四位固定1010,A2、A1位根据芯片引脚接高低电平决定,后一位必须接地。

AT24C08: 前四位固定1010,A2位根据芯片引脚接高低电平决定,后两位必须接地。

AT24C16: 前四位固定1010,后3位必须接地。

读写位:读1  、写0

AT24Cxx系列优点就是低功耗

基本读写操作

字节写:

I2C时序通信:发出起始条件->发送8位地址(器件地址7位+读写位0)->主机接收应答(从机发送应答)->发送字地址(芯片内部)->主机接收应答(从机发送应答)->发送8位数据->主机接收应答(从机发送应答)->发出停止条件->等待5ms(延时5ms)保证完成写周期;

页写:

I2C时序通信:发出起始条件->发送8位地址(器件地址7位+读写位0)->主机接收应答(从机发送应答)->发送字地址(芯片内部)->主机接收应答(从机发送应答)->发送8位数据->主机接收应答(从机发送应答)->…………(最多发送8个数据否则会覆盖先前写入的数据(字节))->发出停止条件->等待5ms(延时5ms)保证完成写周期;

内部写周期机制:发送写命令->……->发送停止信号,启动写周期->可以通过发送I2起始信号->(1)(发送一个字节->读取EEPROM应答判断芯片是否应答0 )->不是就重复操作(1)->是,就进行下一个操作

随机读一个数据:

发出起始条件->发送8位地址(器件地址7位+读写位0)->主机接收应答(从机发送应答)->发送字地址(芯片内部)->主机接收应答(从机发送应答)->发出起始条件->发送8位地址(器件地址7位+读写位1)->主机接收应答(从机发送应答)->可用指针来操作(存储)读取8位数据->主机发送不应答->发送停止信号

顺序读(连续读数据):

发出起始条件->发送8位地址(器件地址7位+读写位0)->主机接收应答(从机发送应答)->发送字地址(芯片内部)->主机接收应答(从机发送应答)->发出起始条件->发送8位地址(器件地址7位+读写位1)->主机接收应答(从机发送应答)->可用指针来操作(存储)读取8位数据->主机发送应答->……(直到主机不想接受了)->主机发送不应答->发送停止信号

原理图

AT24C02实现连续页写思路:

用一个变量来判断当前地址还可写入多少个字节,判断是否要跨页写,判断为需要跨页,先写完本页,再通过地址偏移(+前一页还可写入的字节数)得到下一页的地址,在进行一页写操作,如果写完一页,还没停止还要写,再通过地址偏移(+一页可写的字节数)得到下一页的地址,再进行重复操作。

总代码

AT24C02.c

#include "AT24C02.h"                  // Device header
#include "Delay.h"//AT24C02模块地址0x01010111 0x57  0x10101111 AF AE
//AT24C02最多读写50个字节  0x31
#define AT24C02_ADDRESS (0xA0)void AT24C02_W_SCL(uint8_t x)
{GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction) x);Delay_us(10); 
}void AT24C02_W_SDA(uint8_t x)
{GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction) x);Delay_us(10); 
}uint8_t AT24C02_R_SDA(void)
{uint8_t BitVal;BitVal = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);Delay_us(10);return BitVal;    
}void AT24C02_Init(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//开启GPIOB的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);					//将PB10和PB11引脚初始化为开漏输出/*设置默认电平*/GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);			//设置PB10和PB11引脚初始化后默认为高电平(释放总线状态)
}void AT24C02_Start(void)
{ AT24C02_W_SDA(1) ;AT24C02_W_SCL(1) ;AT24C02_W_SDA(0) ;AT24C02_W_SCL(0) ;
}void AT24C02_Stop(void)
{AT24C02_W_SDA(0) ;AT24C02_W_SCL(1) ;AT24C02_W_SDA(1) ;
}void AT24C02_SendByte(uint8_t Byte)
{uint8_t i;for( i=0;i<8;i++){   AT24C02_W_SDA(Byte &(0x80 >> i));//从最高位一位一位移出AT24C02_W_SCL(1);AT24C02_W_SCL(0);//用完拉低时钟线,防止时序出差}}uint8_t AT24C02_RecviceByte(void)
{   uint8_t i;uint8_t Byte = 0x00; AT24C02_W_SDA(1);//主机放开对数据线的控制for(i=0;i<8;i++){AT24C02_W_SCL(1);//时钟线高电平期间读取时钟线if(AT24C02_R_SDA()==1)   {Byte |= (0x80>>i);} AT24C02_W_SCL(0);}return Byte;
}void AT24C02_SendAck(uint8_t x)
{//AT24C02_W_SCL(0);AT24C02_W_SDA(x);AT24C02_W_SCL(1);AT24C02_W_SCL(0);//用完拉低时钟线,防止时序出差
}uint8_t AT24C02_RecviceAck(void)
{uint8_t Ack=0;AT24C02_W_SDA(1);//主机放开对数据线的控制AT24C02_W_SCL(1);//时钟线高电平期间读取时钟线Ack = AT24C02_R_SDA();AT24C02_W_SCL(0);//用完拉低时钟线,防止时序出差return Ack; 
}uint8_t AT24C02_WriteByte(uint8_t address,uint8_t data)
{AT24C02_Start();AT24C02_SendByte(AT24C02_ADDRESS);if(AT24C02_RecviceAck()) return 1;AT24C02_SendByte(address);if(AT24C02_RecviceAck()) return 2;AT24C02_SendByte(data);if(AT24C02_RecviceAck()) return 3;AT24C02_Stop();Delay_ms(5);//重点,最少要满足AT24C02的写循环的最小周期return 0;
}uint8_t AT24C02_ReadByte(uint8_t address,uint8_t *data )
{AT24C02_Start();AT24C02_SendByte(AT24C02_ADDRESS);if(AT24C02_RecviceAck()) return 1;AT24C02_SendByte(address);if(AT24C02_RecviceAck()) return 2; AT24C02_Start();   AT24C02_SendByte(AT24C02_ADDRESS+1);if(AT24C02_RecviceAck()) return 3;*data = AT24C02_RecviceByte();AT24C02_SendAck(1);AT24C02_Stop();Delay_ms(5);//重点,最少要满足AT24C02的写循环的最小周期return 0;
}uint8_t AT24C02_PageWrite(uint8_t address,uint8_t *str,uint8_t count)
{AT24C02_Start();AT24C02_SendByte(AT24C02_ADDRESS);if(AT24C02_RecviceAck()) return 1;AT24C02_SendByte(address);if(AT24C02_RecviceAck()) return 2; for (uint8_t i = 0; i < count; i++){AT24C02_SendByte(*str++);if (AT24C02_RecviceAck()) return 3;}//    AT24C02_SendAck(1);  //无需应答AT24C02_Stop();Delay_ms(5);return 0;
}   uint8_t AT24C02_NPageWrite(uint8_t address,uint8_t *str,uint8_t count)
{uint8_t num =  address%8 +count  ; //判读是否跨页if(num>8){while(count){uint8_t temp =  8 - address%8  ;if(count>=temp){AT24C02_PageWrite(address,str,temp);  address +=temp;str += temp;count -= temp;               }else{AT24C02_PageWrite(address,str,count);address +=count;str += count;count -= count;                             }}}        else{AT24C02_PageWrite(address,str,count);}return 0;
}   u8 AT24C02_NReadData(uint8_t address,uint8_t *str,uint8_t count)
{AT24C02_Start();AT24C02_SendByte(AT24C02_ADDRESS);if(AT24C02_RecviceAck()) return 1;AT24C02_SendByte(address);if(AT24C02_RecviceAck()) return 2; AT24C02_Start(); AT24C02_SendByte(AT24C02_ADDRESS+1);if(AT24C02_RecviceAck()) return 3;for(uint8_t i = 0;i<count-1;i++){   *str = AT24C02_RecviceByte();AT24C02_SendAck(0);str++;count--;} *str = AT24C02_RecviceByte();AT24C02_SendAck(1);AT24C02_Stop();// Delay_ms(5);//重点,最少要满足AT24C02的写循环的最小周期return 0;
}    

AT24C02.h

#ifndef     _AT24C02_H_
#define     _AT24C02_H_#include "stm32f10x.h"                  // Device header//void AT24C02_WriteByte(uint8_t WordAddress,uint8_t data);
//uint8_t AT24C02_ReadByte(uint8_t WordAddress);
uint8_t AT24C02_WriteByte(uint8_t address,uint8_t data);
uint8_t AT24C02_ReadByte(uint8_t address,uint8_t *data );
uint8_t AT24C02_PageWrite(uint8_t address,uint8_t *str,uint8_t count);
uint8_t AT24C02_NPageWrite(uint8_t address,uint8_t *str,uint8_t count);void AT24C02_Init(void);u8 AT24C02_NReadData(u8 page_Address,u8 *buf,u8 Datalen);#endif

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

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

相关文章

蓝牙BLE开发——解决iOS设备获取MAC方式

解决iOS设备获取MAC方式 uniapp 解决 iOS 获取 MAC地址&#xff0c;在Android、iOS不同端中互通&#xff0c;根据MAC 地址处理相关的业务场景&#xff1b; 文章目录 解决iOS设备获取MAC方式监听寻找到新设备的事件BLE工具效果图APP监听设备返回数据解决方式ArrayBuffer转16进制…

01 Oracle 基本操作

Oracle 基本操作 初使用步骤 1.创建表空间 2.创建用户、设置密码、指定表空间 3.给用户授权 4.切换用户登录 5.创建表 注意点&#xff1a;oracle中管理表的基本单位是用户 文章目录 了解Oracle体系结构 1.创建表空间**2.删除表空间**3.创建用户4.给用户授权5.切换用户登录6.表操…

独一无二,万字详谈——Linux之文件管理

Linux文件部分的学习&#xff0c;有这一篇的博客足矣! 目录 一、文件的命名规则 1、可以使用哪些字符&#xff1f; 2、文件名的长度 3、Linux文件名的大小写 4、Linux文件扩展名 二、文件管理命令 1、目录的创建/删除 &#xff08;1&#xff09;、目录的创建 ① mkdir…

rust windwos 两个edit框

use winapi::shared::minwindef::LOWORD; use windows::{core::*,Win32::{Foundation::*,Graphics::Gdi::{BeginPaint, EndPaint, PAINTSTRUCT},System::LibraryLoader::GetModuleHandleA,UI::WindowsAndMessaging::*,}, };// 两个全局静态变量&#xff0c;用于保存 Edit 控件的…

解锁成长密码:探寻刻意练习之道

刻意练习&#xff0c;真有那么神&#xff1f; 在生活中&#xff0c;你是否有过这样的困惑&#xff1a;每天苦练英语口语&#xff0c;可一到交流时还是支支吾吾&#xff1b;埋头苦学吉他&#xff0c;却总是卡在几个和弦转换上&#xff1b;工作多年&#xff0c;业务能力却似乎陷入…

WPS中如何为指定区域的表格添加行或者列,同时不影响其它表格?

大家好&#xff0c;我是小鱼。 日常工作中会遇到这种情况&#xff1a;在一个Excel工作表中有多个表格&#xff0c;因为后期数据量增加就需要为指定区域的表格添加行或者列&#xff0c;但是不能影响其它表格。这种情况下我们应该怎么操作呢&#xff1f; 为指定区域的表格添加行…

Gitlab17.7+Jenkins2.4.91实现Fastapi项目持续发布版本详细操作(亲测可用)

一、gitlab设置&#xff1a; 1、进入gitlab选择主页在左侧菜单的下面点击管理员按钮。 2、选择左侧菜单的设置&#xff0c;选择网络&#xff0c;在右侧选择出站请求后选择允许来自webhooks和集成对本地网络的请求 3、webhook设置 进入你自己的项目选择左侧菜单的设置&#xff…

模型工作流:自动化的模型内部三角面剔除

1. 关于自动减面 1.1 自动减面的重要性及现状 三维模型是游戏、三维家居设计、数字孪生、VR/AR等几乎所有三维软件的核心资产&#xff0c;模型的质量和性能从根本上决定了三维软件的画面效果和渲染性能。其中&#xff0c;模型减面工作是同时关乎质量和性能这两个要素的重要工…

Unity微信小游戏接入开放数据域

demo地址&#xff1a;https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/tree/main/Demo/Ranking 官方说明&#xff1a; https://github.com/wechat-miniprogram/minigame-unity-webgl-transform/blob/main/Design/OpenData.md 准备一个Canvas&#xff0c…

如何实现 MySQL 的读写分离?

面试题 你们有没有做 MySQL 读写分离&#xff1f;如何实现 MySQL 的读写分离&#xff1f;MySQL 主从复制原理的是啥&#xff1f;如何解决 MySQL 主从同步的延时问题&#xff1f; 面试官心理分析 高并发这个阶段&#xff0c;肯定是需要做读写分离的&#xff0c;啥意思&#x…

go window安装protoc protoc生成protobuf文件

1. 下载&#xff1a; Releases protocolbuffers/protobuf GitHub 2. 解压缩&#xff1a; 3. 配置环境变量&#xff1a; 选择系统变量->Path -> 新增 解压缩后的bin路径 4. 打印版本&#xff1a; protoc --version 5. 安装protoc-gen-go cmd 下输入安装命令&#xff0…

学习C++:标识符命名规则

标识符命名规则&#xff1a; 作用&#xff1a;C规定给标识符&#xff08;变量、常量&#xff09;命名时&#xff0c;有一套自己的规则 标识符不能是关键字 标识符只能由字母、数字、下划线组成 第一个字符必须为字母或下划线 标识符中字母区分大小写 &#xff08;给标识符命…

Linux系统程序设计--6.线程

线程基本概念 刚创建的进程默认有一个线程&#xff0c;成为主控线程(主线程) Linux线程实现 线程标识 Linux线程的创建和终止 pthread_create 龟兔赛跑案例 #include<stdio.h> #include<stdlib.h> #include<pthread.h> #include<math.h>void * th_fn…

5G学习笔记之Non-Public Network

目录 0. NPN系列 1. 概述 2. SNPN 2.1 SNPN概述 2.2 SNPN架构 2.3 SNPN部署 2.3.1 完全独立 2.3.2 共享PLMN基站 2.3.3 共享PLMN基站和PLMN频谱 3. PNI-NPN 3.1 PNI-NPN概述 3.2 PNI-NPN部署 3.2.1 UPF独立 3.2.2 完全共享 0. NPN系列 1. NPN概述 2. NPN R18 3. 【SNPN系列】S…

DevOps实战:用Kubernetes和Argo打造自动化CI/CD流程(1)

DevOps实战&#xff1a;用Kubernetes和Argo打造自动化CI/CD流程&#xff08;1&#xff09; 架构 架构图 本设计方案的目标是在一台阿里云ECS服务器上搭建一个轻量级的Kubernetes服务k3s节点&#xff0c;并基于Argo搭建一套完整的DevOps CI/CD服务平台&#xff0c;包括Argo CD…

清空DNS 缓存

如果遇到修改了host文件&#xff0c;但是IP和域名的映射有问题的情况&#xff0c;可以尝试刷新DNS缓存。 ipconfig/flushdns win建加R建&#xff0c;然后输入cmd&#xff0c;然后回车 然后回车&#xff0c;或者点击确定按钮。 出现如下所示标识清空DNS 缓存成功。

计算机伦理与职业规范1:计算的社会背景

1 第一个阶段&#xff1a;为战争而发展的计算机器 1.1 问题描述 面对全球冲突&#xff0c;一帮数学家开始致力于尽可能快地解决复杂数学问题。冲突双方都会通过无线电发送命令和战略信息&#xff0c;而这些信号也可能被敌方截获。为了防止信息泄露&#xff0c;军方会对信号进…

笔记本通过HDMI转VGA线连接戴尔显示器,wifi不可用或网速变慢

早上开开心心的来使用我的分屏显示器&#xff0c;结果winP开拓展&#xff0c;我的wifi就断掉了&#xff0c;琢磨了好一阵我以为是wifi的问题&#xff0c;发现不进行拓展&#xff0c;网络又好了&#xff0c;一上午就研究这个了&#xff0c;说是hdmi信号干扰了wifi信号啥的额&…

48页PPT|2024智慧仓储解决方案解读

本文概述了智慧物流仓储建设方案的行业洞察、业务蓝图及建设方案。首先&#xff0c;从政策层面分析了2012年至2020年间国家发布的促进仓储业、物流业转型升级的政策&#xff0c;这些政策强调了自动化、标准化、信息化水平的提升&#xff0c;以及智能化立体仓库的建设&#xff0…

计算机网络:应用层 —— 网络应用模式

文章目录 客户—服务器方式和对等方式客户/服务器方式 (C/S方式)工作流程特点 对等方式 (P2P方式)工作流程P2P 应用特点 客户—服务器方式和对等方式 网络应用程序运行在处于网络边缘的不同的端系统上&#xff0c;通过彼此间的通信来共同完成某项任务。 开发一种新的网络应用…