一. IIC的基本介紹
1.1IIC的簡介
IIC是雙線(不算地線)半雙工的一種通訊方式(可以雙向通訊,但不可以在同一時間雙向數(shù)據(jù)傳輸).
IIC串行總線一般有兩根信號線,一根是雙向的數(shù)據(jù)線SDA,另一根是時鐘線SCL,其時鐘信號是由主控器件產(chǎn)生。所有接到IIC總線設(shè)備上的串行數(shù)據(jù)SDA都接到總線的SDA上,各設(shè)備的時鐘線SCL接到總線的SCL上。對于并聯(lián)在一條總線上的每個IC都有唯一的地址。


1.2地址問題
IIC設(shè)備地址
協(xié)議格式中第一個字節(jié)(為slave address)由7位地址和一位R/W讀寫位組成的,這字節(jié)是個器件地址。
常用IIC接口通用器件的器件地址是由種類型號,及尋址碼組成的,共7位。
如格式如下:
D7 D6 D5 D4 D3 D2 D1 D0
(1)、器件類型:D7-D4共4位決定的。這是由半導(dǎo)公司生產(chǎn)時就已固定此類型的了,也就是說這4位已是固定的。
(2)、用戶自定義地址碼:D3-D1共3位。這是由用戶自己設(shè)置的,通常的作法如EEPROM這些器件是由外部IC的3個引腳所組合電平?jīng)Q定的(用常用的名字如A0,A1,A2)。這也就是尋址碼。所以為什么同一IIC總線上同一型號的IC只能最多共掛8片同種類芯片的原因了。
(3)、最低一位就是R/W位,,“0”表示寫,“1”表示讀(通常讀寫信號中寫上面有一橫線,表示低電平)。所以IIC設(shè)備通常有兩個地址,即讀地址和寫地址。
IIC 設(shè)備的7 位地址是就當(dāng)前IIC總線而言的,是“相對地址”。不同的IIC總線上的設(shè)備可以使用相同的7 位地址,但是它們所在的i2c 總線不同。所以在系統(tǒng)中一個IIC設(shè)備的“絕對地址”由二元組(IIC適配器的ID 和設(shè)備在該總線上的7 位地址)表示。”,所以這個函數(shù)的作用主要是排除同一IIC總線上出現(xiàn)多個地址相同的設(shè)備。
1.3 IIC協(xié)議
IIC總線在傳輸數(shù)據(jù)的過程中一共有三種類型信號,分別為:開始信號、結(jié)束信號和應(yīng)答信號。這些信號中,起始信號是必需的,結(jié)束信號和應(yīng)答信號,都可以不要。同時我們還要介紹其空閑狀態(tài)、數(shù)據(jù)的有效性、數(shù)據(jù)傳輸。

(1)空閑狀態(tài)
當(dāng)IIC總線的數(shù)據(jù)線SDA和時鐘線SCL兩條信號線同時處于高電平時,規(guī)定為總線的空閑狀態(tài)。此時各個器件的輸出級場效應(yīng)管均處在截止?fàn)顟B(tài),即釋放總線,由兩條信號線各自的上拉電阻把電平拉高。
(2)起始信號與停止信號
起始信號:當(dāng)時鐘線SCL為高期間,數(shù)據(jù)線SDA由高到低的跳變;啟動信號是一種電平跳變時序信號,而不是一個電平信號;
停止信號:當(dāng)時鐘線SCL為高期間,數(shù)據(jù)線SDA由低到高的跳變;停止信號也是一種電平跳變時序信號,而不是一個電平信號。

(3) 應(yīng)答信號
發(fā)送器每發(fā)送一個字節(jié)(8個bit),就在時鐘脈沖9期間釋放數(shù)據(jù)線,由接收器反饋一個應(yīng)答信號。
應(yīng)答信號為低電平時,規(guī)定為有效應(yīng)答位(ACK,簡稱應(yīng)答位),表示接收器已經(jīng)成功地接收了該字節(jié);
應(yīng)答信號為高電平時,規(guī)定為非應(yīng)答位(NACK),一般表示接收器接收該字節(jié)沒有成功。
對于反饋有效應(yīng)答位ACK的要求是:接收器在第9個時鐘脈沖之前的低電平期間將數(shù)據(jù)線SDA拉低,并且確保在該時鐘的高電平期間為穩(wěn)定的低電平。 如果接收器是主控器,則在它收到最后一個字節(jié)后,發(fā)送一個NACK信號,以通知被控發(fā)送器結(jié)束數(shù)據(jù)發(fā)送,并釋放數(shù)據(jù)線SDA,以便主控接收器發(fā)送一個停止信號P。

(4)數(shù)據(jù)有效性
IIC總線進(jìn)行數(shù)據(jù)傳送時,時鐘信號為高電平期間,數(shù)據(jù)線上的數(shù)據(jù)必須保持穩(wěn)定;只有在時鐘線上的信號為低電平期間,數(shù)據(jù)線上的高電平或低電平狀態(tài)才允許變化。即:數(shù)據(jù)在時鐘線SCL的上升沿到來之前就需準(zhǔn)備好。并在在下降沿到來之前必須穩(wěn)定。

(5)數(shù)據(jù)的傳達(dá)
在IIC總線上傳送的每一位數(shù)據(jù)都有一個時鐘脈沖相對應(yīng)(或同步控制),即在SCL串行時鐘的配合下,在SDA上逐位地串行傳送每一位數(shù)據(jù)。數(shù)據(jù)位的傳輸是邊沿觸發(fā)。

二.代碼
關(guān)于IIC代碼部分的內(nèi)容這里主要講解HAL塊部分的內(nèi)容。這里HAL初始化的三個部分包括:引腳配置初始化,寫數(shù)據(jù)函數(shù),讀數(shù)據(jù)函數(shù)。
在引腳配置的 IICInit 中對IIC的兩個 引腳(SCL,SDA)進(jìn)行引腳的配置,并對IIC相關(guān)的庫函數(shù)進(jìn)行配置,其中引腳的配置這里不再進(jìn)行講解,需要注意的是GPIO的模式要配置成GPIO_MODE_AF_OD 復(fù)用開漏輸出或者GPIO_Mode_Out_PP數(shù)據(jù)寄存器輸出。
關(guān)于IIC的配置,IIC的模式,自身地址,
typedef struct
{
uint32_t I2C_ClockSpeed; /*設(shè)置SCL時鐘頻,此值不低于40000*/
uint16_t I2C_Mode; /* 指定工作模式,可選I2C模式和SMBUS模式*/
uint16_t I2C_DutyCycle; /*指定時鐘占空比,可選 low/high=2:1以及16:9模式*/
uint16_t I2C_OwnAddress1; /*指定自身的I2C設(shè)備地址 */
uint16_t I2C_Ack; /*使能或者關(guān)閉響應(yīng) (一般都是使能) */
uint16_t I2C_AcknowledgedAddress; /*指定地址的長度,可以位7位及10位 */
}I2C_InitTypeDef;
? I2C_ClockSpeed 設(shè)置I2C的傳輸速率,在調(diào)用初始化函數(shù)時,函數(shù)會根據(jù)我們輸入的數(shù)值經(jīng)過運(yùn)算后把時鐘因子寫入到I2C的時鐘控制寄存器CCR。而我們寫入的這個參數(shù)值不得高于400KHz。實際上由于CCR寄存器不能寫入小數(shù)類型的時鐘因子,影響到 SCL的實際頻率可能會低于本成員設(shè)置的參數(shù)值,這時除了通訊稍慢一點以外,不會對I2C的標(biāo)準(zhǔn)通訊造成其它影響。
? I2C_Mode 選擇I2C的使用方式,有I2C模式(I2C_Mode_I2C )和SMBus主、從模式(I2C_Mode_SMBusHost、 I2C_Mode_SMBusDevice ) 。 I2C不需要在此處區(qū)分主從模式,直接設(shè)置I2C_Mode_I2C即可。
? I2C_DutyCycle 設(shè)置I 2C的SCL線時鐘的占空比。該配置有兩個選擇,分別為低電平時間比高電平時間為2:1 ( I2C_DutyCycle_2)和16:9 (I2C_DutyCycle_16_9)。其實這兩個模式的比例差別并不大,一般要求都不會如此嚴(yán)格,這里隨便選就可以了。
? I2C_OwnAddress1 配置STM32的I2C設(shè)備自己的地址,每個連接到I2C總線上的設(shè)備都要有一個自己的地址,作為主機(jī)也不例外。地址可設(shè)置為7位或10位(受下面 I2C_AcknowledgeAddress成員決定),只要該地址是I2C總線上唯一的即可。 STM32的I2C外設(shè)可同時使用兩個地址,即同時對兩個地址作出響應(yīng),這個結(jié)構(gòu)成員I2C_OwnAddress1配置的是默認(rèn)的、OAR1寄存器存儲的地址,若需要設(shè)置第二個地址寄存器OAR2,可使用 I2C_OwnAddress2Config函數(shù)來配置,OAR2不支持10位地址。
? I2C_Ack_Enable 配置I 2C應(yīng)答是否使能,設(shè)置為使能則可以發(fā)送響應(yīng)信號。一般配置為允許應(yīng)答(I2C_Ack_Enable),這是絕大多數(shù)遵循I 2C標(biāo)準(zhǔn)的設(shè)備的通訊要求,改為禁止應(yīng)答(I2C_Ack_Disable)往往會導(dǎo)致通訊錯誤。
? I2C_AcknowledgeAddress 選擇I2C的尋址模式是7位還是10位地址。這需要根據(jù)實際連接到I2C總線上設(shè)備的地址進(jìn)行選擇,這個成員的配置也影響到 I2C_OwnAddress1成員,只有這里設(shè)置成10位模式時, I2C_OwnAddress1才支持10位地址。
利用庫函數(shù)版本編寫HAL代碼部分如下:
void IICInit(void)
{
/*GPIO初始化*/
GPIO_InitTypeDef GPIO_InitStructure;
/* 配置硬件IIC需要的變量 */
I2C_InitTypeDef I2C_InitStructure;
/* 使能與 I2C1 有關(guān)的時鐘 */
RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOB,ENABLE );
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
/* PB6-I2C1_SCL、PB7-I2C1_SDA*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/*IIC外設(shè)初始化*/
/* I2C 配置 */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C ; //配置為普通IIC模式
//I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
//I2C_InitStructure.I2C_OwnAddress1 = SlaveAddress;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; //使能自動應(yīng)答
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = 50000; //5K的速度?
/* I2C1 初始化 */
I2C_Init(I2C1, &I2C_InitStructure);
/* 使能 I2C1 */
I2C_Cmd (I2C1,ENABLE);
/*允許應(yīng)答模式*/
I2C_AcknowledgeConfig(I2C1, ENABLE);
}
void ByteWrite(u8 addr,u8 dataValue)
{
I2C_GenerateSTART(I2C1,ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
I2C_SendData(I2C1,addr);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_SendData(I2C1,dataValue);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTOP(I2C1,ENABLE);
}
u8 ByteRead(u8 addr)
{
u8 dataValue;
while(I2C_GetFlagStatus(I2C1,I2C_FLAG_BUSY));
I2C_GenerateSTART(I2C1,ENABLE);//起始信號
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Transmitter);//發(fā)送設(shè)備地址+寫信號
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));//
I2C_Cmd(I2C1,ENABLE);
I2C_SendData(I2C1,addr);//發(fā)送存儲單元地址,從0開始
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED));
I2C_GenerateSTART(I2C1,ENABLE);//起始信號
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT));
I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Receiver);//發(fā)送設(shè)備地址+讀信號
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
I2C_AcknowledgeConfig(I2C1,DISABLE);
I2C_GenerateSTOP(I2C1,ENABLE);
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)));
dataValue=I2C_ReceiveData(I2C1);//讀出寄存器數(shù)據(jù)
return dataValue;
}
審核編輯:湯梓紅
-
IIC
+關(guān)注
關(guān)注
11文章
306瀏覽量
39489 -
串行總線
+關(guān)注
關(guān)注
1文章
185瀏覽量
31110 -
代碼
+關(guān)注
關(guān)注
30文章
4900瀏覽量
70694
發(fā)布評論請先 登錄
一文詳解IIC總線

一文詳解IIC總線


IIC總線的相關(guān)資料推薦
IIC總線接口學(xué)習(xí)

IIC總線時序詳解

IIC總線初始化基本驅(qū)動參考程序應(yīng)用代碼免費(fèi)下載

評論