模擬I2C為什么要將GPIO端口設置為開漏輸出?
時間:2023-10-24 來源:華清遠見
不知道大家有沒有跟我遇到類似的問題:我在fs4412開發板上調試mup6050(六軸傳感器)時,使用I2C通信協議,模擬I2C協議正確,但是一直讀取數據失敗,且伴隨著開發板發熱。最后發現造成該現象的原因是沒有配置GPIO為開漏輸出。
首先我們先簡單回顧一下I2C通信總線:
I2C(集成電路總線),是由飛利浦(Philips)公司開發的一種簡單、雙向二線制同步串行總線。它只需要兩根線(時間線和數據線)即可在連接于總線上的器件之間實現通信。每個連接到總線上的器件都有唯一的地址,任何器件既可以作為主機也可以作為從機,但同一時刻只允許有一個主機。

I2C信號的幾個重要的概念:
初始狀態(即空閑狀態):SCL和SDA均被上拉電阻鉗位在高電平的初始狀態;
開始信號:當SCL為高電平的時候,SDA被拉低,此為開始信號,表明通訊開始;
終止信號:當SCL為高電平的時候,SDA被拉高,此為終止信號,表明本次通訊結束;
應答信號:當發送器向接收器發送完一個字節(8位)數據后,第9個時鐘周期內,接收器必須給發送器一個應答信號,這樣數據才算傳輸成功。高電平表非應答,低電平表應答。
根據I2C總線的物理特性,I2C總線內部使用的是漏極開路輸出驅動器,這里的漏極開路輸出就是我們說的開漏輸出。因此特性SDA和SCL可以被拉低為低電平,但是不能被驅動為高電平,所以每條線上都要使用一個上拉電阻使得初始狀態為高電平。
開漏輸出:開漏輸出就是不輸出電壓,控制輸出低電平時引腳接地,控制輸出高電平時引腳既不輸出高電平,也不輸出低電平,為高阻態。如果外接上拉電阻,則在輸出高電平時電壓會拉到上拉電阻的電源電壓。這種方式適合在連接的外設電壓比單片機電壓低的時候。
以MOS管為例:
N-MOS管:漏極接正極,源極接負極,柵極正電壓時導電溝道建立;
P-MOS管:漏極接負極,源極接正極,柵極負電壓時導電溝道建立。
因此在不接上拉電阻時:輸出邏輯0,則N-MOS激活;輸出邏輯1,P-MOS不會激活,不會輸出高電平。在接上拉電阻時:輸出邏輯0,則N-MOS激活;
輸出邏輯1,P-MOS激活,可以輸出高電平。也就是說開漏輸出如果不接上拉電阻,是沒有輸出高電平的能力的。如果需要開漏輸出有輸出高電平的能力就需要接上拉電阻。
另外,在一些情況下(比如總線),多個GPIO口可能會連接在同一根線上,這樣就存在某個GPIO輸出高電平,但另一個GPIO輸出低電平的情況。如果不是使用開漏輸出,你會發現這個GPIO的VCC和另一個GPIO的GND接在了一起,會導致電路短路。而如果使用開漏輸出,VCC和GND之間就多了個上拉電阻,這樣就避免的短路,保證了電路安全。所以總線一般會使用開漏輸出。 回到開頭的那個問題,目前很多開發板是可以通過軟件給GPIO端口配置上拉電阻的,我一開始使用I2C協議并沒有將總線設置為開漏輸出,導致數據讀取失敗,并且由于電路短路導致開發板發熱。所以模擬I2C必須要將GPIO端口設置為開漏輸出。

