前端一般模仿什么网站,自适应网站好建们,怎样用网站模板做网站,织梦网站模板源码下载学习使用的开发板#xff1a;STC89C52RC/LE52RC 编程软件#xff1a;Keil5 烧录软件#xff1a;stc-isp
开发板实图#xff1a; 文章目录 AT24C02介绍存储器 I2C总线介绍I2C时序结构数据帧AT24C02数据帧 编程实例 —— 按键控制数据大小存储器写入读出 AT24C02介绍 …学习使用的开发板STC89C52RC/LE52RC 编程软件Keil5 烧录软件stc-isp
开发板实图 文章目录 AT24C02介绍存储器 I2C总线介绍I2C时序结构数据帧AT24C02数据帧 编程实例 —— 按键控制数据大小存储器写入读出 AT24C02介绍
AT24C02 是一种可以实现掉电不丢失的存储器可用于保存单片机运行时想永久保存的数据信息存储介质E2PROM通讯接口I2C总线容量256字节 引脚及应用电路如下 详细结合I2C通信协议讲解
存储器
存储器大致分为两类 RAM(Random Access Memory随机存取存储器)掉电丢失 ROM(Read Only Memory只读存储器)掉电不丢失 RAM
SRAM静态随机存储器访问时间短速度快用于CPU高速缓存(Cache)。DRAM动态随机存储器访问时间长速度较慢用于主存也就是运行内存。
ROM
Mask ROM在制作过程写入写入后不可更改类似磁带只用于读取PROM可改写一次的只读存储器。PROM在出厂时存储的内容全为1用户可以根据需要将其中的某些单元写入数据0(部分的PROM相反出场全为0) 以实现对其“编程”的目的EPROM(可擦除可编程ROM)具有可擦除功能擦除后即可进行再编程但是缺点是擦除需要使用紫外线照射一定的时间且时间较长E2PROM/E2PROM/EEPROM(电可擦除)可直接用电信号擦除也可用电信号写入写入时间为ms级别Flash(闪存)属于E2PROM的改进产品。最大特点是必须按块(Block)擦除(每个区块的大小不定不同厂家的产品有不同的规格) 而EEPROM则可以一次只擦除一个字节(Byte)。硬盘、软盘、光盘相应控制器 Flash闪存芯片
I2C总线介绍
单片机常用的通信方式有UART(串口)、SPI、I2C、DS232
UART常用于两个单片机进行通信详情参看【51单片机】串口通信 UART有三个缺陷不能远距离传输、传输速度慢、不能一对多通信。针对这三个缺陷衍生出了其他的通信方式
远距离传输RS232/RS485
传输速度SPI(加了个clock线提供时钟信号)常用于SD卡屏幕这类对通信速度要求高的外设
一对多通信I2C —— 常用于开发板中单片机与其他外设进行通信 I2C总线(Inter IC BUS) 是由 Philips 公司开发的一种通用数据总线同步、半双工、带数据应答有两根通信线SCLSerial Clock、SDASerial Data
所有I2C设备的 SCL 连接在一起SDA 连在一起 设备的 SCL 和 SDA 均要配置成开漏输出模式 开漏输出可参看B站up主工科男孙老师的《推挽 开漏 高阻 这都是谁想出来的词》 开漏输出可用于适配不同电压的芯片在总线通信时避免不同设备输出高低电平导致设备烧毁。通过搭配外接上拉电阻输出高低电平 当 SCLKN1OUT 关闭SCLKIN 为高电平当 SCLK1OUT 打开SCLKIN 为低电平 SCL 和 SDA 各添加一个上拉电阻阻止一般为4.7KΩ左右 上拉电阻可参看B站up主工科男孙老师的《单片机的上拉电阻 到底在拉什么》 上拉电阻阻值过小会漏电阻值过大驱动能力(将低电平拉高的速度)下降。
当总线挂载设备增多时可适当降低上拉电阻阻值 开漏输出 和 上拉电阻 的共同作用实现了“线与”的功能解决多机通信互相干扰的问题 当总线设备较多且通信速度要求高可以适当降低上拉电阻的阻值
详情参看B站up主工科男孙老师的《单片机I2C通信入门(上)硬件部分有哪些注意点?》
I2C时序结构
因为总线上挂载多个设备需要约定通信协议才能让通信正确无误畅通无阻 例如一次读数据通信需要知道什么时候发起向谁读数据对方是否存在读数据停止读数据。 I2C通信协议将上述操作都抽象成了一个个时序最终拼接成数据帧
总共有六个时序结构如下
起始条件 —— 数据帧的起始表示开始通信
SCL 高电平期间SDA 从高电平切换到低电平
终止条件 —— 数据帧的结尾表示通信结束
SCL 高电平期间SDA 从低电平切换到高电平
发送一个字节 —— 可发送数据I2C地址字地址…
SCL 低电平期间主机将数据位依次放到SDA线上(高位在前)然后拉高 SCL从机(对方设备)将在 SCL 高电平期间读取数据位。SCL 高电平期间 SDA 不允许有数据变化依次循环上述过程8次即可发送一个字节数据
注意先拉低 SCL再将数据放到 SDA然后拉高 SCL此时从机会读取 SDA 数据
接收一个字节 —— 主机(MCU) 接收从机数据
SCL 低电平期间从机将数据依次放到 SDA 线上(高位在前)然后拉高 SCL主机将在 SCL 高电平期间读取数据位所以SCL高电平期间SDA不允许有数据变化依次循环上述过程8次即可接收一个字节主机在接收之前需要释放SDA
注意先拉高 SDA释放总线给从机。从机在 SCL 低电平时将数据放到 SDA 主机拉高 SCL 读取数据再拉低 SCL 让从机放数据
发送应答 —— 接收从机数据后告诉从机无误或有误
在接收完一个字节之后主机在下一个时钟发送一位数据、数据0表示应答数据1表示非应答。发送流程同发送一位数据
接收应答 —— 主机发送一字节数据后接收从机的接收应答
在主机发送完一个字节之后主机在下一个时钟接收一位数据判断从机是否应答数据0 表示应答数据1 表示非应答(主机在接收之前需要释放SDA) 数据帧
I2C数据帧描述具体的一次通信由上述时序结构拼接而成。
发送一帧数据 —— 向谁发什么 协议格式中第一个字节(为slave address)由7位地址和一位R/W读写位组成的这字节是个器件地址。
I2C 挂载多个设备通过从机地址(slave address)标识对哪个设备进行读/写操作
常用I2C接口通用器件的器件地址是由种类型号及寻址码组成的共7位。 如格式如下 器件类型A6 - A3 共4位决定的。这是由半导公司生产时就已固定此类型的了也就是说这4位已是固定的。本开发板为 1010 用户自定义地址码A2 - A0 共3位。这是由用户自己设置的通常的作法如EEPROM这些器件是由外部IC的3个引脚所组合电平决定的用常用的名字如A0,A1,A2。这也就是寻址码。AT24C02 的寻址码为 000 最低一位就是R/W位“0”表示写“1”表示读通常读写信号中写上面有一横线表示低电平。所以I2C设备通常有两个地址即读地址和写地址
综上AT24C02 的写地址为0xA0读地址为0xA1 回到数据帧发送一帧数据流程如下
S(起始位) - 发送从机地址 W - 从机返回接收应答 - 发送一字节数据 - 从机返回接收应答 … - P(终止位) 接收一帧数据 S(起始位) - 发送从机地址 W - 从机返回接收应答 - 接收一字节数据 - 主机发送应答 - … - P(终止位) 复合格式 —— 先发送再接收 AT24C02数据帧
AT24C02是一个存储器本质就是写入数据和读取数据其数据帧分为字节写 和 随机读
字节写 存储器内部还有字地址需要指明将数据写到存储器的哪个位置 —— word address
随机读 需要先告诉 AT24C02 要读哪个地址的数据再进行读字节数据帧
编程实例 —— 按键控制数据大小存储器写入读出
按键和数码管部分参看【51单片机】独立按键 和 【51单片机】数码管
首先对I2C的时序结构进行封装读者可以对照上述时序图代码如下
#include REGX52.h
#include Delay.hsbit I2C_SDA P2^0;//数据线
sbit I2C_SCL P2^1;//Clock线/*** brief I2C开始标志* parm 无* retval 无*/
void I2C_Start()
{//起始条件SCL高电平期间SDA从高电平切换到低电平//先置SDA 1确保从高电平切到低电平I2C_SDA 1;//SCL置高电平I2C_SCL 1;//SDA由高电平切换为低电平I2C_SDA 0;//SCL恢复低电平I2C_SCL 0;
}
/*** brief I2C停止标志* parm 无* retval 无*/
void I2C_Stop()
{//终止条件SCL高电平期间SDA从低电平切换到高电平//先置SDA 0确保从低电平切到高电平I2C_SDA 0;//SCL置高电平I2C_SCL 1;//SDA由低电平切换为高电平I2C_SDA 1;
}
/*** brief I2C发送字节数据* parm Byte要发送的数据范围: 0 ~ 255* retval 无*/
void I2C_SendByte(unsigned char Byte)
{//发送数据从高位开始//SCL低电平期间SDA写数据SCL拉高后从机读取数据unsigned char i 0;for(i 0; i 8; i){I2C_SDA Byte (0x80 i);I2C_SCL 1;//此处要注意若机器频率过快可能导致从机还没读到数据SCL就被拉低了I2C_SCL 0;//需要查看手册。}
}
/*** brief I2C读取一字节数据* parm 无* retval 读取到的数据*/
unsigned char I2C_ReceiveByte()
{//接收数据从高位开始//SCL高电平时从SDA读数据unsigned char Byte 0, i;//将SDA置高电平释放SDA给从机I2C_SDA 1;for(i 0; i 8; i){I2C_SCL 1;if(I2C_SDA) Byte | (0x80 i);I2C_SCL 0;}return Byte;
}
/*** brief 发送应答* parm AckBit为0表示应答为1表示非应答* retval 无*/
void I2C_SendAck(unsigned char AckBit)
{//在读完一个字节后主机在下一个时钟发送一位数据//数据0表示应答数据1表示非应答I2C_SDA AckBit;I2C_SCL 1;I2C_SCL 0;
}
/*** brief 接收应答* parm 无* retval Ack为0表示应答为1表示非应答*/
unsigned char I2C_ReceiveAck()
{//在发完一个字节后主机在下一个时钟接收一位数据判断从机是否应答//数据0表示应答数据1表示非应答主机在接收之前需要释放SDAunsigned char Ack;//释放SDAI2C_SDA 1;//SCL置高电平I2C_SCL 1;//读响应Ack I2C_SDA;//SCL置低电平I2C_SCL 0;return Ack;
}然后封装 AT24C02 的两个数据帧对 I2C 的时序结构进行拼接
#include REGX52.h
#include I2C.h
//AT24C02的从机地址写从机地址读需 | 0x01
#define AT24C02_ADDRESS 0xA0/*** brief 向AT24C02暂存器写入数据* parm WordAddress:写到暂存器的什么地址* parm Data:要写入的数据 * retval 无*/
void AT24C02_WriteByte(unsigned char WordAddress, unsigned char Data)
{I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_SendByte(Data);I2C_ReceiveAck();I2C_Stop();
}
/*** brief 从AT24C02读取数据* parm WordAddress:读什么地址的数据* retval 读出的数据*/
unsigned char AT24C02_ReadByte(unsigned char WordAddress)
{unsigned char Data;I2C_Start();I2C_SendByte(AT24C02_ADDRESS);I2C_ReceiveAck();I2C_SendByte(WordAddress);I2C_ReceiveAck();I2C_Start();I2C_SendByte(AT24C02_ADDRESS | 0x01);//此处是读I2C_ReceiveAck();Data I2C_ReceiveByte();I2C_SendAck(1);I2C_Stop();return Data;
}主程序 —— 监控按键按下并执行相应操作
按键一变量按键二变量–按键三将变量写入 AT24C02按键四将数据读出 At24C02
#include REGX52.h
#include AT24C02.h
#include SoleKey.h
#include LCD1602.h
#include Delay.hvoid main()
{unsigned char Key 0;unsigned int Count 0;LCD_Init();//LCD1602初始化LCD_ShowNum(1, 1, Count, 5);while(1){Key SoleKey();//获取哪个按键按下if(Key){if(Key 1)//1按键按下Count{Count;LCD_ShowNum(1, 1, Count, 5);}else if(Key 2)//2按键按下Count--{Count--;LCD_ShowNum(1, 1, Count, 5);}else if(Key 3)//3按键按下存储数据{AT24C02_WriteByte(0x00, Count / 256);Delayms(5);//因为写速度较慢不能连续写会导致数据错误AT24C02_WriteByte(0x01, Count % 256);LCD_ShowNum(1, 1, Count, 5); //显示写入成功LCD_ShowString(2, 1, Write OK!);Delayms(1000);LCD_ShowString(2, 1, );}else if(Key 4)//4按键按下读出数据{Count AT24C02_ReadByte(0x00) * 256 AT24C02_ReadByte(0x01);LCD_ShowNum(1, 1, Count, 5);//显示读出成功LCD_ShowString(2, 1, Read OK! );Delayms(1000);LCD_ShowString(2, 1, );}}}
}效果如下 【51单片机AT24C02 I2C通信】 完整项目链接
AT24C02 存储数据 I2C通信 以上就是本篇博客的所有内容感谢你的阅读 如果觉得本篇文章对你有所帮助的话不妨点个赞支持一下博主拜托啦这对我真的很重要。