1、 C51 串串 I2C 总线共总线共 14 页页 I2C 总线是 Philips 公司最先推出的一种双向数据传输总线,其仅使用两根连线便可以实现全双工同步数据传送。在 I2C 总线中,一条为串行数据线(SDA),另一条为一条串行时钟线(SCL)。I2C 总线占用引脚少,接口协议简单。目前多数公司均推出了 I2C 总线接口的各种器件,如存储器、A/D、D/A、键盘、LCD 等,大大方便了用户的选择。本章主要介绍了 I2C 总线的工作原理、寻址方式以及数据操作,并重点介绍了数据传输协议以及相应的 C51 子函数。最后通过具体的实例,介绍如何使用在没有 I2C 总线接口的单片机上读写具有 I2C 总
2、线接口的 E2PROM 存储器。1 I2C 总线概述 I2C 总线采用两线制,由数据线 SDA和时钟线 SCL构成。I2C 总线对数据通信进行了严格的定义。1.1 I2C 总线工作原理 典型的 I2C 总线系统结构,如图所示。I2C 总线上可以挂接多个器件,其中每个器件必须都支持 I2C 总线通信协议。1.2 I2C 总线器件的寻址方式 由于所有器件都通过 SCL和 SDA连接在 I2C 总线上,因此,主器件在进行数据传输前需要通过寻址,选择需要通信的从器件。I2C 总线上所有外围器件都需要有唯一的 7位地址,由器件地址和引脚地址两部分组成。器件地址是 I2C 器件固有的地址编码,器件出厂时就
3、已经给定,不可更改。引脚地址是由 I2C 总线外围器件的地址引脚(A2,A1,A0)决定,根据其在电路中接电源正极、接地或悬空的不同,形成不同的地址代码。1.3 I2C 总线数据操作 在 I2C 总线上,数据是伴随着时钟脉冲,一位一位地传送的,数据位由低到高传送,每位数据占一个时钟脉冲。I2C 总线上的在时钟线 SCL高电平期间,数据线 SDA的状态就表示要传送的数据,高电平为数据 1,低电平为数据 0。在数据传送时,SDA上数据的改变在时钟线为低电平时完成,而 SCL为高电平时,SDA必须保持稳定,否则SDA上的变化会被当作起始或终止信号而致使数据传输停止。1写数据格式 2读数据格式 2 I
4、2C 总线接口 EEPROM 存储器 目前,市场上 I2C 总线接口器件有多种,例如 A/D转换器、D/A转换器、时钟芯片和存储器等。这里以典型的 I2C 总线接口的存储器为例进行介绍。I2C 总线接口 EEPROM 存储器是一种采用 I2C 总线接口的串行总线存储器,这类存储器具有体积小、引脚少、功耗低、工作电压范围宽等特点。目前,Atmel、MicroChip、National 等公司均提供各种型号的 I2C 总线接口的串行 EEPROM 存储器。在单片机系统中使用较多的 EEPROM存储器是 24 系列串行 EEPROM。其具有型号多、容量大、支持 I2C 总线协议、占用单片机 I/O
5、端口少,芯片扩展方便、读写简单等优点。3 C51 模拟 I2C 总线协议 在实际应用中,往往遇到所使用的单片机没有 I2C 总线接口,例如典型的 51系列单片机。为了让此类单片机用于操作 I2C 总线器件的能力,往往需要在程序模拟 I2C 总线数据传输协议。这里以典型的 51系列单片机为例,假设其外接 6MHz 的晶振,采用 P1.0 作为时钟线SCL,P1.1 作为数据线 SDA。在 C51 语言的程序中,首先需要声明 SCL和 SDA所使用的引脚。其声明如下所示:sbit SCL=P10;sbit SDA=P11;3.1 延时子函数 这里给出一个典型的延时子函数。当单片机的工作频率比较高的
6、时候,为了保证 I2C总线的传输速率满足 100kHz 或者 400kHz 的限制,可以进行适当的延时处理。用户可以根据需要使用。延时子函数的程序示例如下:void Delays(unsigned int number)/延时子程序 unsigned char temp;for(;number!=0;number-)/循环 for(temp=0;temp100;temp+)/空循环 3.2 起始信号子函数 起始信号子函数用于开始 I2C 总线通信。其中,起始信号是在时钟线 SCL为高电平期间,数据线 SDA上高电平向低电平变化的下降沿信号。起始信号出现以后,才可以进行后续的 I2C 总线寻址或
7、数据传输等。起始信号的时序,如图所示。在程序中,可以直接为 SDA和 SCL赋值来实现起始信号的时序。起始信号子函数示例如下:void StartI2C()/起始信号子程序 SDA=1;Delays(1);/延时,用于满足传输速率要求 SCL=1;Delays(1);SDA=0;Delays(1);SCL=0;Delays(1);3.3 终止信号子函数 终止信号子函数用于终止 I2C 总线通信。其中,终止信号是在时钟线 SCL为高电平期间,数据线 SDA上低电平到高电平变化的上升沿信号。终止信号一出现,所有 I2C 总线操作都结束,并释放总线控制权。终止信号的时序,如图所示。在程序中,可以直接
8、为 SDA和 SCL赋值来实现终止信号的时序。终止信号子函数示例如下:3.4 应答信号子函数 应答信号子函数用于表明 I2C 总线数据传输的结束。I2C 总线数据传送时,一个字节数据传送完毕后都必须由主器件产生应答信号。主器件在第 9 个时钟位上释放数据总线SDA,使其处于高电平状态,此时从器件输出低电平拉低数据总线 SDA为应答信号。应答信号的时序,如图所示。在程序中,可以直接为 SDA和 SCL赋值来实现应答信号的时序。应答信号子函数示例如下:void AckI2C()/发送应答位子程序 SDA=0;Delays(1);SCL=1;Delays(1);SCL=0;Delays(1);SDA
9、=1;Delays(1);3.5 非应答信号子函数 非应答信号子函数用于数据传输出现异常而无法完成时。在一个字节数据传送完毕后,在第 9个时钟位上从器件输出高电平为非应答信号。非应答信号的产生有两种情况。当从器件正在进行其他处理而无法接收总线上的数据时,从器件不产生应答,此时从器件释放总线,将数据线 SDA置为高电平。这样,主器件可产生一个停止信号来终止总线数据传输。当主器件接收来自从器件的数据时,接收到最后一个数据字节后,必须给从器件发送一个非应答信号,使从器件释放数据总线。这样,主器件才可以发送停止信号,从而终止数据传送。3.6 应答位检查子函数 应答位检查子函数用于主器件检测接收的是否为
10、正常的应答信号,以便于判断数据接收是否正常。程序中定义了 ErrorBit 作为应答检查位,用于数据线 SDA上的应答位检查结果,最后通过 return 语句返回该值。应答位检查子函数示例如下:bit TestAckI2C()/应答位检查子程序 bit ErrorBit;SDA=1;Delays(1);SCL=1;Delays(1);ErrorBit=SDA;/读入 SDA上的应答状态 Delays(1);SCL=0;Delays(1);return(ErrorBit);/返回应答状态,0为应答信号,1为非应答信号 3.7 单字节写子函数 单字节写子函数用于向从器件写入单个字节的数据。程序中,
11、可以通过 for循环语句,逐位将数据发送到 I2C 数据总线上。该函数在使用之前,必须先使用起始信号子函数启动 I2C 总线数据传输。单字节写子函数的流程图,如图 16.7所示。单字节写子函数示例如下:bit Write8BitI2C(unsigned char input)/input 为待发送的数据 unsigned char temp;for(temp=8;temp!=0;temp-)/循环移位,逐位发送数据 SDA=(bit)(input&0 x80);/取数据的最高位 Delays(1);SCL=1;Delays(1);SCL=0;Delays(1);input=input1;/左移
12、一位 return 1;3.8 单字节读子函数 单字节读子函数用于从 I2C 数据总线读入单个字节的数据。程序中,可以通过 for循环语句,逐位将数据读入。该函数在使用之前,同样需要先使用起始信号子函数启动 I2C总线数据传输。单字节读子函数的流程图,如图所示。单字节读子函数示例如下:3.9 多字节写子函数 多字节写子函数用于主器件发送多个字节的数据。首先发送起始位,接着是寻址字节,然后是数据的所要存入单元的首地址,外围器件此时产生正确的应答后,主器件便将开始多个字节的数据传输。多字节写子函数的流程图,如图所示。多字节写子函数示例如下:3.10 多字节读子函数 多字节读子函数用于主器件从 SD
13、A线上读取多个字节的数据。在读多个字节的操作中,除了发送寻址字节外,还要发送器件的子地址。因此,在读多个字节操作前,要进行一个字节的写操作,然后重新开始读操作,将从器件内的字节数据读出。多字节写读函数的流程图,如图 16.10所示。多字节写读函数示例如下:4 C51 读写 EEPROM实例 I2C 总线接口器件以体积小,占用引脚少,接口简单,读写操作方便等优点而得到广泛的应用。目前 Philips、Atmel、Maxim 以及其他集成电路制造商推出了很多基于 I2C 总线的单片机和外围器件,如 24系列 E2PROM、串行实时时钟芯片 DS1302、USB2.0芯片 CY7C68013A等。这
14、里以普通的 51系列单片机为例,通过实例介绍如何使用 C51 模拟 I2C 总线接口来读写 I2C 总线的 EEPROM 存储器。4.1 电路设计 这里给出单片机 AT89S51 读写 I2C 总线接口的 AT24C08 存储器的电路原理图图,该电路图中所使用的元器件的参数及数量,如表所示。4.2 程序设计 这里采用 C51 语言在 Keil Vison3 集成开发环境中编写程序。本程序的功能是利用单片机的 P1.0、P1.1 作为 I2C 串行总线的 SCL、SDA接口,向AT24C08 写入 10 个字节的数据,然后再将写入的数据读出,并比较读写的数据是否完全一致。如果数据的读写一致,则点
15、亮 LED,表示写入正确;否则熄灭 LED报警。4.3 仿真分析 为了加深对 I2C 串行总线协议的理解,可以在 Keil Vison3 集成开发环境中对整个程序进行仿真。通过信号仿真,可以查看 I2C 总线中起始信号、终止信号以及数据读写的时序。具体操作步骤如下:5 小结 本章首先介绍了 I2C 串行总线的工作原理、寻址方式以及总线数据的读写操作等,并对常用的 I2C 串行总线接口的 EEPROM存储器进行了介绍。接着,本章详细介绍了I2C 串行总线的协议,以及采用 C51 语言模拟读写 I2C 串行总线的子函数。最后通过一个具体的实例,讲解了 51系列单片机读写 I2C 总线外围器件的电路
16、设计以及程序设计。I2C 串行总线具有接口简单、引脚少、体积小等优点,在实际电路设计中经常使用。阅读(1554)|评论(1)|转发(0)|0 上一篇:编译内核(Compile the Kernel)下一篇:_IO,_IOR,_IOW 和_IORW 的含义 相关热门文章 内存模拟块设备中 mount/dev/r.刀具发展快,对【金刚石刀具磨.传感器模拟考试答案 合理使用 U盘的 6 大妙方.CATTI考试笔译综合能力模拟试.linux 常见服务端口 【ROOTFS 搭建】busybox 的 httpd.xmanager 2.0 for linux 配置 什么是 shell linux socket 的 bug?curl:(56)Recv failure:Con.CACTI 不能安装 WINE,怎么办?.kernel 报错 l701.exel16922:.C 语言 如何在一个整型左边补 0.python 无法爬取阿里巴巴的数据.给主人留下些什么吧!gongxijie2014-01-16 11:46:51 你这个没写完啊,模拟之后和一般硬件实现的 I2C 性能对比如何呢,一般都会有性能的降低
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1