I2C總線進(jìn)行數(shù)據(jù)傳送時,時鐘信號為高電平期間,數(shù)據(jù)線上的數(shù)據(jù)必須保持穩(wěn)定,只有在時鐘線上的信號為低電平期間,數(shù)據(jù)線上的高電平或低電平狀態(tài)才允許變化。
起始和終止信號 :SCL線為高電平期間,SDA線由高電平向低電平的變化表示起始信號;SCL線為高電平期間,SDA線由低電平向高電平的變化表示終止信號。
數(shù)據(jù)傳送格式(1)字節(jié)傳送與應(yīng)答
每一個字節(jié)必須保證是8位長度。數(shù)據(jù)傳送時,先傳送最高位(MSB),每一個被傳送的字節(jié)后面都必須跟隨一位應(yīng)答位(即一幀共有9位)。如果一段時間內(nèi)沒有收到從機的應(yīng)答信號,則自動認(rèn)為從機已正確接收到數(shù)據(jù)。
3引角對應(yīng),為當(dāng)前電路中的地址選擇線,三根線可選擇8個芯片同時連接在電路中,當(dāng)要與哪個芯片通信時傳送相應(yīng)的地址即可與該芯片建立連接,TX-1B實驗板上三根地址線都為0。最后一位R/W為告訴從機下一字節(jié)數(shù)據(jù)是要讀還是寫,0為寫入,1為讀出。
AT24C02的芯片地址如下圖,1010為固定,A0,A1,A2正好與芯片的1,2,
code:
/*
通訊中 SDA 口通訊雙方都可為輸出,如果一方輸出低,
另一方則如果輸出高也不能使SDA為高,相當(dāng)于,輸出低的一方占住了SDA口。
兩個口,一個出高一個出低,則線上電平是低的。
這是由于,出高的驅(qū)動能力不及出低拉電流的能力。
所以SDA=1為釋放數(shù)據(jù)線
*/
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit sda=P2^0;
sbit scl=P2^1;
void delay()//執(zhí)行空語句,微秒級延時函數(shù)
{;;}
void delay1ms(uint z)//延時1ms
{
uint x,y;
for(x=z;x>0;x--)
{
for(y=0;y<=110;y++)
{
}
}
}
void init()//初始化狀態(tài)下SCL和SDA都為高電平
{
scl=1;
delay();
sda=1;
delay();
}
void start()//在SCL為高電平時SDA由高電平到低電平
{
sda=1;
delay();
scl=1;
delay();
sda=0;
}
void respons()
/*
應(yīng)答信號,SCL在高電平期間,SDA被從設(shè)備拉為低電平表示應(yīng)答。
(sda==1)和i<255相與,表示若在一段時間內(nèi)沒有從器件的應(yīng)答則主器件
默認(rèn)從器件已經(jīng)收到數(shù)據(jù)而不再等待應(yīng)答信號
*/
{
uchar i;
scl=1;
delay();
while((sda==1)&&(i<250))
{
i++;
}
scl=0;
delay();
}
void stop()//SCL在高電平期間,SDA一個上升沿停止信號
{
sda=0;
delay();
scl=1;
delay();
sda=1;
}
void write_byte(uchar date)//寫一個字節(jié)
{
uchar i,temp;
temp=date;
for(i=0;i<8;i++)
{
temp=temp<<1;
scl=0;//只有在SCL為0期間才允許SDA數(shù)據(jù)線上的狀態(tài)才允許變化
delay();
sda=CY;//PSW的寄存器的CY進(jìn)位標(biāo)志位
delay();
scl=1; //SCL時鐘信號為高電平期間數(shù)據(jù)線上的數(shù)據(jù)必須保持穩(wěn)定
delay();
}
scl=0;
delay();
sda=1;//釋放總線
delay();
}
uchar read_byte()
{
uchar i,k;
scl=0;
delay();
sda=1;//釋放總線
delay();
for(i=0;i<8;i++)
{
scl=1;
delay();
k=(k<<1)|sda;
scl=0;
delay();
}
//delay();here is a bug
return k;
}
void write_address(uchar address,uchar date)
{
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
write_byte(date);
respons();
stop();
}
uchar read_address(uchar address)
{
uchar date;
start();
write_byte(0xa0);
respons();
write_byte(address);
respons();
start();
write_byte(0xa1);
respons();
date=read_byte();
stop();
return date;
}
void main()
{
init();
write_address(1,0xfe);
delay1ms(100);
P2=read_address(1);
while(1);
}
I2C總線介紹:
I2C總線(Inter IC Bus)由飛利浦公司推出,是近年來微電子控制領(lǐng)域廣泛采用的一宗新型總線標(biāo)準(zhǔn),它使同步通信的一種特殊形式,具有接口少、控制簡單、器件封裝形體小、通信速率較高等優(yōu)點(可達(dá)400Kbps)。在主從通信中,可以有多個I2C總線器件同時接到I2C總線上,所有與I2C總線兼容的器件都具有標(biāo)準(zhǔn)的接口,通過地址來識別通信對象,是她可以經(jīng)由I2C總線相互直接通信。
I2C總線由數(shù)據(jù)線和時鐘線SDA和SCL兩條線構(gòu)成,可發(fā)送數(shù)據(jù)可接收數(shù)據(jù)。于CPU及被控IC間、IC與IC間均可雙向傳送,各器件均并于總線上,各自有唯一地址。信息傳輸中,I2C總線上的各器件既是被控又是控制器件,既是發(fā)送器又是接收器。CPU發(fā)出的控制信號分為地址碼和數(shù)據(jù)嗎兩部分;地址碼選址;數(shù)據(jù)嗎送數(shù)。故而各IC雖同并于總線上但卻各自獨立。
I2C總線硬件結(jié)構(gòu)圖
圖中:ACL時鐘,SDA數(shù)據(jù) 接上拉電阻,故總線空閑是高電平,任一器件變低均將拉低電平故曰:各器件的時鐘線及數(shù)據(jù)線乃“與”關(guān)系。
通信格式為 時鐘高時下跳開始尋地址 發(fā)送一字節(jié) 8位中低位為數(shù)據(jù)方向 0為我黨要向下面發(fā)指令 形象的為“O”,俗稱為蛋,如川蛋:“川O001”,陜蛋:“陜O001”都是當(dāng)官的向下發(fā)指令,發(fā)飆的,當(dāng)然,單片機哎平方C系統(tǒng)呢有點民主成分,從機可以向主機傳信息,既發(fā)1,形象的成為“1”:咦 你們小麻蝦 小老百信還要上方發(fā)信息呀???。?事實上是的 0為下蛋-----下傳數(shù)據(jù);1為上訪-----上傳數(shù)據(jù)。記住了吧!
時鐘為高SCL=1時 數(shù)據(jù)那得穩(wěn)定 俗稱維穩(wěn)期間當(dāng)然 時鐘撤了 SCL=0時 隨便你蝦子變化數(shù)據(jù)。
發(fā)送啟動信號 那得我們主機發(fā)了 黨外人士沒這個權(quán)利 在時鐘為高 警察在的時 本地圖片,請重新上傳候 主機發(fā)一個下跳沿信號 表示開會了 開始了既:SCL=1時 SDA 你們老百姓就等著查戶口吧!
當(dāng)官的在警察在時下跳了 于是衙門發(fā)令查戶口 高七位為你我家庭住址,最低一位為數(shù)據(jù)方向 上面已表在此老子不說了。
各民眾,自己根據(jù)收到的地址碼對號入座,發(fā)現(xiàn)是自己 那就準(zhǔn)備收吧---數(shù)據(jù)。
而且在收數(shù)據(jù)時 每次收到了 都得回答“諾”.若是犯人那得點頭說“政府好”,當(dāng)然主機可以不回答 主機不回答視為停止傳數(shù)據(jù)的命令 注意了 每次回答都必須是時鐘為高時拉數(shù)據(jù)線為低哦!不得有誤。
主機若在時鐘為高時上跳---警察在的時候領(lǐng)導(dǎo)跳上臺那是表示結(jié)束了gameover了 數(shù)據(jù)傳送動作停止了。
2,單片機模擬I2C總線通信
目前很多單片機都有硬硬的I2C總線通信控制單元,工作時無需我們介入自動工作,但可憐的51單片機沒有 這個接口我們不得不通過軟件模擬I2C總線的工作時序,在要用時。調(diào)用這些子函數(shù)即可。
有仨方式:一,主機向從機發(fā)數(shù)據(jù),數(shù)據(jù)傳送方向在整個過程中不變。
二,主機在第一個字節(jié)后,立即從從機讀數(shù)。
三,在傳送過程中,當(dāng)需要改變傳送方向時,需將起始信號和從機地址重復(fù)發(fā)放一次,而兩次讀寫方向的那個位剛好相反。