51單片機I2C總線驅(qū)動程序
I2C總線只有兩根雙向信號線。一根是數(shù)據(jù)線SDA,另一根是時鐘線SCL。
本文引用地址:http://www.butianyuan.cn/article/201611/315583.htm一.I2C系統(tǒng)結構
每個接到I2C總線上的器件都有唯一的地址。主機與其它器件間的數(shù)據(jù)傳送可以是由主機發(fā)送數(shù)據(jù)到其它器件,這時主機即為發(fā)送器。由總線上接收數(shù)據(jù)的器件則為接收器。
二.數(shù)據(jù)位的有效性規(guī)定
I2C總線進行數(shù)據(jù)傳送時,時鐘信號為高電平期間,數(shù)據(jù)線上的數(shù)據(jù)必須保持穩(wěn)定,只有在時鐘線上的信號為低電平期間,數(shù)據(jù)線上的高電平或低電平狀態(tài)才允許變化。
三.字節(jié)傳送與應答
每一個字節(jié)必須保證是8位長度。數(shù)據(jù)傳送時,先傳送最高位(MSB),每一個被傳送的字節(jié)后面都必須跟隨一位應答位(即一幀共有9位)。
四.驅(qū)動程序
#define uchar unsigned char#define uint unsigned int#define somenop() _nop_(),_nop_(),_nop_(),_nop_(),_nop_(),_nop_()sbit SCL=P2^1;sbit SDA=P2^0;
- 1
- 2
- 3
- 4
- 5
1.起始信號和終止信號
SCL線為高電平期間,SDA線由高電平向低電平的變化表示起始信號;
SCL線為高電平期間,SDA線由低電平向高電平的變化表示終止信號。
起始和終止信號都是由主機發(fā)出的,在起始信號產(chǎn)生后,總線就處于被占用的狀態(tài);在終止信號產(chǎn)生后,總線就處于空閑狀態(tài)
void I2C_Start() //起始{SCL=1;somenop();SDA=1;somenop();SDA=0;somenop();SCL=0;somenop();}void I2C_Stop() //終止{ SDA=0;somenop();SCL=1;somenop();SDA=1;somenop();}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
2.發(fā)送數(shù)據(jù)
void I2C_SendByte(uchar dat, uchar ack) //發(fā)送一個字節(jié){uchar i,j,b=0;for(i=0;i<8;i++){ SCL=0; somenop(); SDA=(bit)(dat&0x80); //每次取最高位進行發(fā)送dat<<=1; //從最高位開始發(fā)送,左移使每一位逐漸成為最高位SCL=1; //上升沿時發(fā)送數(shù)據(jù)somenop(); }SCL=0;somenop(); SDA=1; somenop();SCL=1;_nop_();while((SDA==1)&&(j<250)) j++; //等待應答,也就是等待從設備把SDA拉低SCL=0;_nop_(); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
3.讀取數(shù)據(jù)
uchar I2C_ReadByte() //讀一個字節(jié){uchar i,dat=0;SCL=0; //此處也可以不置低,因為起始和發(fā)送一個字節(jié)之后SCL都是0somenop();SDA=1; //拉高準備數(shù)據(jù)讀取_nop_();for(i=0;i<8;i++) //讀取8位數(shù)據(jù){SCL=1;somenop();dat<<=1;if(SDA==1)dat=dat"0x01;somenop();SCL=0; //下降沿時讀取數(shù)據(jù)somenop();}return dat;}
評論