I2C總線規(guī)范與I2C器件C51讀寫程序(一)
1、I2C總線簡介:
I2C 總線是一雙線串行總線,它提供一小型網(wǎng)絡(luò)系統(tǒng),為總線上的電路共享公共的總線??偩€上的器件有單片機、LCD 驅(qū)動器以及上E2PROM 器等等。自從菲利普公司提出I2C總線規(guī)范以來,I2C器件得到了廣泛的應(yīng)用。I2C器件的應(yīng)用大大減少了電路間連線,減小了電路板尺寸,降低了硬件成本,并提高了系統(tǒng)可靠性。
2、I2C規(guī)范:
I2C總線規(guī)范可以參考有關(guān)資料,本文僅給出有關(guān)硬件操作的基本概念。
2.1、I2C 總線名詞解釋:
發(fā)送器:發(fā)送數(shù)據(jù)到總線上的器件
接收器:從總線上接收數(shù)據(jù)的器件
主器件:啟動數(shù)據(jù)傳送并產(chǎn)生時鐘信號的器件
從器件:被主器件尋址的器件
2.2、I2C總線時序定義:
起始位:SCL=1時,在SDA上有下降延
停止位:SCL=1時,在SDA上有上升延
*主器件發(fā)停止信號給從器件,作用在于使從器件處為準(zhǔn)備狀態(tài)(或是已知的狀態(tài))
從應(yīng)答:SDA=0
*寫數(shù)據(jù)時,應(yīng)答的器件在第九個時鐘周期將SDA線拉低,表示已收到一個8位數(shù)據(jù),并表示可繼續(xù)接收。主機在向從機寫一字節(jié)后接收從應(yīng)答,再進行后續(xù)操作(一般不考慮從應(yīng)答位的具體值,僅在應(yīng)答檢測時用于判斷從器件是否完成其內(nèi)部寫周期)
主應(yīng)答:SDA=0(用)
*讀數(shù)據(jù)時,主機每接收從機一個字節(jié)數(shù)據(jù)(不是最后一個),返回主應(yīng)答ACK(SDA=0)
是最后一個字節(jié)時返回?zé)o需應(yīng)答NO_ACK(SDA=1)
當(dāng)從機工作于讀模式時,在向主機發(fā)送一個8位數(shù)據(jù)后釋放SDA線并監(jiān)視一個應(yīng)答信號,一旦接收到主機的應(yīng)答信號,從機繼續(xù)發(fā)送數(shù)據(jù);如主器件沒有發(fā)送應(yīng)答信號,從機停止傳送數(shù)據(jù)并等待一個停止信號,主器件必須發(fā)一個停止信號給從機使其進入備用電源模式并使器件處于已知的狀態(tài)
應(yīng)答檢測:采用應(yīng)答檢測讀命令測試從機是否<頁寫>結(jié)束(通過從應(yīng)答來識別)
*當(dāng)從器件完成內(nèi)部寫周期后將發(fā)送一個應(yīng)答信號(從應(yīng)答)給主器件,以便可以繼續(xù)進行下一次讀操作
3、I2C器件C51讀寫程序
3.1、數(shù)據(jù)定義說明:
sbit sda=P0^0; //I2C器件SDA數(shù)據(jù)線
sbit scl=P0^1; //I2C器件SCL時鐘線
#define nops() {_nop_();_nop_();_nop_();_nop_();_nop_();} //nop指令個數(shù)定義
uchar i2c_ad_main; //器件從地址
uchar i2c_ad_sub; //器件子地址
uchar *i2c_buf; //發(fā)送/接收數(shù)據(jù)緩沖區(qū)
uchar i2c_num; //發(fā)送/接收數(shù)據(jù)個數(shù)
說明:可以在你的應(yīng)用程序中修改上述值,使其適應(yīng)你的demo設(shè)計
3.2、子函數(shù)說明:(私有函數(shù),不能調(diào)用)
void i2c_start(void) //送起始位
void i2c_stop(void) //送停止位
void i2c_ack_main(bit ack_main) //主應(yīng)答
說明:ack_main=1:ack主應(yīng)答;ack_main=0:no_ack無需應(yīng)答
void send_byte(uchar c) //發(fā)送單個字節(jié)
uchar read_byte(void) //接收單個字節(jié)
說明:此函數(shù)需要配合主應(yīng)答來用
3.3、模塊函數(shù)說明:(I2C外部接口函數(shù),可被應(yīng)用程序調(diào)用)
void send_to_byte(uchar ad_main,uchar c) //向無子地址器件發(fā)送單字節(jié)數(shù)據(jù)
void send_to_nbyte(uchar ad_main,uchar ad_sub,uchar *buf,uchar num)
//向有子地址器件發(fā)送多字節(jié)數(shù)據(jù)
void read_from_byte(uchar ad_main,uchar *buf) //從無子地址器件讀單字節(jié)數(shù)據(jù)
void read_from_nbyte(uchar ad_main,uchar ad_sub,uchar *buf,uchar num)
//從有子地址器件讀多個字節(jié)數(shù)據(jù)