1 I2C总线特色
I2C总线最主要的长处是其简单性和有用性。因为接口直接在组件之上,因而I2C总线占用的空间十分小,减少了电路板的空间和芯片管脚的数量,降低了互联本钱。总线的长度可高达25英尺,而且能够以10Kbps的最大传输速率支撑40个组件。I2C总线的另一个长处是,它支撑多主控(multimastering), 其间任何能够进行发送和接纳的设备都能够成为主总线。一个主控能够操控信号的传输和时钟频率。当然,在任何时刻点上只能有一个主控。
2 I2C总线作业原理
I2C总线上的数据安稳规矩,SCL为高电平时SDA上的数据保持安稳,SCL为低电平时答应SDA改动。假如SCL处于高电平时,SDA上发生下降沿,则认为是开端位,SDA上的上升沿认为是中止位。通讯速率分为惯例形式(时钟频率100kHz)和快速形式(时钟频率400kHz)。同一总线上能够衔接多个带有I2C接口的器材,每个器材都有一个仅有的地址,既能够是单接纳的器材,也能够是能够接纳发送的器材。
每次数据传输都是以一个开端位开端,而以中止位完毕。传输的字节数没有约束。最高有用位将首要被传输,接纳方收到第8位数据后会宣布应对位。数据传输一般分为两种:主设备发送从设备接纳和从设备发送主设备接纳。这两种形式都需求主机发送开端位和中止位,应对位由接纳方发生。从设备地址一般是1或2个字节,用于区别衔接在同一I2C上的不同器材。
I2C总线在传送数据进程中共有三种类型信号, 它们分别是:开端信号、完毕信号和应对信号。
开端信号:SCL为高电平时,SDA由高电平向低电平跳变,开端传送数据。
完毕信号:SCL为高电平时,SDA由低电平向高电平跳变,完毕传送数据。
应对信号:接纳数据的IC在接纳到8bit数据后,向发送数据的IC宣布特定的低电平脉冲,表明已收到数据。CPU向受控单元宣布一个信号后,等候受控单元宣布一个应对信号,CPU接纳到应对信号后,依据实际情况作出是否持续传递信号的判别。若未收到应对信号,由判别为受控单元呈现毛病。
在I2C总线中只有主发送和主接纳两种操作办法。在体系初始化时,由指令操控CPU送出相关的数据,经接口送到I2C寄存器内。经过初始化这些寄存器,能够完成I2C总线的主形式操控,以及完成I2C总线上的从设备读写。
当主设备和其间的一个从设备交流数据时,主设备首要宣布一个发动Start信号,这个信号被一切的从设备接纳。即从设备预备接纳CPU的信号,然后主设备再宣布它要通讯的从设备地址。接下来,一切的从设备将收到的这个地址和它们自己的地址进行比较。
假如收到的地址和它们自己的地址不同,则什么都不做,仅仅等候主设备宣布中止stop信号;假如收到的地址和它自己的地址相同,它就宣布一个信号给主设备,这个信号称为应对Acknowledge信号。当主设备收到应对信号后,它就开端向从设备发送数据或许从从设备接纳数据。当一切操作都进行完毕时,主设备宣布一个Stop信号,通讯完毕,开释I2C总线;然后一切的从设备都等候下一次Start信号的到来。
3 总线根本操作
I2C规程运用主/从双向通讯。器材发送数据到总线上,则界说为发送器,器材接纳数据则界说为接纳器。主器材和从器材都能够作业于接纳和发送状况。 总线有必要由主器材(一般为微操控器)操控,主器材发生串行时钟(SCL)操控总线的传输方向,并发生开端和中止条件。SDA线上的数据状况仅在SCL为低电平的期间才干改动,SCL为高电平的期间,SDA状况的改动被用来表明开端和中止条件。
3.1 操控字节
在开端条件之后,有必要是器材的操控字节,其间高四位为器材类型辨认符(不同的芯片类型有不同的界说,EEPROM一般应为1010),接着三位为片选,最终一位为读写位,当为1时为读操作,为0时为写操作。
1.写进程
(1)上电后等候一个延时(1ms)。
(2)器材寻址,给一个开端信号(SCL为高电平时SDA给一个下降沿)。发送从器材地址,高5位为10110,然后依据A1/A0(假如和器材的地址相同则那个器材会应对)进行读/写操控(O为读)。
(3)应对,器材在SCL的第9个周期时SDA给出一个低电平,作为应对信号。
(4)开端写有两种形式:字节写形式和页写形式。
·字节形式:给出A15~A8应对,给出A7~A0应对;然后给出DATA和中止信号 (SCL为高电平时,SDA给出一个上升沿),接着要等候一个擦写时刻。
·页写形式:给出地址今后接连给出64个数据。假如多于64个数据,则地址计数器主动翻转。(假如少于64昵,估量是没有问题的,可是需求试验验证。)
(5)判别擦写操作是否完毕的一个办法(应对查询),假如器材还处于擦写状况,则不会应对器材寻址;假如有应对,则阐明擦写完毕。
2.读进程
(1)上电今后等候一个延时(lms)。
(2)器材寻址。
(3)应对。
(4)开端读有三种形式:当即当时地址读、挑选/随机读、接连读。
·当即当时地址读:假如前次读/写的操作地址为N,则现在是N+1。不需求ACK,可是需求Stop信号。
·挑选/随机读:先伪写(用于给出一个地址),然后再次发动,读取数据。
·接连读:读取一个今后给一个应对,这样器材会再给出下一个地址的数据内容。
(5)开端数据传输Start后、中止数据传输Stop前,SCL高电平期间,SDA上为有用数据。
/*******************************************************************
一、程序阐明:
1, 24LC02器材地址是1010000R/W.
2, 数组写入24LC02采纳页写办法.
3, 数组code从24LC02读出时采纳自在读办法.
4, 选用4.00M晶体。
5,选用软件I2C。
二、硬件衔接:
1, SDA——->23 pin.(当然你能够恣意挑选脚位)
2, SCL——->18 Pin.(当然你能够恣意挑选脚位)
3, PORTD—–>外接8个LED,显现读出的数据,在这里,读出的刚好是一个闪烁的流水灯状况。
*******************************************************************/
#i nclude “pic.h”
#define uchar unsigned char
#define nop() asm(“nop”
#define SCL TRISC3
#define SDA TRISC4
void start_i2c();
void stop_i2c();
void send_byte(uchar c);
uchar receive_byte();
void I_send_str(uchar sla,uchar suba,uchar *s,uchar no);
void delay_250ms();
void i2c_error ();
uchar code[]={0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
uchar no,ack,c,data;
void main(void)
{
uchar i;
TRISC=0Xff; //C口设为输入 RC3为SCL线,RC4为SDA线。
PORTC=0X00;
TRISD=0X00; //D口为输出,显现IC24LC02中读出的内容
PORTD=0X00; //初始显现全亮
I_send_str(0xa0,0x00,code,9); //页写入code数组到24LC02,器材地址为0Xa0,子地址为0X00,共9个数。
delay_250ms();
///////////开端读出到D口进行显现,依据Random read时序图。
while (1)
{
for (i=0x00;i<0x09;i++)
{
start_i2c();
send_byte(0xa0); //发送器材地址,即DEVICE ADDRESS。
if (ack==0) i2c_error(); //假如24LC02无应对。则进入I2C ERROR过错指示。
send_byte(i); //发送字地址,即WORD ADDRESS。D口显现数组。
if (ack==0) i2c_error();
start_i2c(); //重新发动总线。
send_byte(0xa1); //发送读指令和器材地址DEVICE ADDRESS。
if (ack==0) i2c_error();
data=receive_byte();
stop_i2c();
PORTD=data;
delay_250ms();
}
}
}
/*******************************************************************
起动总线函数
函数原型: void start_i2c();
Function: start on the I2C bus
*******************************************************************/
void start_i2c()
{
SDA=1; //发送启始条件的数据信号
nop();
SCL=1;
nop();nop();nop();nop();nop(); //24LC02要求树立时刻大于4,7S
SDA=0; //发送开端信号
nop();nop();nop();nop();nop();
SCL=0; //钳住I2C总线,预备发送数据或接纳数据
nop();nop();
}
/*******************************************************************
中止总线函数
函数原型: void stop_i2c();
Function: stop the I2C bus
*******************************************************************/
void stop_i2c()
{
SDA=0; //发送完毕条件的数据信号
nop();
SCL=1;
nop();nop();nop();nop();nop();
SDA=1;
nop();nop();nop();nop();
}
/*=================================================================
字节数据传送函数
函数原型: void send_byte(uchar c);
Function: 将数据C发送出去,能够是地址,也能够是数据,发完后等候回应,并对此状况
位进行操作(不应对或非应对都使ack=0 ),发送数据正常,ack=1;ack=0
表明被控器无应对或损坏。
==================================================================*/
void send_byte(uchar c)
{
uchar bit_count;
for (bit_count=0;bit_count<8;bit_count++)
{
if ((c< else {SDA=0;} nop(); SCL=1; nop();nop();nop();nop();nop(); SCL=0; } nop();nop(); SDA=1; nop();nop(); SCL=1; nop();nop();nop(); if (RC4==1) ack=0; else ack=1; //用ASK=1为有应对信号 SCL=0; nop();nop(); } /*================================================================== 字节数据接纳函数 函数原型:uchar receive_byte(); FUNCTION: 用来接纳从器材传来的数据,并判别总线过错(不发应对信号), 发完后请用应对函数。 ===================================================================*/ uchar receive_byte() { uchar retc,bit_count; retc=0; SDA=1; for (bit_count=0;bit_count<8;bit_count++) { nop(); SCL=0; nop();nop();nop();nop();nop(); SCL=1; nop();nop(); retc=retc<<1; if (RC4==1) retc=retc+1; nop();nop(); } SCL=0; nop();nop(); return (retc); } /*================================================================ 向有子地址器材发送多字节数据函数 函数原型: bit I_send_str(uchar sla,uchar suba,uchar *s,uchar no); Function: 从发动总线到发送地址,数据,完毕总线的全进程,从器材地址sla。假如 回来1表明操作成功,不然操作有误。 =================================================================*/ void I_send_str(uchar sla,uchar suba,uchar *s,uchar no) { uchar i; start_i2c(); send_byte(sla); if (ack==0) i2c_error(); send_byte(suba); if (ack==0) i2c_error(); for (i=0;i { send_byte(*s); if (ack==0) i2c_error(); s++; } stop_i2c(); // return(1); } /***************************************************************** 延时函数 函数原型: void delay_250ms(); FUNCTION: 延明250ms *****************************************************************/ void delay_250ms() { unsigned int d=24999; while (–d); } /***************************************************************** 总线过错函数 函数原型: void i2c_error(); Function: 经过RD7闪烁8次表明总线操作失利一次报警。 *****************************************************************/ void i2c_error () { uchar i; for (i=0;i<8;i++) { RD7=0; delay_250ms(); RD7=1; delay_250ms(); } } /**********END**************/