基于51单片机IIC通信的AT24C02学习笔记
引言
最近在学习几种串行通信协议,感觉收获很多,这篇文章是学习IIC总线协议的第一篇文章,以后还会再写一篇关于PCF8591 IIC通信的ADDA转换芯片的文章.
关于IIC总线
IIC 即Inter-Integrated Circuit(集成电路总线),这种总线类型是由飞利浦半导体公司在八十年代初设计出来的一种简单、双向、二线制、同步串行总线,主要是用来连接整体电路(ICS) ,IIC是一种多向控制总线,也就是说多个芯片可以连接到同一总线结构下,同时每个芯片都可以作为实时数据传输的控制源。主要包括启始、停止、读、写、应答信号。这种方式简化了信号传输总线接口。
IIC总线上可以挂多个器件,而每个器件都有唯一的地址,这样可以标识通信目标。数据的通信的方式采用主从方式,主机负责主动联系从机,而从机则被动回应数据。

关于AT24C02
AT24C02是一个2K位串行CMOS E2PROM, 内部含有256个8位字节,CATALYST公司的先进CMOS技术实质上减少了器件的功耗。AT24C02有一个8字节页写缓冲器。该器件通过IIC总线接口进行操作,有一个专门的写保护功能。在单片机上的应用广泛, 可以实现掉电数据不丢失功能。

IIC总线数据有效性的规定

SCL=1期间,SDA必须保持稳定,SCL=0时,SDA才允许改变。
IIC 总线的几种信号
1.起始和终止信号:

从时序图可以看出,起始信号为,SCL=1,SDA下降沿;终止信号为SCL=1,SDA为上升沿,保持的时间是有限制的:

具体的程序实现如下:
起始信号:SDA=1保持时间大于4。7us,随后SDA=0保持时间大于4us
/*SDA下降沿*/
void start()
{
SDA = 1; //顺序不能反了,先是SDA=1;
SCL = 1;
delay();
SDA = 0;
delay();
}
终止信号:SDA=0保持时间大于4us,随后SDA=1保持时间大于4。7us
/*SDA上升沿*/
void end()
{
SDA = 0; //顺序不能反了,先是SDA=0;
SCL = 1;
delay();
SDA = 1;
delay();
}
2.应答信号:

传送的每一个字节必须保证是8位长度。数据传送时,先传送最高位(MSB),每一个被传送的字节后面都必须跟随一位应答信号(即一帧共有9位)。
如:主机往总线上发送一个字节的数据后,释放总线,从机会把总线拉低(即应答信号),以表示这一字节发送成功
同理主机从总线上读取完一个字节的数据后,主机会把总线拉低,"告诉"从机这一字节的数据接收成功

程序实现
应答信号:
void ack()
{
uchar i = 0;
SCL = 1;
delay();
while(SDA == 1 && i < 250)i++;
SCL = 0; //SCL=0,SDA可以改变
delay();
}
3.AT24C02的器件地址:

根据数据手册和原理图可以看出器件地址为:0x90/0x91其中最后一位是读写方向位,若下一个字节为向总线上发送数据,则为0x90,若下一个字节是从总线上读取数据,则为0x91。
4.往总线上写一字节的数据
程序实现:先写最高位,通过左移运算符,将一字节的数据一位一位的传送到总线上,其中CY存储的是左移后的进位
void write_byte(uchar dat)
{
uchar i;
for(i = 0; i < 8; i++)
{
dat = dat << 1; //如1011 0011 左移一位为0110 0110
SCL = 0; //SDL=0,才能往SDA送数据,或从SDA读数据
delay();
SDA = CY; //上面左移后进位为1
delay();
SCL = 1;
delay();
}
SCL = 0;
// delay();
SDA = 1; //释放SDA
delay();
}
5.从总线上读取一个字节的数据
程序实现:带返回值,先读高位,然后通过移位运算符,一位一位读入
uchar read_byte()
{
uchar dat = 0, tmp, i;
SCL = 0;
delay();
for(i = 0; i < 8; i++)
{
SCL = 1; //让SDA保持稳定,准备读取
delay();
tmp = SDA; //读取此时SDA的状态
dat = dat << 1;
dat = dat | tmp;
delay();
SCL = 0; //释放SDA总线,为下一次读取做准备
delay();
}
return dat;
}
AT24C02读写操作
1.通过以上几种信号的组合,可以向AT24C02指定单元地址写一字节的数据,可以看出,读写顺序为:起始,写器件地址,应答,写单元地址,应答,写数据,应答,终止。

程序实现:此函数无返回值,有两个形参, 内存单元地址,范围0-255;要写的数据,如0xfe;
void write_AT24C02(uchar unit_addr, uchar dat)
{
start();
write_byte(AT24C02_ADDR + 0); //下一个字节为写,所以是+0
ack();
write_byte(unit_addr);
ack();
write_byte(dat);
ack();
end();
}
2.从AT24C02任意单元地址读取数据,可以看出读写顺序为:起始,写器件地址+0(下一个字节为写),应答,写单元地址,应答,起始,写器件地址+1(下一个字节为读取),读取数据,终止。

具体程序实现:此函数有返回值,一个形参;单元地址,范围:0-255;
uchar read_AT24C02(uchar unit_addr)
{
uchar dat;
/*先写数据*/
start();
write_byte(AT24C02_ADDR + 0); //下一个字节为写
ack();
write_byte(unit_addr);
ack();
start();
write_byte(AT24C02_ADDR + 1); //下一个字节为读
ack();
dat = read_byte();
end();
return dat;
}
延时函数:
void delay() //短暂5us延时
{
;;
}
IIC初始化:
void I2C_init() //初始化
{
SDA = ;
delay();
SCL = ;
delay();
}
具体应用
有了以上几个函数,我们就可以写主函数了, 功能是向内存单元211,写入数据0xae,然后在从内存单元211中读取出来,送给P1口led显示.注意:写完后要延时一会才能读取,否则不能成功读取.
void main()
{
write_AT24C02(211, 0xae);
delay_10ms(); //写完后,必须延时一定的时间才可以读取,否则不行
P1 = read_AT24C02(211);
while(1);
}
总结
通过IIC 总线通信协议的学习,可以看出,IIC总线用IO口模拟操作起来还是很简单的,使用起来还是比较方便的,而且还可以多个IIC器件挂接在一条总线上,只需要SDA和SCL两根线即可,当然也有缺点,由于是只有一根数据线,所以不能全双工传输,传输速度也有一定的限制.
我是初学者,以上内容如有错误,欢迎指正.
参考资料:
AT24C02_百度百科
iic_百度百科
欢迎大家关注我的个人博客 http://www.wangchaochao.top/
微信扫码关注我的公众号

不定期更新个人学习笔记和技术总结,欢迎大家互相学习交流!
基于51单片机IIC通信的AT24C02学习笔记的更多相关文章
- 基于51单片机IIC通信的PCF8591学习笔记
引言 PCF8591 是单电源,低功耗8 位CMOS 数据采集器件,具有4 个模拟输入.一个输出和一个串行I2C 总线接口.3 个地址引脚A0.A1 和A2 用于编程硬件地址,允许将最多8 个器件连接 ...
- 51单片机RAM 数据存储区学习笔记
转自:http://www.eepw.com.cn/article/216237_2.htm 1.RAM keil C语言编程 RAM是程序运行中存放随机变量的数据空间.在keil中编写程序,如果当前 ...
- ET 与RETI 基于51单片机中断跳出指令“RETI”浅议
最近在基于51单片机编程的过程中出现了个很奇怪的问题“程序执行中在寄存器EA=1,ET0=1,TR0=1条件下,单TF0=1时并没有执行中断”.在有过单片机中断编程经历者都知道当EA=1,ET0=1的 ...
- 基于51单片机个LCD1602的万年历程序
小白 第一次跟新博客 基于51单片机和LCD1602的万年历程序 可实现走时和调时功能 有简单的1602菜单制作 欢迎大家交流 LCD1602和51单片机的连接方法 RS = P3^5; //数据/命 ...
- 基于51单片机的CAN通讯协议C语言程序
//-----------------------函数声明,变量定义-------------------------------------------------------- #includ ...
- Flex与51单片机socket通信 策略问题
直接把<cross-domain-policy> <allow-access-from domain="*" to-ports="*"/> ...
- 基于jdk1.8的HashMap源码学习笔记
作为一种最为常用的容器,同时也是效率比较高的容器,HashMap当之无愧.所以自己这次jdk源码学习,就从HashMap开始吧,当然水平有限,有不正确的地方,欢迎指正,促进共同学习进步,就是喜欢程序员 ...
- 线程之间的通信socketpair【学习笔记】【原创】
平台信息:内核:linux3.1.0系统:android5.0平台:tiny4412 作者:庄泽彬(欢迎转载,请注明作者) 说明: 韦老师的安卓视频学习笔记 一.在一个进程中多个线程如何进行通信,主要 ...
- 基于【 MySql 】二 || mysql详细学习笔记
mysql重点学习笔记 /* Windows服务 */ -- 启动MySQL net start mysql -- 创建Windows服务 sc create mysql binPath= mysql ...
随机推荐
- 从0移植uboot (二) _uboot启动流程分析
经过了上一篇的配置,我们已经执行make就可以编译出一个uboot.bin,但这还不够,首先,此时的uboot并不符合三星芯片对bootloader的格式要求,同时,此时的uboot.bin也没有结合 ...
- MySQL优化-一 、缓存优化
body { font-family: Helvetica, arial, sans-serif; font-size: 14px; line-height: 1.6; padding-top: 10 ...
- error LNK2001: unresolved external symbol __beginthreadex
解决方法: project->settings->C++>category->code generation->Use runtime library选Debug Mul ...
- Apache Struts2存在S2-045
麻蛋的,批了老半天都找不到,还得谷歌 不扯蛋了,直接主题: Struts2 2.3.32 版本 下载地址:https://dist.apache.org/repos/dist/release/stru ...
- Digital Tutors - Introduction to Scripting Shaders in Unity 学习笔记
1. Overview 2. Understanding Shader definition:code that define what the material can do in the envi ...
- Maximum Depth of Binary Tree leetcode
Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...
- Python开发【第十八篇】Web框架之Django【基础篇】
一.简介 Python下有许多款不同的 Web 框架,Django 是重量级选手中最有代表性的一位,许多成功的网站和APP都基于 Django. Django 是一个开放源代码的Web应用框架,由 P ...
- WeMall的Android app商城中的wemall doraemon代码
WeMall-Android 包含SMSSDK/WeMall-Client/social_sdk_library_project三个项目以及Api目录下的client.php/update.xml接口 ...
- 剑指offer_(4)
重建二叉树: 题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字. 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍 ...
- 【转】nginx配置:location配置方法及实例详解
location匹配的是nginx的哪个变量? $request_uri location的匹配种类有哪些? 格式 location [ 空格 | = | ~ | ~* | !~ | !~* ] /u ...