日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

I2C总线标准代码

發(fā)布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 I2C总线标准代码 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

/********

起始信號,SCL=1,時鐘總線為高電平,數(shù)據(jù)總線由高電平變?yōu)榈碗娖絊DA=1-->SDA=0

void I2C_Start(void)

{

I2C_SCL_HIGH();//SCL=1

I2C_SDA_HIGH();//SDA=1? 開始都為高電平,當(dāng)SDA為低電平為起始信號

I2C_DELAY();

I2C_SDA_LOW();

I2C_DELAY();

I2C_SCL_LOW();

I2C_DELAY();

}

停止信號 SCL=1,SDA=0,時鐘總線為高電平,數(shù)據(jù)總線由低電平變?yōu)楦唠娖絊DA=0-->SDA=1

void I2C_Stop(void)

{

????I2C_SDA_Low();

????I2C_SCL_High();

????I2C_Delay();

????I2C_SDA_High();

????I2C_Delay();

}

發(fā)送一個字節(jié)8位

u8 I2C_SendByte(uint8_t Byte)

{

????uint8_t i;

????for(i = 0 ; i < 8 ; i++)/* 先發(fā)送高位字節(jié) */

????{

????????if(Byte & 0x80)

????????{

????????????I2C_SDA_High();

????????}

????????else

????????{

????????????I2C_SDA_Low();

????????}

????????I2C_Delay();

????????I2C_SCL_High();

????????I2C_Delay();

????????I2C_SCL_Low();

????????I2C_Delay();

????????if(i == 7)

????????{

????????????I2C_SDA_High();?????????????????????/* 釋放SDA總線 */

????????}

????????Byte <<= 1;?????????????????????????????/* 左移一位? */

????????I2C_Delay();

????}

} 

?

//CPU從I2C總線設(shè)備上讀取一個字節(jié)(8bit數(shù)據(jù))
u8 I2C_ReadByte(void)

{

? ? uint8_t i;

? ? uint8_t value;

?

? ? /* 先讀取最高位即bit7 */

? ? value = 0;

? ? for(i = 0 ; i < 8 ; i++)

? ? {

? ? ? ? value <<= 1;

? ? ? ? I2C_SCL_High();

? ? ? ? I2C_Delay();

? ? ? ? if(I2C_SDA_READ())

? ? ? ? {

? ? ? ? ? ? value++;

? ? ? ? }

? ? ? ? I2C_SCL_Low();

? ? ? ? I2C_Delay();

? ? }

? ? return value;

}
//CPU產(chǎn)生一個ACK信號
void I2C_Ack(void)

{

? ? I2C_SDA_Low();

? ? I2C_Delay();

? ? I2C_SCL_High();

? ? I2C_Delay();

? ? I2C_SCL_Low();

? ? I2C_Delay();

? ? I2C_SDA_High();

}
//CPU產(chǎn)生一個非ACK信號
void I2C_NoAck(void)

{

? ? I2C_SDA_High();
? ? I2C_Delay();
? ? I2C_SCL_High();
? ? I2C_Delay();
? ? I2C_SCL_Low();
? ? I2C_Delay();

}
//CPU產(chǎn)生一個時鐘,并讀取器件的ACK應(yīng)答信號
uint8_t I2C_WaitToAck(void)

{

? ? uint8_t redata;

? ? I2C_SDA_High();
? ? I2C_Delay();
? ? I2C_SCL_High();
? ? I2C_Delay();
? ? if(I2C_SDA_READ())

? ? {
? ? ? ? redata = 1;
? ? }
? ? else
? ? {
? ? ? ? redata = 0;
? ? }
? ? I2C_SCL_Low();
? ? I2C_Delay();
? ? return redata;
}

寫數(shù)據(jù)時序圖進(jìn)行分解,經(jīng)分解后如下圖所示:

結(jié)合I2C總線協(xié)議的知識,我們可以知道I2C寫數(shù)據(jù)由一下10個步驟組成。?
??第一步,發(fā)送一個起始信號。?
??第二步,發(fā)送7bit從機(jī)地址,即OZ9350的地址。此處需要注意,發(fā)送數(shù)據(jù)時,無法發(fā)送7bit數(shù)據(jù),此處發(fā)送了7bit地址+1bit讀寫選擇位,即發(fā)送7bit+r/w。最低位為1表示讀,為0表示寫。?
??第三步,產(chǎn)生一個ACK應(yīng)答信號,此應(yīng)答信號為從機(jī)器件產(chǎn)生的應(yīng)答。?
??第四步,發(fā)送寄存器地址,8bit數(shù)據(jù)。?
??第五步,產(chǎn)生一個ACK應(yīng)答信號,此應(yīng)答信號為從機(jī)器件產(chǎn)生的應(yīng)答。?
??第六步,發(fā)送一個數(shù)據(jù),8bit數(shù)據(jù)。?
??第七步,產(chǎn)生一個ACK應(yīng)答信號,此應(yīng)答信號為從機(jī)器件產(chǎn)生的應(yīng)答信號。?
??第八步,發(fā)送一個CRC校驗(yàn)碼,此CRC校驗(yàn)值為2、4、6步數(shù)據(jù)產(chǎn)生的校驗(yàn)碼。?
??第九步,既可以發(fā)送一個應(yīng)答信號,也可以發(fā)送一個無應(yīng)答信號,均有從機(jī)器件產(chǎn)生。?
??第十步,發(fā)送一個停止信號。?
??接下來,按照以上十個步驟,可以寫出i2c寫數(shù)據(jù)的函數(shù)。代碼如下: ?

u8 I2C_WriteBytes(void)

{

? ? I2C_Start(); ? ? ? ? ? ? ? ? ? ?//1
? ? I2C_SendByte(Slaver_Addr | 0); ?//2
? ? I2C_WaitToAck(); ? ? ? ? ? ? ? ?//3
? ? I2C_SendByte(Reg_Addr); ? ? ? ? //4
? ? I2C_WaitToAck(); ? ? ? ? ? ? ? ?//5
? ? I2C_SendByte(data); ? ? ? ? ? ? //6
? ? I2C_WaitToAck(); ? ? ? ? ? ? ? ?//7
? ? I2C_SendByte(crc); ? ? ? ? ? ? ?//8
? ? I2C_WaitToAck(); ? ? ? ? ? ? ? ?//9
? ? I2C_Stop(); ? ? ? ? ? ? ? ? ? ? //10

}

讀數(shù)據(jù)的時序圖經(jīng)分解后如下圖所示:

通過分解后的時序圖,可以看到OZ9350的讀數(shù)據(jù)由以下13個步驟組成。?
??第一步,發(fā)送一個起始信號。?
??第二步,發(fā)送7bit從機(jī)地址,即OZ9350的地址。此處需要注意,發(fā)送數(shù)據(jù)時,無法發(fā)送7bit數(shù)據(jù),此處發(fā)送了7bit地址+1bit讀寫選擇位,即發(fā)送7bit+r/w。最低位為1表示讀,為0表示寫。?
??第三步,產(chǎn)生一個ACK應(yīng)答信號,此應(yīng)答信號為從機(jī)器件產(chǎn)生的應(yīng)答。?
??第四步,發(fā)送寄存器地址。?
??第五步,產(chǎn)生一個ACK應(yīng)答信號,此應(yīng)答信號為從機(jī)器件產(chǎn)生的應(yīng)答。?
??第六步,再次發(fā)送一個騎士信號。?
??第七步,發(fā)送7bit從機(jī)地址,即OZ9350的地址。此處需要注意,發(fā)送數(shù)據(jù)時,無法發(fā)送7bit數(shù)據(jù),此處發(fā)送了7bit地址+1bit讀寫選擇位,即發(fā)送7bit+r/w。最低位為1表示讀,為0表示寫。?
??第八步,產(chǎn)生一個ACK應(yīng)答信號,此應(yīng)答信號為從機(jī)器件產(chǎn)生的應(yīng)答。?
??第九步,讀取一個字節(jié)(8bit)的數(shù)據(jù)。?
??第十步,產(chǎn)生一個ACK應(yīng)答信號,此應(yīng)答信號為CPU產(chǎn)生。?
??第十一步,讀取一個CRC校驗(yàn)碼。?
??第十二步,產(chǎn)生一個NACK信號。此無應(yīng)答信號由CPU產(chǎn)生。?
??第十三步,產(chǎn)生一個停止信號。?
??接下來,由以上分析步驟,可以寫出OZ9350的I2C讀數(shù)據(jù)代碼。如下所示:

u8 I2C_ReadBytes(void)

{
? ? u8 data;
? ? u8 crc;
? ? I2C_Start(); ? ? ? ? ? ? ? ? ? ?//1
? ? I2C_SendByte(Slaver_Addr | 0); ?//2
? ? I2C_WaitToAck(); ? ? ? ? ? ? ? ?//3
? ? I2C_SendByte(Reg_Addr); ? ? ? ? //4
? ? I2C_WaitToAck(); ? ? ? ? ? ? ? ?//5
? ? I2C_Start(); ? ? ? ? ? ? ? ? ? //6
? ? I2C_SendByte(Slaver_Addr | 1); ?//7 1-讀
? ? I2C_WaitToAck(); ? ? ? ? ? ? ? ?//8
? ? data=I2C_ReadByte(); ? ? ? ? ? ?//9
? ? I2C_Ack(); ? ? ? ? ? ? ? ? ? ? ?//10
? ? crc=I2C_ReadByte(); ? ? ? ? ? ? //11
? ? I2C_NoAck(); ? ? ? ? ? ? ? ? ? ?//12
? ? I2C_Stop(); ? ? ? ? ? ? ? ? ? ? //13
}

寫:MCU在數(shù)據(jù)總線上的數(shù)據(jù)穩(wěn)定之后,檢測邊沿信號(上升沿)寫數(shù)據(jù)到器件;
讀:MCU發(fā)出邊沿信號(下降沿)告訴器件發(fā)送數(shù)據(jù),檢測到邊沿信號之后,器件改變(更新)數(shù)據(jù),等待穩(wěn)定之后MCU讀取數(shù)據(jù)

數(shù)據(jù)的寫操作:圖中演示了I2C連續(xù)寫數(shù)據(jù),兩個字節(jié)的連續(xù)寫入,更多字節(jié)同樣

數(shù)據(jù)的讀操作:在上圖中,可以認(rèn)為寫入了設(shè)備地址及寄存器地址,再次重啟總線后,發(fā)送讀命令,連續(xù)讀取兩個字節(jié),發(fā)送NACK,發(fā)送停止信號;

?

總結(jié)

以上是生活随笔為你收集整理的I2C总线标准代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。