0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

三星I2C控制如何實(shí)現(xiàn)裸機(jī)讀取從設(shè)備信息

牽手一起夢(mèng) ? 來(lái)源:一口Linux ? 作者:一口Linux ? 2021-01-19 15:34 ? 次閱讀

前言

I2C(Inter-Integrated Circuit)總線(xiàn)(也稱(chēng) IIC 或 I2C) 是有PHILIPS公司開(kāi)發(fā)的兩線(xiàn)式串行總線(xiàn),用于連接微控制器及外圍設(shè)備,是微電子通信控制領(lǐng)域廣泛采用的一種總線(xiàn)標(biāo)準(zhǔn)。它是同步通信的一種特殊形式,具有接口線(xiàn)少、控制方式簡(jiǎn)單、器件封裝形式小、通信速率較高等優(yōu)點(diǎn)。

三星I2C控制如何實(shí)現(xiàn)裸機(jī)讀取從設(shè)備信息

Exynos4412 i2c控制器綜述

Exynos4412精簡(jiǎn)指令集微處理器支持4個(gè)IIC總線(xiàn)控制器。為了能使連接在總線(xiàn)上的主和從設(shè)備之間傳輸數(shù)據(jù),專(zhuān)用的數(shù)據(jù)線(xiàn)SDA和時(shí)鐘信號(hào)線(xiàn)SCL被使用,他們都是雙向的。

如果工作在多主機(jī)的IIC總線(xiàn)模式,多個(gè)4412處理器將從從機(jī)那接收數(shù)據(jù)或發(fā)送數(shù)據(jù)給從機(jī)。在IIC總線(xiàn)上的主機(jī)端4412會(huì)啟動(dòng)或終止一個(gè)數(shù)據(jù)傳輸。4412的IIC總線(xiàn)控制器會(huì)用一個(gè)標(biāo)準(zhǔn)的IIC總線(xiàn)仲裁機(jī)制去實(shí)現(xiàn)多主機(jī)和多從機(jī)傳輸數(shù)據(jù)。

通過(guò)控制如下寄存器以實(shí)現(xiàn)IIC總線(xiàn)上的多主機(jī)操作:

控制寄存器: I2CCON狀態(tài)寄存器: I2CSTATTx/Rx數(shù)據(jù)偏移寄存器:I2CDS地址寄存器: I2CADD

如果I2C總線(xiàn)空閑,那么SCL和SDA信號(hào)線(xiàn)將都為高電平。在SCL為高電平期間,如果SDA有由高到低電平的跳變,那么將啟動(dòng)一個(gè)起始信號(hào),如果SDA有由低到高電平的跳變,將啟動(dòng)一個(gè)結(jié)束信號(hào)。

主機(jī)端的設(shè)備總是提供起始和停止信號(hào)的一端。在起始信號(hào)被發(fā)出后,一個(gè)數(shù)據(jù)字節(jié)的前7位被當(dāng)作地址通過(guò)SDA線(xiàn)被傳輸。這個(gè)地制值決定了總線(xiàn)上的主設(shè)備將要選擇那個(gè)從設(shè)備作為傳輸對(duì)象,bit8決定傳輸數(shù)據(jù)的方向(是讀還是寫(xiě))。

I2C總線(xiàn)上的數(shù)據(jù)(即在SDA上傳輸?shù)臄?shù)據(jù))都是以8位字節(jié)傳輸?shù)?,在總線(xiàn)上傳輸操作的過(guò)程中,對(duì)發(fā)送或接收的數(shù)據(jù)字節(jié)數(shù)是沒(méi)有限制的。I2C總線(xiàn)上的主/從設(shè)備發(fā)送數(shù)據(jù)總是以一個(gè)數(shù)據(jù)的最高位開(kāi)始傳輸(即MSB方式),傳輸完一個(gè)字節(jié)后,應(yīng)答信號(hào)緊接其后。

Exynos4412 I2C總線(xiàn)接口特性共有9個(gè)通道,支持多主、從I2C總線(xiàn)接口。其中8個(gè)通道作為普通接口(即I2C0、I2C1....),1個(gè)通道作為HDMI的專(zhuān)用接口。7位地址模式。串行,8位單向或雙向的數(shù)據(jù)傳輸。在標(biāo)準(zhǔn)模式中,每秒最多可以傳輸100k位,即12.5kB的數(shù)據(jù)量。在快速模式中,每秒最多可以傳輸400k位,即50kB的數(shù)據(jù)量。支持主機(jī)端發(fā)送、接收,從機(jī)端發(fā)送、接收操作。支持中斷和查詢(xún)方式。框圖

從上圖可以看出,4412提供4個(gè)寄存器來(lái)完成所有的IIC操作。SDA線(xiàn)上的數(shù)據(jù)從IICDS寄存器經(jīng)過(guò)移位寄存器發(fā)出,或通過(guò)移位寄存器傳入IICDS寄器;IICADD寄存器中保存4412當(dāng)做從機(jī)時(shí)的地址;IICCON、IICSTAT兩個(gè)寄存器用來(lái)控制或標(biāo)識(shí)各種狀態(tài),比如選擇工作工作模式,發(fā)出S信號(hào)、P信號(hào),決定是否發(fā)出ACK信號(hào),檢測(cè)是否接收到ACK信號(hào)。

I2C總線(xiàn)接口操作

針對(duì)4412處理器的I2C總線(xiàn)接口,具備4種操作模式:

主機(jī)發(fā)送模式主機(jī)接收模式從機(jī)發(fā)送模式從機(jī)接收模式

下面將描述這些操作模式之間的功能關(guān)系:

0、數(shù)據(jù)有效性

SDA線(xiàn)上的數(shù)據(jù)必須在時(shí)鐘的高電平周期保持穩(wěn)定。數(shù)據(jù)線(xiàn)的高或低電平狀態(tài)IIC位傳輸數(shù)據(jù)的有效性在SCL線(xiàn)的時(shí)鐘信號(hào)是低電平才能改變。

1. 開(kāi)始和停止條件

當(dāng)4412的I2C接口空閑時(shí),它往往工作在從機(jī)模式。或者說(shuō),4412的的i2c接口在SDA線(xiàn)上察覺(jué)到一個(gè)起始信號(hào)之前它應(yīng)該工作在從機(jī)模式。當(dāng)控制器改變4412的i2c接口的工作模式為主機(jī)模式后,SDA線(xiàn)上發(fā)起數(shù)據(jù)傳輸并且控制器會(huì)產(chǎn)生SCL時(shí)鐘信號(hào)。

開(kāi)始條件通過(guò)SDA線(xiàn)進(jìn)行串行的字節(jié)傳輸,一個(gè)停止信號(hào)終止數(shù)據(jù)傳輸,停止信號(hào)是指SCL在高電平器件SDA線(xiàn)有從低到高電平的跳變,主機(jī)端產(chǎn)生起始和停止條件。當(dāng)主、從設(shè)備產(chǎn)生一個(gè)起始信號(hào)后,I2C總線(xiàn)將進(jìn)入忙狀態(tài)。這里需要說(shuō)明的是上述主從設(shè)備都有可能作為主機(jī)端。

當(dāng)一個(gè)主機(jī)發(fā)送了一個(gè)起始信號(hào)后,它也應(yīng)該發(fā)送一個(gè)從機(jī)地址以通知總線(xiàn)上的從設(shè)備。這個(gè)地址字節(jié)的低7位表示從設(shè)備地址,最高位表示傳輸數(shù)據(jù)的方向,即主機(jī)將要進(jìn)行讀還是寫(xiě)。當(dāng)最高位是0時(shí),它將發(fā)起一個(gè)寫(xiě)操作(發(fā)送操作);當(dāng)最高位是1時(shí),它將發(fā)起一個(gè)讀數(shù)據(jù)的請(qǐng)求(接收操作)。

主機(jī)端發(fā)起一個(gè)結(jié)束信號(hào)以完成傳輸操作,如果主機(jī)端想在總線(xiàn)上繼續(xù)進(jìn)行數(shù)據(jù)的傳輸,它將發(fā)出另外一個(gè)起始信號(hào)和從設(shè)備地址。用這樣的方式,它們可以用各種各樣的格式進(jìn)行讀寫(xiě)操作。

下圖為起始和停止信號(hào):

2. 數(shù)據(jù)傳輸格式

放到SDA線(xiàn)上的所有字節(jié)數(shù)據(jù)的長(zhǎng)度應(yīng)該為8位,在每次傳輸數(shù)據(jù)時(shí),對(duì)傳輸數(shù)據(jù)量沒(méi)有限制。在起始信號(hào)后的第一個(gè)數(shù)據(jù)字節(jié)應(yīng)該包含地址字段,當(dāng)4412的I2C接口被設(shè)置為主模式時(shí),地址字節(jié)應(yīng)該由控制器端發(fā)出。在每個(gè)字節(jié)后,應(yīng)該有一個(gè)應(yīng)答位。

如果從機(jī)要完成一些其他功能后(例如一個(gè)內(nèi)部中斷服務(wù)程序)才能繼續(xù)接收或發(fā)送下一個(gè)字節(jié),從機(jī)可以拉低SCL迫使主機(jī)進(jìn)入等待狀態(tài)。當(dāng)從機(jī)準(zhǔn)備好接收下一個(gè)數(shù)據(jù)并釋放SCL后,數(shù)據(jù)傳輸繼續(xù)。如果主機(jī)在傳輸數(shù)據(jù)期間也需要完成一些其他功能(例如一個(gè)內(nèi)部中斷服務(wù)程序)也可以拉低SCL以占住總線(xiàn)。

下面的圖中將說(shuō)明數(shù)據(jù)傳輸格式:

上圖中說(shuō)明,在傳輸完每個(gè)字節(jié)數(shù)據(jù)后,都會(huì)有一個(gè)應(yīng)答信號(hào),這個(gè)應(yīng)答信號(hào)在第9個(gè)時(shí)鐘周期。具體過(guò)程如下(注意下面描述的讀寫(xiě)過(guò)程都是針對(duì) 4412處理器而言,當(dāng)有具體的I2C設(shè)備與4412相連時(shí),數(shù)據(jù)表示什么需要看具體的I2C設(shè)備,4412是不知道數(shù)據(jù)的含義的):

寫(xiě)過(guò)程:主機(jī)發(fā)送一個(gè)起始信號(hào)S→發(fā)送從機(jī)7位地址和1位方向,方向位表示寫(xiě)→主機(jī)釋放SDA線(xiàn)方便從機(jī)給回應(yīng)→有從機(jī)匹配到地址,拉低SDA線(xiàn)作為ACK→主機(jī)重新獲得SDA傳輸8位數(shù)據(jù)→主機(jī)釋放SDA線(xiàn)方便從機(jī)給回應(yīng)→從機(jī)收到數(shù)據(jù)拉低SDA線(xiàn)作為ACK告訴主機(jī)數(shù)據(jù)接收成功→主機(jī)發(fā)出停止信號(hào)。

讀過(guò)程:主機(jī)發(fā)送一個(gè)起始信號(hào)S→發(fā)送從機(jī)7位地址和1位方向,方向位表示讀→主機(jī)釋放SDA線(xiàn)方便從機(jī)給回應(yīng)→有從機(jī)匹配到地址,拉低SDA線(xiàn)作為ACK→從機(jī)繼續(xù)占用SDA線(xiàn),用SDA傳輸8位數(shù)據(jù)給主機(jī)→從機(jī)釋放SDA線(xiàn)(拉高)方便主機(jī)給回應(yīng)→主機(jī)接收到數(shù)據(jù)→主機(jī)獲得SDA線(xiàn)控制并拉低SDA線(xiàn)作為ACK告訴從機(jī)數(shù)據(jù)接收成功→主機(jī)發(fā)出停止信號(hào)。

注意:在具體的I2C通信時(shí),要看I2C設(shè)備才能確定讀寫(xiě)時(shí)序,比如下面即將描述的第七大點(diǎn)中的示例,讀寫(xiě)EEPROM中就會(huì)說(shuō)道具體的數(shù)據(jù)含義,讀寫(xiě)過(guò)程。

3. 應(yīng)答信號(hào)的傳輸

為了完成一個(gè)字節(jié)數(shù)據(jù)的傳輸,接收方將發(fā)送一個(gè)應(yīng)答位給發(fā)送方。應(yīng)答信號(hào)出現(xiàn)在SCL線(xiàn)上的時(shí)鐘周期中的第九個(gè)時(shí)鐘周期,為了發(fā)送或接收1個(gè)字節(jié)的數(shù)據(jù),主機(jī)端會(huì)產(chǎn)生8個(gè)時(shí)鐘周期,為了傳輸一個(gè)ACK位,主機(jī)端需要產(chǎn)生一個(gè)時(shí)鐘脈沖。ACK時(shí)鐘脈沖到來(lái)之際,發(fā)送方會(huì)在SDA線(xiàn)上設(shè)置高電平以釋放SDA線(xiàn)。在ACK時(shí)鐘脈沖之間,接收方會(huì)驅(qū)動(dòng)和保持SDA線(xiàn)為低電平,這發(fā)生在第9個(gè)時(shí)鐘脈沖為高電平期間。應(yīng)答信號(hào)為低電平時(shí),規(guī)定為有效應(yīng)答位(ACK簡(jiǎn)稱(chēng)應(yīng)答位),表示接收器已經(jīng)成功地接收了該字節(jié);應(yīng)答信號(hào)為高電平時(shí),規(guī)定為非應(yīng)答位(NACK),一般表示接收器接收該字節(jié)沒(méi)有成功。對(duì)于反饋有效應(yīng)答位ACK的要求是,接收器在第9個(gè)時(shí)鐘脈沖之前的低電平期間將SDA線(xiàn)拉低,并且確保在該時(shí)鐘的高電平期間為穩(wěn)定的低電平。如果接收器是主控器,則在它收到最后一個(gè)字節(jié)后,發(fā)送一個(gè)NACK信號(hào)(即不發(fā)出ACK信號(hào)),以通知被控發(fā)送器結(jié)束數(shù)據(jù)發(fā)送,并釋放SDA線(xiàn),以便主控接收器發(fā)送一個(gè)停止信號(hào)P。

4. 讀寫(xiě)操作

當(dāng)I2C控制器在發(fā)送模式下發(fā)送數(shù)據(jù)后,I2C總線(xiàn)接口將等待直到移位寄存器(I2CDS)接收到一個(gè)數(shù)據(jù)。在往此寄存器寫(xiě)入一個(gè)新數(shù)據(jù)前,SCL線(xiàn)應(yīng)該保持為低電平,寫(xiě)完數(shù)據(jù)后,I2C控制器將釋放SCL線(xiàn)。當(dāng)前正在傳輸?shù)臄?shù)據(jù)傳輸完成后,4412會(huì)捕捉到一個(gè)中斷,然后cpu將開(kāi)始往I2CDS寄存器中寫(xiě)入一個(gè)新的數(shù)據(jù)。

當(dāng)I2C控制器在接收模式下接收到數(shù)據(jù)后,I2C總線(xiàn)接口將等待直到I2CDS寄存器被讀。在讀到新數(shù)據(jù)之前,SCL線(xiàn)會(huì)被保持為低電平,讀到數(shù)據(jù)后I2C控制器將釋放掉SCL線(xiàn)。一個(gè)新數(shù)據(jù)接收完成后,4412將收到一個(gè)中斷,cpu收到這個(gè)中斷請(qǐng)求后,它將從I2CDS寄存器中讀取數(shù)據(jù)。

5. 總線(xiàn)仲裁機(jī)制

總線(xiàn)上可能掛接有多個(gè)器件,有時(shí)會(huì)發(fā)生兩個(gè)或多個(gè)主器件同時(shí)想占用總線(xiàn)的情況,這種情況叫做總線(xiàn)競(jìng)爭(zhēng)。I2C總線(xiàn)具有多主控能力,可以對(duì)發(fā)生在SDA線(xiàn)上的總線(xiàn)競(jìng)爭(zhēng)進(jìn)行仲裁,其仲裁原則是這樣的:當(dāng)多個(gè)主器件同時(shí)想占用總線(xiàn)時(shí),如果某個(gè)主器件發(fā)送高電平,而另一個(gè)主器件發(fā)送低電平,則發(fā)送電平與此時(shí)SDA總線(xiàn)電平不符的那個(gè)器件將自動(dòng)關(guān)閉其輸出級(jí)??偩€(xiàn)競(jìng)爭(zhēng)的仲裁是在兩個(gè)層次上進(jìn)行的。首先是地址位的比較,如果主器件尋址同一個(gè)從器件,則進(jìn)入數(shù)據(jù)位的比較,從而確保了競(jìng)爭(zhēng)仲裁的可靠性。由于是利用I2C總線(xiàn)上的信息進(jìn)行仲裁,因此不會(huì)造成信息的丟失。

6. 終止條件

當(dāng)一個(gè)從接收者不能識(shí)別從地址時(shí),它將保持SDA線(xiàn)為高電平。在這樣的情況下,主機(jī)會(huì)產(chǎn)生一個(gè)停止信號(hào)并且取消數(shù)據(jù)的傳輸。當(dāng)終止傳輸產(chǎn)生后,主機(jī)端接收器會(huì)通過(guò)取消ACK的產(chǎn)生以告訴從機(jī)端發(fā)送器結(jié)束發(fā)送操作。這將在主機(jī)端接收器接收到從機(jī)端發(fā)送器發(fā)送的最后一個(gè)字節(jié)之后發(fā)生,為了讓主機(jī)端產(chǎn)生一個(gè)停止條件,從機(jī)端發(fā)送者將釋放SDA線(xiàn)。

7. 配置I2C總線(xiàn)

如果要設(shè)置I2C總線(xiàn)中SCL時(shí)鐘信號(hào)的頻率,可以在I2CCON寄存器中設(shè)置4位分頻器的值。I2C總線(xiàn)接口地址值存放在I2C總線(xiàn)地址寄存器(I2CADD)中,默認(rèn)值未知。

8. 每種模式下的操作流程圖

在I2C總線(xiàn)上執(zhí)行任何的收發(fā)Tx/Rx操作前,應(yīng)該做如下配置:

(1)在I2CADD寄存器中寫(xiě)入從設(shè)備地址(2)設(shè)置I2CCON控制寄存器

a. 使能中斷b. 定義SCL頻率

(3)設(shè)置I2CSTAT寄存器以使能串行輸出

下圖為主設(shè)備發(fā)送模式

下圖為主設(shè)備接收模式

下圖為從設(shè)備發(fā)送模式

下圖為從設(shè)備接收模式

I2C控制器寄存器

I2C控制器用到的寄存器如下所示:

1-- I2C總線(xiàn)控制寄存器

IICCON寄存器用于控制是否發(fā)出ACK信號(hào)、設(shè)置發(fā)送器的時(shí)鐘、開(kāi)啟I2C中斷,并標(biāo)識(shí)中斷是否發(fā)生

使用IICCON寄存器時(shí),有如下注意事項(xiàng)

發(fā)送模式的時(shí)鐘頻率由位[6]、位[3:0]聯(lián)合決定。另外,當(dāng) IICCON[6]=0時(shí),IICCON[3:0]不能取0或1。

位[4]用來(lái)標(biāo)識(shí)是否有I2C中斷發(fā)生,讀出為0時(shí)標(biāo)識(shí)沒(méi)有中斷發(fā)生,讀出為1時(shí)標(biāo)識(shí)有中斷發(fā)生。當(dāng)此位為1時(shí),SCL線(xiàn)被拉低,此時(shí)所以I2C傳輸停止;如果要繼續(xù)傳輸,需寫(xiě)入0清除它。

中斷在以下3種情況下發(fā)生:

當(dāng)發(fā)送地址信息或接收到一個(gè)從機(jī)地址并且吻合時(shí);當(dāng)總線(xiàn)仲裁失敗時(shí);當(dāng)發(fā)送/接收完一個(gè)字節(jié)的數(shù)據(jù)(包括響應(yīng)位)時(shí);

基于SDA、SCL線(xiàn)上時(shí)間特性的考慮,要發(fā)送數(shù)據(jù)時(shí),先將數(shù)據(jù)寫(xiě)入IICDS寄存器,然后再清除中斷。

如果IICCON[5]=0,IICCON[4]將不能正常工作,所以,即使不使用I2C中斷,也要將IICCON[5]設(shè)為1.

2 -- I2C狀態(tài)寄存器

IICSTAT寄存器用于選擇I2C接口的工作模式,發(fā)出S信號(hào)、P信號(hào),使能接收/發(fā)送功能,并標(biāo)識(shí)各種狀態(tài),比如總線(xiàn)仲裁是否成功、作為從機(jī)時(shí)是否被尋址、是否接收到0地址、是否接收到ACK信號(hào)等。

3 -- I2C數(shù)據(jù)發(fā)送/接收移位寄存器

fs4412的i2c總線(xiàn)上掛載了mpu6050

mpu6050每次讀取或者要寫(xiě)入數(shù)據(jù)時(shí),必須先告知從設(shè)備要操作的內(nèi)部寄存器地址(RA),然后緊跟著讀取或者寫(xiě)入數(shù)據(jù)(DATA),內(nèi)部寄存器的配置和讀取一次最多1個(gè)data,交互時(shí)序如下:

【注意】上述兩個(gè)時(shí)序非常重要,下面我們編寫(xiě)基于linux的驅(qū)動(dòng)編寫(xiě)i2c_msg還要再依賴(lài)他。

上述簡(jiǎn)化時(shí)序的術(shù)語(yǔ)解釋如下

【寄存器使用規(guī)則】

下面先提前講一下具體應(yīng)用中如何啟動(dòng)和恢復(fù)IIC的傳輸啟動(dòng)或恢復(fù)4412的I2C傳輸有以下兩種方法。1) 當(dāng)IICCON[4]即中斷狀態(tài)位為0時(shí),通過(guò)寫(xiě)IICSTAT寄存器啟動(dòng)I2C操作。有以下兩種情況。

1--在主機(jī)模式,令I(lǐng)ICSTAT[5:4]等于0b11,將發(fā)出S信號(hào)和IICDS寄存器的數(shù)據(jù)(尋址),令I(lǐng)ICSTAT[5:4]等于0b01,將發(fā)出P信號(hào)。2--在從機(jī)模式,令I(lǐng)ICSTAT[4]等于1將等待其他主機(jī)發(fā)出S信號(hào)及地址信息。

2)當(dāng)IICCON[4]即中斷狀態(tài)為1時(shí),表示I2C操作被暫停。在這期間設(shè)置好其他寄存器之后,向IICCON[4]寫(xiě)入0即可恢復(fù)I2C操作。所謂“設(shè)置其他寄存器”,有以下三種情況:

1--對(duì)于主機(jī)模式,可以按照上面1的方法寫(xiě)IICSTAT寄存器,恢復(fù)I2C操作后即可發(fā)出S信號(hào)和IICDS寄存器的值(尋址),或發(fā)出P信號(hào)。2--對(duì)于發(fā)送器,可以將下一個(gè)要發(fā)送的數(shù)據(jù)寫(xiě)入IICDS寄存器中,恢復(fù)I2C操作后即可發(fā)出這個(gè)數(shù)據(jù)。3--對(duì)于接收器,可以從IICDS寄存器讀出接收到的數(shù)據(jù)。最后向IICCON[4]寫(xiě)入0的同時(shí),設(shè)置IICCON[7]以決定是否在接收到下一個(gè)數(shù)據(jù)后是否發(fā)出ACK信號(hào)。MPU6050

MPU-6000(6050)為全球首例整合性6軸運(yùn)動(dòng)處理組件,相較于多組件方案,免除了組合陀螺儀與加速器時(shí)間軸之差的問(wèn)題,減少了大量的封裝空間。當(dāng)連接到三軸磁強(qiáng)計(jì)時(shí),MPU-60X0提供完整的9軸運(yùn)動(dòng)融合輸出到其主I2C或SPI端口(SPI僅在MPU-6000上可用)。

MPU-6000(6050)的角速度全格感測(cè)范圍為±250、±500、±1000與±2000°/sec (dps),可準(zhǔn)確追蹤快速與慢速動(dòng)作,并且,用戶(hù)可程式控制的加速器全格感測(cè)范圍為±2g、±4g±8g與±16g。

產(chǎn)品傳輸可透過(guò)最高至400kHz的IIC或最高達(dá)20MHz的SPI(MPU-6050沒(méi)有SPI)。

電路圖

【MPU6050硬件電路圖】(實(shí)際板子電路圖不一定和下面一樣,具體問(wèn)題具體分析,本例參考exynos-fs4412開(kāi)發(fā)板)

1 AD0接地的 值為 0

所以從設(shè)備地址為0x68;

2 SCL、SDA連接的i2c_SCL5、i2c_SDA5

由此可得這兩個(gè)信號(hào)線(xiàn)復(fù)用了GPIO的GPB的2、3引腳;

3 查閱exynos4412 datasheet 6.2.2 Part 1可得

所以設(shè)置GPIO 的 GPB 【15:8】= 0x33 即可。

MPU6050內(nèi)部寄存器

mpu6050內(nèi)部寄存器的使用,參考datasheet《MPU-6000 and MPU-6050Register Map and Descriptions Revision 4.0 》。

Mpu6050內(nèi)部有100多個(gè)寄存器。比如:

這個(gè)寄存器是用來(lái)設(shè)置加速度屬性的,當(dāng)bit[4:3] 設(shè)置為0,表示3個(gè)軸的加速度量程最大為±2g。

mpu6050的內(nèi)部寄存器非常多,并不需要每一個(gè)寄存器都需要搞懂,在如下代碼實(shí)例中,我已經(jīng)列舉出常用的寄存器以及他們的典型值,其他的寄存器不再一一介紹。

下面是個(gè)IIC總線(xiàn)實(shí)例:

用IIC總線(xiàn)實(shí)現(xiàn)CPU與MPU-6050的數(shù)據(jù)查詢(xún)

具體代碼如下:

/***************************************

// MPU6050常用內(nèi)部地址,以下地址在mpu6050內(nèi)部

/***************************************

#define SMPLRT_DIV 0x19 //陀螺儀采樣率,典型值:0x07(125Hz)

#define CONFIG 0x1A //低通濾波頻率,典型值:0x06(5Hz)

#define GYRO_CONFIG 0x1B //陀螺儀自檢及測(cè)量范圍,典型值:0x18(不自檢,2000deg/s)

#define ACCEL_CONFIG 0x1C //加速計(jì)自檢、測(cè)量范圍及高通濾波頻率,典型值:0x01(不自檢,2G,5Hz)

#define ACCEL_XOUT_H 0x3B

#define ACCEL_XOUT_L 0x3C

#define ACCEL_YOUT_H 0x3D

#define ACCEL_YOUT_L 0x3E

#define ACCEL_ZOUT_H 0x3F

#define ACCEL_ZOUT_L 0x40

#define TEMP_OUT_H 0x41

#define TEMP_OUT_L 0x42

#define GYRO_XOUT_H 0x43

#define GYRO_XOUT_L 0x44

#define GYRO_YOUT_H 0x45

#define GYRO_YOUT_L 0x46

#define GYRO_ZOUT_H 0x47

#define GYRO_ZOUT_L 0x48

#define PWR_M(jìn)GMT_1 0x6B //電源管理,典型值:0x00(正常啟用)

#define WHO_AM_I 0x75 //IIC地址寄存器(默認(rèn)數(shù)值0x68,只讀)

#define SlaveAddress 0xD0 //IIC寫(xiě)入時(shí)的地址字節(jié)數(shù)據(jù),+1為讀取

typedef struct {

unsigned int CON;

unsigned int DAT;

unsigned int PUD;

unsigned int DRV;

unsigned int CONPDN;

unsigned int PUDPDN;

}gpb;

#define GPB (* (volatile gpb *)0x11400040)

typedef struct {

unsigned int I2CCON;

unsigned int I2CSTAT;

unsigned int I2CADD;

unsigned int I2CDS;

unsigned int I2CLC;

}i2c5;

#define I2C5 (* (volatile i2c5 *)0x138B0000 )

void mydelay_ms(int time)

int i, j;

while(time--)

for (i = 0; i < 5; i++)

for (j = 0; j < 514; j++);

*********************************************************************

* @brief iic read a byte program body

* @param[in] slave_addr, addr, &data

* @return None

*********************************************************************

void iic_read(unsigned char slave_addr, unsigned char addr, unsigned char *data)

根據(jù)mpu6050的datasheet,要讀取數(shù)據(jù)必須先執(zhí)行寫(xiě)操作:寫(xiě)入一個(gè)從設(shè)備地址,

然后執(zhí)行讀操作,才能讀取到該內(nèi)部寄存器的內(nèi)容

I2C5.I2CDS = slave_addr; //將從機(jī)地址寫(xiě)入I2CDS寄存器中

I2C5.I2CCON = (1 << 7)|(1 << 6)|(1 << 5); //設(shè)置時(shí)鐘并使能中斷

I2C5.I2CSTAT = 0xf0; //[7:6]設(shè)置為0b11,主機(jī)發(fā)送模式;

//往[5:4]位寫(xiě)0b11,即產(chǎn)生啟動(dòng)信號(hào),發(fā)出IICDS寄存器中的地址

while(?。↖2C5.I2CCON & (1 << 4))); // 等待傳輸結(jié)束,傳輸結(jié)束后,I2CCON [4]位為1,標(biāo)識(shí)有中斷發(fā)生;

// 此位為1時(shí),SCL線(xiàn)被拉低,此時(shí)I2C傳輸停止;

I2C5.I2CDS = addr; //寫(xiě)命令值

I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4));// I2CCON [4]位清0,繼續(xù)傳輸

while(?。↖2C5.I2CCON & (1 << 4)));// 等待傳輸結(jié)束

I2C5.I2CSTAT = 0xD0; // I2CSTAT[5:4]位寫(xiě)0b01,發(fā)出停止信號(hào)

I2C5.I2CDS = slave_addr | 1; //表示要讀出數(shù)據(jù)

I2C5.I2CCON = (1 << 7)|(1 << 6) |(1 << 5) ; //設(shè)置時(shí)鐘并使能中斷

I2C5.I2CSTAT = 0xb0;//[7:6]位0b10,主機(jī)接收模式;

//往[5:4]位寫(xiě)0b11,即產(chǎn)生啟動(dòng)信號(hào),發(fā)出IICDS寄存器中的地址

// I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4)); 如果強(qiáng)行關(guān)閉,將讀取不到數(shù)據(jù)

while(?。↖2C5.I2CCON & (1 << 4)));//等待傳輸結(jié)束,接收數(shù)據(jù)

I2C5.I2CCON &= ~((1<<7)|(1 << 4)); Resume the operation & no ack

// I2CCON [4]位清0,繼續(xù)傳輸,接收數(shù)據(jù),

// 主機(jī)接收器接收到最后一字節(jié)數(shù)據(jù)后,不發(fā)出應(yīng)答信號(hào) no ack

// 從機(jī)發(fā)送器釋放SDA線(xiàn),以允許主機(jī)發(fā)出P信號(hào),停止傳輸;

while(?。↖2C5.I2CCON & (1 << 4)));// 等待傳輸結(jié)束

I2C5.I2CSTAT = 0x90;

*data = I2C5.I2CDS;

I2C5.I2CCON &= ~(1<<4); clean interrupt pending bit

mydelay_ms(10);

*data = I2C5.I2CDS;

*************************************************************

* @brief iic write a byte program body

* @param[in] slave_addr, addr, data

* @return None

************************************************************

void iic_write (unsigned char slave_addr, unsigned char addr, unsigned char data)

I2C5.I2CDS = slave_addr;

I2C5.I2CCON = (1 << 7)|(1 << 6)|(1 << 5) ;

I2C5.I2CSTAT = 0xf0;

while(?。↖2C5.I2CCON & (1 << 4)));

I2C5.I2CDS = addr;

I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4));

while(?。↖2C5.I2CCON & (1 << 4)));

I2C5.I2CDS = data;

I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4));

while(?。↖2C5.I2CCON & (1 << 4)));

I2C5.I2CSTAT = 0xd0;

I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4));

mydelay_ms(10);

void MPU6050_Init ()

iic_write(SlaveAddress, PWR_M(jìn)GMT_1, 0x00);

iic_write(SlaveAddress, SMPLRT_DIV, 0x07);

iic_write(SlaveAddress, CONFIG, 0x06);

iic_write(SlaveAddress, GYRO_CONFIG, 0x18);

iic_write(SlaveAddress, ACCEL_CONFIG, 0x01);

讀取mpu6050某個(gè)內(nèi)部寄存器的內(nèi)容

int get_data(unsigned char addr)

char data_h(yuǎn), data_l;

iic_read(SlaveAddress, addr, &data_h(yuǎn));

iic_read(SlaveAddress, addr+1, &data_l);

return (data_h(yuǎn)<<8)|data_l;

* 裸機(jī)代碼,不同于LINUX 應(yīng)用層, 一定加循環(huán)控制

int main(void)

int data;

unsigned char zvalue;

GPB.CON = (GPB.CON & ~(0xff<<8)) | 0x33<<8; // GPBCON[3], I2C_5_SCL GPBCON[2], I2C_5_SDAmydelay_ms(100);

uart_init();

---------------------------------------------------------------

I2C5.I2CSTAT = 0xD0;

I2C5.I2CCON &= ~(1<<4); clean interrupt pending bit

--------------------------------------------------------------

mydelay_ms(100);

MPU6050_Init();

mydelay_ms(100);

printf("********** I2C test!! ***********");

while(1)

data = get_data(GYRO_ZOUT_H);

printf(" GYRO --> Z <---:Hex: %x", data);

data = get_data(GYRO_XOUT_H);

printf(" GYRO --> X <---:Hex: %x", data);

printf("");

mydelay_ms(1000);

return 0;

實(shí)驗(yàn)結(jié)果如下:

********** I2C test?。?***********

GYRO --> Z <---:Hex: 1c GYRO --> X <---:Hex: feda

GYRO --> Z <---:Hex: fefc GYRO --> X <---:Hex: fed6

GYRO --> Z <---:Hex: fefe GYRO --> X <---:Hex: fed6

GYRO --> Z <---:Hex: fefe GYRO --> X <---:Hex: fedc

GYRO --> Z <---:Hex: fefe GYRO --> X <---:Hex: feda

GYRO --> Z <---:Hex: fefc GYRO --> X <---:Hex: fed6

GYRO --> Z <---:Hex: fefe GYRO --> X <---:Hex: feda

GYRO --> Z <---:Hex: fcf2 GYRO --> X <---:Hex: 202

GYRO --> Z <---:Hex: ec GYRO --> X <---:Hex: faa0

GYRO --> Z <---:Hex: 4c GYRO --> X <---:Hex: e

GYRO --> Z <---:Hex: fe GYRO --> X <---:Hex: fed8

GYRO --> Z <---:Hex: 0 GYRO --> X <---:Hex: fede

GYRO --> Z <---:Hex: 0 GYRO --> X <---:Hex: feda

讀寫(xiě)操作代碼解析:

寫(xiě)入一個(gè)數(shù)據(jù)流程:

讀數(shù)據(jù)流程:

上圖閱讀注意點(diǎn):

從設(shè)備地址是在用的時(shí)候應(yīng)該左移一位|讀寫(xiě)位,比如寫(xiě)reg=0x68<1|0,即0xD0;主設(shè)備發(fā)出S信號(hào),需要將I2CSTATn 的bite:5設(shè)置為1;主設(shè)備發(fā)出p信號(hào),需要將I2CSTATn 的bite:5設(shè)置為0;主機(jī)發(fā)送數(shù)據(jù)需要將寄存器I2CCONn的bit:4置0,to reume the operation;主機(jī)等待從設(shè)備發(fā)送的ack或者data,需要輪訓(xùn)判斷I2CCONn的bit:4是否置1;代碼的理解除了結(jié)合功能流程圖、時(shí)序圖、源代碼還要結(jié)合寄存器說(shuō)明;代碼的編寫(xiě)順序必須嚴(yán)格按照時(shí)序和模塊流程圖執(zhí)行;時(shí)序中的每一個(gè)數(shù)據(jù)信號(hào)(包括ack、data、reg)的產(chǎn)生或者發(fā)送對(duì)應(yīng)的代碼都用箭頭以及相同的顏色框處;對(duì)1于read操作,NACK的回復(fù)需要在接收最后一個(gè)data之前設(shè)置I2CCONn :7位為0,這樣在收到從設(shè)備的data后,才會(huì)將SDA拉低。

責(zé)任編輯:gt

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 控制器
    +關(guān)注

    關(guān)注

    112

    文章

    16444

    瀏覽量

    179188
  • 微處理器
    +關(guān)注

    關(guān)注

    11

    文章

    2274

    瀏覽量

    82706
  • 總線(xiàn)
    +關(guān)注

    關(guān)注

    10

    文章

    2900

    瀏覽量

    88315
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    I2C總線(xiàn)的優(yōu)缺點(diǎn)分析

    設(shè)備之間的通信,這大大減少了所需的引腳數(shù)量,降低了硬件成本。此外,由于其簡(jiǎn)單性,I2C總線(xiàn)也易于實(shí)現(xiàn)和維護(hù)。 2. 多主機(jī)和多機(jī)支持
    的頭像 發(fā)表于 01-17 15:50 ?150次閱讀

    I2C總線(xiàn)與Arduino的接口示例

    在現(xiàn)代電子設(shè)計(jì)中,I2C總線(xiàn)因其簡(jiǎn)單性和靈活性而廣受歡迎。它允許多個(gè)設(shè)備共享同一通信線(xiàn)路,從而節(jié)省空間和成本。Arduino,作為一個(gè)多功能的微控制器平臺(tái),自然也支持I2C通信。
    的頭像 發(fā)表于 01-17 15:34 ?186次閱讀

    I2C總線(xiàn)的工作模式介紹

    兩根線(xiàn)組成:數(shù)據(jù)線(xiàn)(SDA)和時(shí)鐘線(xiàn)(SCL)。數(shù)據(jù)線(xiàn)負(fù)責(zé)傳輸數(shù)據(jù),而時(shí)鐘線(xiàn)則用于同步數(shù)據(jù)傳輸。I2C總線(xiàn)是全雙工的,意味著數(shù)據(jù)可以在兩個(gè)方向上傳輸。它支持多個(gè)主設(shè)備設(shè)備,但在同一
    的頭像 發(fā)表于 01-17 15:32 ?145次閱讀

    I2C總線(xiàn)協(xié)議詳細(xì)解析

    1. I2C總線(xiàn)簡(jiǎn)介 I2C總線(xiàn)由Philips Semiconductor(現(xiàn)為NXP Semiconductors)在1980年代初期開(kāi)發(fā)。它是一種多主機(jī)總線(xiàn),允許多個(gè)設(shè)備共享同一總線(xiàn)。I
    的頭像 發(fā)表于 01-17 15:22 ?188次閱讀

    I2C總線(xiàn)與單片機(jī)的連接

    在現(xiàn)代電子系統(tǒng)中,單片機(jī)(MCU)是核心控制單元,而I2C總線(xiàn)作為一種多主機(jī)、多機(jī)的串行通信協(xié)議,因其簡(jiǎn)單、高效和節(jié)省引腳的特性而被廣泛應(yīng)用于各種電子設(shè)備中。
    的頭像 發(fā)表于 01-17 15:18 ?161次閱讀

    I2C總線(xiàn)設(shè)備地址設(shè)置方法

    I2C總線(xiàn)是一種廣泛使用的串行通信協(xié)議,它允許多個(gè)設(shè)備在兩條線(xiàn)上(數(shù)據(jù)線(xiàn)SDA和時(shí)鐘線(xiàn)SCL)進(jìn)行通信。每個(gè)設(shè)備都有一個(gè)唯一的地址,以確保數(shù)據(jù)能夠正確地發(fā)送到目標(biāo)設(shè)備。
    的頭像 發(fā)表于 01-17 15:17 ?245次閱讀

    I2C總線(xiàn)應(yīng)用實(shí)例分析

    在現(xiàn)代電子系統(tǒng)中,I2C總線(xiàn)因其簡(jiǎn)單、靈活和高效的特點(diǎn)而被廣泛應(yīng)用于各種設(shè)備之間的通信。 I2C總線(xiàn)概述 I2C總線(xiàn)由Philips(現(xiàn)為NXP)在1980年代初期開(kāi)發(fā),最初用于音頻和
    的頭像 發(fā)表于 01-17 15:09 ?175次閱讀

    I2C總線(xiàn)與SPI總線(xiàn)的比較

    于低速通信。它只需要兩根線(xiàn):數(shù)據(jù)線(xiàn)(SDA)和時(shí)鐘線(xiàn)(SCL),這使得I2C非常適合于節(jié)省引腳的應(yīng)用。 特點(diǎn) 多主機(jī)支持 :多個(gè)微控制器可以共享同一I2C總線(xiàn)。 多機(jī)支持 :多個(gè)
    的頭像 發(fā)表于 01-17 15:08 ?168次閱讀

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-i2c設(shè)備通訊編程示例之i2c設(shè)備通信編程

    i2c_rdwr_ioctl_data類(lèi)型的結(jié)構(gòu)體變量work_queue,并為work_queue.msgs分配了動(dòng)態(tài)內(nèi)存。然后,先發(fā)送一個(gè)寫(xiě)操作的消息,設(shè)置要讀取的寄存器地址,然后再發(fā)送一個(gè)讀操作的消息,
    發(fā)表于 11-02 17:01

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-i2c設(shè)備通訊編程示例之i2c編寫(xiě)程序

    的光線(xiàn)傳感器就作為設(shè)備。前面我們了解了i2c的通訊協(xié)議,也初步用i2c-tools嘗試著讀寫(xiě)了一個(gè)設(shè)
    發(fā)表于 11-01 11:31

    飛凌嵌入式ElfBoard ELF 1板卡-i2c設(shè)備通訊編程示例之i2c設(shè)備通信編程

    函數(shù)執(zhí)行i2c寫(xiě)操作。最后,釋放動(dòng)態(tài)分配的內(nèi)存,并返回執(zhí)行結(jié)果。 ()第部分定義了函數(shù)func_read_regs,用于設(shè)備
    發(fā)表于 11-01 11:28

    飛凌嵌入式ElfBoard ELF 1板卡-i2c設(shè)備通訊編程示例之i2c編寫(xiě)程序

    include/linux/i2c-dev.h中針對(duì)每個(gè)i2c總線(xiàn)生成一個(gè)設(shè)備節(jié)點(diǎn),實(shí)現(xiàn)了文件操作接口,用戶(hù)空間可以通過(guò)i2c
    發(fā)表于 10-31 12:00

    嵌入式學(xué)習(xí)-飛凌嵌入式ElfBoard ELF 1板卡-i2c設(shè)備通訊編程示例之i2c硬件原理

    (Serial Data);(i2c為總線(xiàn)型結(jié)構(gòu),主設(shè)備依靠設(shè)備地址進(jìn)行尋址;(四)設(shè)備
    發(fā)表于 10-29 16:29

    飛凌嵌入式ElfBoard ELF 1板卡-i2c設(shè)備通訊編程示例之i2c硬件原理

    (Serial Data);(i2c為總線(xiàn)型結(jié)構(gòu),主設(shè)備依靠設(shè)備地址進(jìn)行尋址;(四)設(shè)備
    發(fā)表于 10-28 08:58

    什么是I2C協(xié)議 I2C總線(xiàn)的控制邏輯

    在實(shí)際使用過(guò)程中,I2C比較容易出現(xiàn)的一個(gè)問(wèn)題就是死鎖 ,死鎖在I2C中主要表現(xiàn)為:I2C死鎖時(shí)表現(xiàn)為SCL為高,SDA一直為低。
    發(fā)表于 03-12 09:17 ?1159次閱讀
    什么是<b class='flag-5'>I2C</b>協(xié)議 <b class='flag-5'>I2C</b>總線(xiàn)的<b class='flag-5'>控制</b>邏輯