1. 資料位的有效性規定
I2C總線進行資料傳送時,時鐘信号為高電平期間,資料線上的資料必須保持穩定,隻有在時鐘線上的信号為低電平期間,資料線上的高電平或低電平狀态才允許變化
2. 起始和終止信号
SCL線為高電平期間,SDA線由高電平向低電平的變化表示起始信号;SCL線為高電平期間,SDA線由低電平向高電平的變化表示終止信号
起始和終止信号都是由主機發出的,在起始信号産生後,總線就處于被占用的狀态;在終止信号産生後,總線就處于空閑狀态
接收器件收到一個完整的資料位元組後,有可能需要完成一些其它工作,如處理内部中斷服務等,可能無法立刻接收下一個位元組,這時接收器件可以将SCL線拉成低電平,進而使主機處于等待狀态。直到接收器件準備好接收下一個位元組時,再釋放SCL線使之為高電平,進而使資料傳送可以繼續進行
3. 資料傳送格式
每一個位元組必須保證是8位長度。資料傳送時,先傳送最高位(MSB),每一個被傳送的位元組後面都必須跟随一位應答位(即一幀共有9位)
主機向從機發送資料:
有陰影部分表示資料由主機向從機傳送,無陰影部分則表示資料由從機向主機傳送
A表示應答, Â非表示非應答。S表示起始信号,P表示終止信号
主機在第一個位元組後,立即從從機讀資料:
改變傳送方向:
在傳送過程中,當需要改變傳送方向時,起始信号和從機位址都被重複産生一次
4. 總線的尋址
D7~D1位組成從機的位址。D0位是資料傳送方向位,為“0”時表示主機向從機寫資料,為“1”時表示主機由從機讀資料
主機發送位址時,總線上的每個從機都将這7位位址碼與自己的位址進行比較,如果相同,則認為自己正被主機尋址,根據R/T位将自己确定為發送器或接收器
一個從機的7位尋址位有4位是固定位,3位是可程式設計位,這時僅能尋址8個同樣的器件,即可以有8個同樣的器件接入到該I2C總線系統中
5. 信号模拟
起始信号:
void I2CStart(void)
{
SDA = 1;
SomeNop();
SCL = 1;
SomeNop();
SDA = 0;
SomeNop();
}
終止信号:
void I2CStop(void)
{
SDA = 0;
SomeNop();
SCL = 1;
SomeNop();
SDA = 1;
SomeNop();
}
6. 串行E2PROM
寫入過程:
讀出過程:
7. 引腳說明
A0、A1、A2均為0
是以從機位址的7位資料為:0xa0
8. 總線時序
9. 舉例
單片機小精靈:
http://download.csdn.net/download/zhangxuechao_/9894028
void delay10us(void) //誤差 0us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}
//IIC起始
void i2cStart()
{
SDA = 1;
delay10us();
SCL = 1;
delay10us();
SDA = 0;
delay10us();
SCL = 0;
delay10us();
return;
}
//IIC停止
void i2cStop()
{
SDA = 0;
delay10us();
SCL = 1;
delay10us();
SDA = 1;
delay10us();
return;
}
//IIC發送
u8 i2cSend(u8 d)
{
u8 i = 0, j = 0;
for(i = 0; i < 8; i++)
{
SDA = d >> 7;
d = d << 1;
delay10us();
SCL = 1;
delay10us();
SCL = 0;
}
SDA = 1;
delay10us();
SCL = 1;
while(SDA)
{
if(j++ > 200)
{
SCL = 0;
delay10us();
return 0;
}
}
SCL = 0;
delay10us();
return 1;
}
//IIC接收
u8 i2cRecv()
{
u8 i = 0, d = 0;
for(i = 0; i < 8; i++)
{
SCL = 1;
delay10us();
d <<= 1;
d |= SDA;
delay10us();
SCL = 0;
delay10us();
}
return d;
}
//E2PROM寫
void at24c02Write(u8 addr, u8 d)
{
i2cStart();
i2cSend(0xa0);
i2cSend(addr);
i2cSend(d);
i2cStop();
}
//E2PROM讀
u8 at24c02Read(u8 addr)
{
u8 d = 0;
i2cStart();
i2cSend(0xa0);
i2cSend(addr);
i2cStart();
i2cSend(0xa1);
d = i2cRecv();
i2cStop();
return d;
}