|
I2C總線包括SCL,SDA 兩根信號(hào)線,其中SCL是時(shí)鐘線,SDA是數(shù)據(jù)線。 對(duì)于I2C總線的操作,主要有以下幾個(gè)命令: 1、開始命令: I2C總線開始的操作過程是通過SCL為高的時(shí)候SDA有個(gè)下降沿的過程; 2、停止命令: I2C停止的的操作過程是通過SCL為高的時(shí)候SDA有個(gè)上升沿的過程; 3、讀寫數(shù)據(jù) I2C讀寫每一位數(shù)據(jù)都是在SCL為高的時(shí)候完成的,讀寫每一位數(shù)據(jù)的時(shí)候SCL都有一個(gè)高脈沖的過程,也就是說,在SCL為高的時(shí)候我們讀寫SDA的值,這意味著在SCL拉高之前,SDA必須為一穩(wěn)定的值,不然讀寫就不準(zhǔn)確; 4、寫完從器件之后等待從器件的應(yīng)答: 在主器件完成對(duì)從器件的寫操作時(shí)候(每次會(huì)有一個(gè)字節(jié)的數(shù)據(jù)),主器件會(huì)等待從器件發(fā)送指示信號(hào),這個(gè)指示信號(hào)是說從器件已經(jīng)接受到了主器件的數(shù)據(jù),這個(gè)回應(yīng)ACK是個(gè)低電平脈沖。并且這是由從器件的硬件來完成的,不需要主器件來軟件操作,只需要等待; 4、主器件讀完數(shù)據(jù)后向從器件發(fā)送應(yīng)答信號(hào): 這其實(shí)包括兩種情況,一種是主器件讀完后還要繼續(xù)讀就要發(fā)送一個(gè)繼續(xù)讀的信號(hào)(其實(shí)就是發(fā)送0),另一種就是不再繼續(xù)讀了,就要發(fā)送停止讀信號(hào)(其實(shí)就是發(fā)送1)。 #define uchar unsigned char #define uint unsigned int void delay() { uint i; for(i=0;i<300;i++); for(i=0;i<300;i++); } //開始 void I2C_START() { SDA = 1; SCL = 1; delay(); SDA = 0; delay(); } //停止 void I2C_STOP() { SDA = 0; SCL = 1; delay(); SDA = 1; delay(); } //寫完等待從器件應(yīng)答 bit write_ACK(void) { uchar i; SCL = 1; delay(); i = SDA; SCL = 0; delay(); if(i==1) return 0; else return 1; } //讀完發(fā)送停止讀的信號(hào) void NACK() { uchar j; SDA = 1; delay(); SCL = 1; delay(); while((SDA==0)&&(j<250)) j++; SCL = 0; delay(); } //寫字節(jié) void I2C_writebyte(uchar dat_w) { uint i; uchar tmp; tmp = dat_w; SCL = 0; delay(); for(i=0;i<8;i++) { if((tmp<<i)&0x80) SDA = 1; else SDA = 0; delay(); SCL = 1; delay(); SCL = 0; delay(); } SDA = 1; delay(); } //讀字節(jié) uchar I2C_readbyte() { uchar i; uchar dat_r,k; SCL = 0; delay(); SDA = 1; delay(); for(i=0;i<8;i++) { SCL = 0; delay(); SCL = 1; delay(); k = SDA; dat_r = (dat_r<<1)|k; SCL = 0; delay(); } return dat_r; } //寫地址及數(shù)據(jù) void I2C_write_add(uchar slave_add, uchar byte_add, uchar dat_w) { I2C_START(); I2C_writebyte(slave_add); write_ACK(); I2C_writebyte(byte_add); write_ACK(); I2C_writebyte(dat_w); write_ACK(); I2C_STOP(); } //讀地址的數(shù)據(jù) uchar I2C_read_add(uchar slave_add, uchar byte_add) { uchar dat_r; I2C_START(); I2C_writebyte(slave_add); write_ACK(); I2C_writebyte(byte_add); write_ACK(); I2C_START(); I2C_writebyte((slave_add+1)); write_ACK(); dat_r = I2C_readbyte(); NACK(); I2C_STOP(); return dat_r; } void main() { SDA = 1; SCL = 1; I2C_write_add(0xa0,0x23,0x51); P1 = I2C_read_add(0xa0,0x23); while(1); } |
|
|