前言
I2CBUS(Inter Integrated Circuit BUS内部集成电路总线)是由Philips公司推出的二线制串行扩展总线。I2C总线是具备总线仲裁和高低速设备同步等功能的高性能多主机总线。由于其组成系统结构简单,无需专门的母板和插座,直接用导线连接设备,通信时无需片选信号,且具有这种总线的器件的价格比较便宜,故当今已有广泛的应用前景。但目前应用很广的MCS51系列、68HC05系列、AT89系列的单片机都不具有这种总线的接口,很大程度上限制了它们的应用范围。本文介绍了这种总线的通信标准,并给出了在8031上利用P1口实现I2C总线的方法,及其软件模拟程序。
I2C总线
I2C总线概述
I2C总线使用两根信号线来进行数据传输,一根是串行数据线(SDA),另一根是串行时钟线(SCL)。它允许若干兼容器件(如存储器、A/D和D/A转换器,以及LED、LCD驱动器等)共享总线。I2C总线上理论上可以允许的最大设备数,是以总线上所有器件的电容总和不超过400pF为限(其中包括连线本身的电容和与它连接端的引出电容),总线上所有器件要依靠SDA发送的地址信号寻址,不需要片选线。任何时刻总线只能由一个主器件控制,各从器件在总线空闲时启动数据传送,由I2C总线仲裁来决定哪个主器件控制总线。
I2C总线数据传输的最高速率为400Kbps,标准速率为100Kbps。SDA与SCL为双向I/O线,都是开漏极端(输出1时,为高阻抗状态)。因此I2C总线上的所有设备的SDA、SCL引脚都要外接上拉电阻。
I2C总线的协议如下:
总线空闲:SCL和SDA都保持高电平。
开始信号:SCL保持高电平的状态下,SDA出现下降沿。出现开始信号以后,总线被认为"忙"。
停止信号:SCL保持高电平的状态下,SDA出现上升沿。停止信号过后,总线被认为"空闲"。
总线忙: 在数据传送开始以后,SCL为高电平的时候,SDA的数据必须保持稳定,只有当SCL为低电平的时候才允许SDA上的数据改变。(如图一)
I2C总线的传送格式为主从式,对系统中的某一器件来说有四种可能的工作方式:主发送方式,从发送方式,主接收方式,从接收方式。
⑴主发送从接收
主器件产生开始信号以后,发送的第一个字节为控制字节。前七位为从器件的地址片选信号。最低位为数据传送方向位(高电平表示读从器件,低电平代表写从器件),然后发送一个选择从器件片内地址的字节,来决定开始读写数据的起始地址。接着再发送数据字节,可以是单字节数据,也可以是一组数据,由主器件来决定。从器件每接收到一个字节以后,都要返回一个应答信号(ASK=0)。主器件在应答时钟周期高电平期间释放SDA线,转由从器件控制,从器件在这个时钟周期的高电平期间必须拉低SDA线,并使之为稳定的低电平,作为有效的应答信号。(如图2)
⑵从接收主发送
在开始信号以后,主器件向从器件发送控制字节。如果从器件接收到主器件发送来的控制字节中的从地址片选信号与该器件相对应,并且方向位为高电平(R/W=1),就表示从器件将要发送数据。从器件先发送一个应答信号(ASK=0)回应主器件,接着由从器件发送数据到主器件。如果,在这个过程之前,主器件发给从器件一个片内地址选择信号,那么从器件发送的数据就从该地址开始发送;如果在从器件接收到请求发送的控制信号以前,没有收到这个地址选择信号,从器件就从最后一次发送数据的地址开始发送数据。发送数据过程中,主器件每接收到一个字节都要返回一个应答信号ACK。若ACK=0(有效应答信号),那么从器件继续发送;若ACK=1(停止应答信号),停止发送。主器件可以控制从器件从什么地址开始发送,发送多少字节。
AT24C02与8031的接口及软件模拟
AT24CXX系列芯片是采用了I2C总线标准的常用的串行EEPROM存储芯片。我们以AT24C02为例来介绍。AT24C02具有256 8(2K)Bit的存储容量,每个字节可重复擦/写100万次,数据保存期大于100年。AT24C02工作于从器件方式,页写的时候最多可以写入8字节(当开始写入的从器件片内地址为页首地址时)。也就是说,AT24C02每页有8字节的容量,每次写入数据是从主器件发送来的片内选择地址开始写入,如果写到页末尾,主器件还在继续发送的话,不会自动转到下一页,而是从该页的头地址开始继续写入,覆盖该页的原有数据,而造成数据丢失。
8031与AT24C02的接口电路原理图如图3
其中P1.0用作SDA线,P1.1用作SCL线。A0-A2为从器件地址选择线,总线上共可接8片AT24C02,故一条I2C总线上共可以接16Kbit容量的这种型号的存储器。每一片的有效地址引脚A2A1A0要按照000~111的顺序与Vcc或Vss相连。WP为写保护引脚,由于AT24C02不具有写保护功能,所以该引脚接地。本设计为了方便,只采用一片AT24C02,将A0-A2接地。
软件模拟I2C总线
SCL EQU P1.1;
SDA EQU P1.0;
开始信号: 停止信号:
START:CLR SCL;STOP:CLR SCL;
SETB SDA;CLR SDA;
ACALL DELAY;ACALL DELAY;
SETB SCL;SETB SCL;
ACALL DELAY;ACALL DELAY;
CLR SDA;SETB SDA;
ACALL DELAY;ACALL DELAY;
CLR SCL;RET;
RET;
发送一个字节: 接收一个字节:
SEND:MOV R0,#08H;REV:MOV R0,#08H;
SEND0:RLC A;REV0:SETB SCL;
MOV SDA,C;MOV C,SDA;
SETB SCL;RLC A;
ACALL DEALY;CLR SCL;
CLR SCL;DJNZ R7,REV0;
DJNZ R0,SEND0;RET;
SETB SDA;
RET;
接收一个应答位: 发送一个应答位:
ACKI:SETB SCL;ACKO:SETB SCL;
ACALL DELAY;ACALL DELAY;
MOV C,SDA;MOV SDA,C;
CLR SCL;CLR SCL;
RET;RET;
循环子程序:
DELAY:NOP;
NOP;
NOP;
RET;
对于AT24C系列芯片来说,其控制字节的格式为:1010A2A1A0。前四位是固定的,为1010。A2A1A0这三位是用来选择对应的从器件,本例中从器件的这三根引脚都接地,选择信号应该为000。是控制数据传送的方向的,1为读从器件,0为写从器件。
主发送从接收程序
这时的控制字应该为:10100000(0A0H)。要写入的从器件的地址为ADDR,写入的数据的字节数为NUM,数据放在以DATA地址开始的主器件存储单元中。
程序如下:
OUT:ACALL START;开始信号
MOV A,#0A0H;定控制字,准备发送
ACALL SEND;发送控制字
ACALL ACKI;接收应答
JC END;从器件不响应,转结束
MOV A,ADDR;设置从器件片内地址
ACALL SEND;发送片内地址
ACALL ACKI;
JC END;
MOV R2,#NUM;设置发送字节数
MOV R1,#DATA;主器件中要发送数据的头地址
MOV A,@R1;
OUT1:ACALL SEND;发送数据
ACALL ACKI;
JC END;
INC R1;
DJNZ R2,OUT1;发送未结束,继续发送
END:ACALLL STOP;停止信号
RET;结束程序
从发送主接收程序
此时的控制字为10100001H,在从器件的地址ADDR处开始读出数据,读数据的字节数为NUM,数据放在以DATA地址开始的主器件存储单元中。用位单元10H来存放应答位。程序如下:
INOUT:ACALL START;开始信号
MOV A,#0A0H;定控制字,准备发送
ACALL SEND;发送控制字
ACALL ACKI;接收应答
JC END;不响应,转结束
MOV A,ADDR;设置要读取从器件的片内地址
ACALL SEND;
ACALL ACKI;
JC END;
ACALL STOP;停止信号
ACALL DELAY;延时
IN:ACALL START;开始信号
MOV A,#0A1H;设置控制字,准备接收
ACALL SEND;发送控制字
ACALL ACKI;
JC END;
MOV R2,#NUM;准备接收数据的字节数
MOV R1,#DATA;接收字节存放在主器件中的地址
IN0:ACALL REV;接收一个字节
MOV @R1,A;把接收到数据存放到存储单元中
CJNZ R2,#01,IN2;判断是否为最后一个接收字节
IN1:SETB 10H;置位发送应答标识位,准备发停 止应答
SJMP IN3;
IN2:CLR 10H;清除发送应答位标识位,准备发 有效应答
IN3:MOV C,10H;应答标识位,赋给进位位
ACALL ACKO;发送应答信号
CLR SCL;拉低时钟线
DJNZ R2,IN0;发送未结束,继续转上
END:ACALL STOP;停止信号
RET;结束程序
结束语
随着单片机的推广与普及,I2C总线已经广泛应用于测量、控制等领域。本文以子程序模块的方式给出了I2C总线在8031上的实现方法,对于其他的单片机如68HC05系列,可以在此基础上,根据总线的时序,改动相应指令,即可实现所要求的功能要求。对于其他基于I2C总线的芯片也同样可行。本文具有一定可移植性和通用性。