基于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 ...
随机推荐
- java标签(label)求16进制字符串的整数和 把一个整数转为4个16进制字符表示
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #4f76cb } p.p2 { margin: 0.0px 0. ...
- TokuDB性能测试报告
一 .背景介绍 近年来,TokuDB作为MySQL的大数据(Big Data)存储引擎受到人们的普遍关注.其架构的核心基于一种新的叫做分形树(Fractal Trees)的索引数据结构,该结构是缓存无 ...
- Selenium 使用css selector (资源来源于网络)
Selenium - CSS Selector 昨天我练习了用CSS(即层叠样式表Cascading Stylesheet) Selector来定位(locate)页面上的元素(Elements).S ...
- 2659: [Beijing wc2012]算不出的算式
2659: [Beijing wc2012]算不出的算式 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 757 Solved: 425[Submit] ...
- Java向上转型的意义
比如我这个程序 public class Testjava{ public static void main(String args[]) { fun(new Student()); fun(new ...
- yii2 Nav::widget() 和 Menu::widget()
Nav::widget http://www.yiiframework.com/doc-2.0/yii-bootstrap-nav.html Menu::widget() http://www.yi ...
- Markdown语法讲解及MWeb使用教程
写了一个月的博客,忽然感觉Markdown编辑器比较好用,于是就下载了一个本地的Markdown编辑软件学习了一下,刚好软件里自带了一篇英文的指示文档,顺便翻译了一下,通过这个过程也大致熟悉了Mark ...
- HTML标签自定义属性
本文章转载至:http://www.cnblogs.com/luoyanli/archive/2012/10/17/2727886.html HTML标签可以自定义属性,但是我们要考虑其在IE.Fir ...
- yii2.0下拉列表的使用
第一种方法:ActiveForm 类的 dropDownList 方法(优点,默认使用yii的样式) 1.在控制器的方法里面 ,我们需要拿到数据,一定是 findAll() 或者是 all() 方法的 ...
- Dreamweaver如何开启代码错误提示,报错代码。
DW的代码错误即无效提示功能设置:在DW代码窗口左面有一列很小的功能按钮,在其中寻找"高亮显示无效代码",选中之后就可以看到无效的代码会被添加背景色,会让你容易辨识.改正后背景色会 ...