色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

I2C內核架構分析

FPGA之家 ? 來源:FPGA之家 ? 作者:FPGA之家 ? 2022-10-17 17:32 ? 次閱讀

前言

I2C(Inter-Integrated Circuit)總線(也稱 IIC 或 I2C) 是有PHILIPS公司開發的兩線式串行總線,用于連接微控制器及外圍設備,是微電子通信控制領域廣泛采用的一種總線標準。它是同步通信的一種特殊形式,具有接口線少、控制方式簡單、器件封裝形式小、通信速率較高等優點。

398c9aa2-437f-11ed-96c9-dac502259ad0.png

Exynos4412 i2c控制器綜述

Exynos4412精簡指令集微處理器支持4個IIC總線控制器。為了能使連接在總線上的主和從設備之間傳輸數據,專用的數據線SDA和時鐘信號線SCL被使用,他們都是雙向的。

如果工作在多主機的IIC總線模式,多個4412處理器將從從機那接收數據或發送數據給從機。在IIC總線上的主機端4412會啟動或終止一個數據傳輸。4412的IIC總線控制器會用一個標準的IIC總線仲裁機制去實現多主機和多從機傳輸數據。

通過控制如下寄存器以實現IIC總線上的多主機操作:

控制寄存器: I2CCON

狀態寄存器: I2CSTAT

Tx/Rx數據偏移寄存器: I2CDS

地址寄存器: I2CADD

如果I2C總線空閑,那么SCL和SDA信號線將都為高電平。在SCL為高電平期間,如果SDA有由高到低電平的跳變,那么將啟動一個起始信號,如果SDA有由低到高電平的跳變,將啟動一個結束信號。

主機端的設備總是提供起始和停止信號的一端。在起始信號被發出后,一個數據字節的前7位被當作地址通過SDA線被傳輸。這個地制值決定了總線上的主設備將要選擇那個從設備作為傳輸對象,bit8決定傳輸數據的方向(是讀還是寫)。

I2C總線上的數據(即在SDA上傳輸的數據)都是以8位字節傳輸的,在總線上傳輸操作的過程中,對發送或接收的數據字節數是沒有限制的。I2C總線上的主/從設備發送數據總是以一個數據的最高位開始傳輸(即MSB方式),傳輸完一個字節后,應答信號緊接其后。

Exynos4412 I2C總線接口特性

共有9個通道,支持多主、從I2C總線接口。其中8個通道作為普通接口(即I2C0、I2C1....),1個通道作為HDMI的專用接口。

7位地址模式。

串行,8位單向或雙向的數據傳輸。

在標準模式中,每秒最多可以傳輸100k位,即12.5kB的數據量。

在快速模式中,每秒最多可以傳輸400k位,即50kB的數據量。

支持主機端發送、接收,從機端發送、接收操作。

支持中斷和查詢方式。

框圖

39a453c2-437f-11ed-96c9-dac502259ad0.png

從上圖可以看出,4412提供4個寄存器來完成所有的IIC操作。SDA線上的數據從IICDS寄存器經過移位寄存器發出,或通過移位寄存器傳入IICDS寄器;IICADD寄存器中保存4412當做從機時的地址;IICCON、IICSTAT兩個寄存器用來控制或標識各種狀態,比如選擇工作工作模式,發出S信號、P信號,決定是否發出ACK信號,檢測是否接收到ACK信號。

I2C總線接口操作

針對4412處理器的I2C總線接口,具備4種操作模式:

主機發送模式

主機接收模式

從機發送模式

從機接收模式

下面將描述這些操作模式之間的功能關系:

0、數據有效性

39f15a82-437f-11ed-96c9-dac502259ad0.png

SDA線上的數據必須在時鐘的高電平周期保持穩定。數據線的高或低電平狀態IIC位傳輸數據的有效性在SCL線的時鐘信號是低電平才能改變。

1.開始和停止條件

當4412的I2C接口空閑時,它往往工作在從機模式。或者說,4412的的i2c接口在SDA線上察覺到一個起始信號之前它應該工作在從機模式。當控制器改變4412的i2c接口的工作模式為主機模式后,SDA線上發起數據傳輸并且控制器會產生SCL時鐘信號。

開始條件通過SDA線進行串行的字節傳輸,一個停止信號終止數據傳輸,停止信號是指SCL在高電平器件SDA線有從低到高電平的跳變,主機端產生起始和停止條件。當主、從設備產生一個起始信號后,I2C總線將進入忙狀態。這里需要說明的是上述主從設備都有可能作為主機端。

當一個主機發送了一個起始信號后,它也應該發送一個從機地址以通知總線上的從設備。這個地址字節的低7位表示從設備地址,最高位表示傳輸數據的方向,即主機將要進行讀還是寫。當最高位是0時,它將發起一個寫操作(發送操作);當最高位是1時,它將發起一個讀數據的請求(接收操作)。

主機端發起一個結束信號以完成傳輸操作,如果主機端想在總線上繼續進行數據的傳輸,它將發出另外一個起始信號和從設備地址。用這樣的方式,它們可以用各種各樣的格式進行讀寫操作。

下圖為起始和停止信號:

3a061be8-437f-11ed-96c9-dac502259ad0.png

2. 數據傳輸格式

放到SDA線上的所有字節數據的長度應該為8位,在每次傳輸數據時,對傳輸數據量沒有限制。在起始信號后的第一個數據字節應該包含地址字段,當4412的I2C接口被設置為主模式時,地址字節應該由控制器端發出。在每個字節后,應該有一個應答位。

如果從機要完成一些其他功能后(例如一個內部中斷服務程序)才能繼續接收或發送下一個字節,從機可以拉低SCL迫使主機進入等待狀態。當從機準備好接收下一個數據并釋放SCL后,數據傳輸繼續。如果主機在傳輸數據期間也需要完成一些其他功能(例如一個內部中斷服務程序)也可以拉低SCL以占住總線。

下面的圖中將說明數據傳輸格式:

3a1eeef2-437f-11ed-96c9-dac502259ad0.png

3a31236a-437f-11ed-96c9-dac502259ad0.png

上圖中說明,在傳輸完每個字節數據后,都會有一個應答信號,這個應答信號在第9個時鐘周期。具體過程如下(注意下面描述的讀寫過程都是針對 4412處理器而言,當有具體的I2C設備與4412相連時,數據表示什么需要看具體的I2C設備,4412是不知道數據的含義的):

寫過程:主機發送一個起始信號S→發送從機7位地址和1位方向,方向位表示寫→主機釋放SDA線方便從機給回應→有從機匹配到地址,拉低SDA線作為ACK→主機重新獲得SDA傳輸8位數據→主機釋放SDA線方便從機給回應→從機收到數據拉低SDA線作為ACK告訴主機數據接收成功→主機發出停止信號。

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

注意:在具體的I2C通信時,要看I2C設備才能確定讀寫時序,比如下面即將描述的第七大點中的示例,讀寫EEPROM中就會說道具體的數據含義,讀寫過程。

3.應答信號的傳輸

為了完成一個字節數據的傳輸,接收方將發送一個應答位給發送方。應答信號出現在SCL線上的時鐘周期中的第九個時鐘周期,為了發送或接收1個字節的數據,主機端會產生8個時鐘周期,為了傳輸一個ACK位,主機端需要產生一個時鐘脈沖。

ACK時鐘脈沖到來之際,發送方會在SDA線上設置高電平以釋放SDA線。在ACK時鐘脈沖之間,接收方會驅動和保持SDA線為低電平,這發生在第9個時鐘脈沖為高電平期間。應答信號為低電平時,規定為有效應答位(ACK簡稱應答位),表示接收器已經成功地接收了該字節;應答信號為高電平時,規定為非應答位(NACK),一般表示接收器接收該字節沒有成功。對于反饋有效應答位ACK的要求是,接收器在第9個時鐘脈沖之前的低電平期間將SDA線拉低,并且確保在該時鐘的高電平期間為穩定的低電平。如果接收器是主控器,則在它收到最后一個字節后,發送一個NACK信號(即不發出ACK信號),以通知被控發送器結束數據發送,并釋放SDA線,以便主控接收器發送一個停止信號P。

3a424aa0-437f-11ed-96c9-dac502259ad0.png

4.讀寫操作

當I2C控制器在發送模式下發送數據后,I2C總線接口將等待直到移位寄存器(I2CDS)接收到一個數據。在往此寄存器寫入一個新數據前,SCL線應該保持為低電平,寫完數據后,I2C控制器將釋放SCL線。當前正在傳輸的數據傳輸完成后,4412會捕捉到一個中斷,然后cpu將開始往I2CDS寄存器中寫入一個新的數據。

當I2C控制器在接收模式下接收到數據后,I2C總線接口將等待直到I2CDS寄存器被讀。在讀到新數據之前,SCL線會被保持為低電平,讀到數據后I2C控制器將釋放掉SCL線。一個新數據接收完成后,4412將收到一個中斷,cpu收到這個中斷請求后,它將從I2CDS寄存器中讀取數據。

5.總線仲裁機制

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

6.終止條件

當一個從接收者不能識別從地址時,它將保持SDA線為高電平。在這樣的情況下,主機會產生一個停止信號并且取消數據的傳輸。當終止傳輸產生后,主機端接收器會通過取消ACK的產生以告訴從機端發送器結束發送操作。這將在主機端接收器接收到從機端發送器發送的最后一個字節之后發生,為了讓主機端產生一個停止條件,從機端發送者將釋放SDA線。

7.配置I2C總線

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

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

在I2C總線上執行任何的收發Tx/Rx操作前,應該做如下配置:

(1)在I2CADD寄存器中寫入從設備地址

(2)設置I2CCON控制寄存器

a.使能中斷

b.定義SCL頻率

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

下圖為主設備發送模式

3a9f4da4-437f-11ed-96c9-dac502259ad0.png

下圖為主設備接收模式

3add8a74-437f-11ed-96c9-dac502259ad0.png

下圖為從設備發送模式

3b0ba1f2-437f-11ed-96c9-dac502259ad0.png

下圖為從設備接收

模式

3b22a78a-437f-11ed-96c9-dac502259ad0.png

I2C控制器寄存器

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

3b449ba6-437f-11ed-96c9-dac502259ad0.png

1-- I2C總線控制寄存器

IICCON寄存器用于控制是否發出ACK信號、設置發送器的時鐘、開啟I2C中斷,并標識中斷是否發生

3bc41214-437f-11ed-96c9-dac502259ad0.png

使用IICCON寄存器時,有如下注意事項

發送模式的時鐘頻率由位[6]、位[3:0]聯合決定。另外,當 IICCON[6]=0時,IICCON[3:0]不能取0或1。

位[4]用來標識是否有I2C中斷發生,讀出為0時標識沒有中斷發生,讀出為1時標識有中斷發生。當此位為1時,SCL線被拉低,此時所以I2C傳輸停止;如果要繼續傳輸,需寫入0清除它。

中斷在以下3種情況下發生:

1 -- 當發送地址信息或接收到一個從機地址并且吻合時;

2 -- 當總線仲裁失敗時;

3 -- 當發送/接收完一個字節的數據(包括響應位)時;

基于SDA、SCL線上時間特性的考慮,要發送數據時,先將數據寫入IICDS寄存器,然后再清除中斷。

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

2 -- I2C狀態寄存器

IICSTAT寄存器用于選擇I2C接口的工作模式,發出S信號、P信號,使能接收/發送功能,并標識各種狀態,比如總線仲裁是否成功、作為從機時是否被尋址、是否接收到0地址、是否接收到ACK信號等。

3bf79a44-437f-11ed-96c9-dac502259ad0.png

3 -- I2C數據發送/接收移位寄存器

3c174c0e-437f-11ed-96c9-dac502259ad0.png

fs4412的i2c總線上掛載了mpu6050

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

3c7b6900-437f-11ed-96c9-dac502259ad0.png

3c9a7aac-437f-11ed-96c9-dac502259ad0.png

【注意】上述兩個時序非常重要,下面我們編寫基于linux的驅動編寫i2c_msg還要再依賴他。

上述簡化時序的術語解釋如下

3cad6144-437f-11ed-96c9-dac502259ad0.png

【寄存器使用規則】

下面先提前講一下具體應用中如何啟動和恢復IIC的傳輸

啟動或恢復4412的I2C傳輸有以下兩種方法。

1)當IICCON[4]即中斷狀態位為0時,通過寫IICSTAT寄存器啟動I2C操作。有以下兩種情況。

1--在主機模式,

令IICSTAT[5:4]等于0b11,將發出S信號和IICDS寄存器的數據(尋址),

令IICSTAT[5:4]等于0b01,將發出P信號。

2--在從機模式,令IICSTAT[4]等于1將等待其他主機發出S信號及地址信息。

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

1--對于主機模式,可以按照上面1的方法寫IICSTAT寄存器,恢復I2C操作后即可發出S信號和IICDS寄存器的值(尋址),或發出P信號。

2--對于發送器,可以將下一個要發送的數據寫入IICDS寄存器中,恢復I2C操作后即可發出這個數據。

3--對于接收器,可以從IICDS寄存器讀出接收到的數據。最后向IICCON[4]寫入0的同時,設置IICCON[7]以決定是否在接收到下一個數據后是否發出ACK信號。

MPU6050

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

3ccc9e74-437f-11ed-96c9-dac502259ad0.jpg

MPU-6000(6050)的角速度全格感測范圍為±250、±500、±1000與±2000°/sec (dps),可準確追蹤快速與慢速動作,并且,用戶可程式控制的加速器全格感測范圍為±2g、±4g±8g與±16g。產品傳輸可透過最高至400kHz的IIC或最高達20MHz的SPI(MPU-6050沒有SPI)。

電路圖

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

3ce2fc46-437f-11ed-96c9-dac502259ad0.png

1 AD0接地的 值為 0

3d1176ca-437f-11ed-96c9-dac502259ad0.png

所以從設備地址為0x68;

2 SCL、SDA連接的i2c_SCL5、i2c_SDA5

3d25fa96-437f-11ed-96c9-dac502259ad0.png

由此可得這兩個信號線復用了GPIO的GPB的2、3引腳;

3查閱exynos4412 datasheet 6.2.2 Part 1可得

3d3b288a-437f-11ed-96c9-dac502259ad0.png

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

MPU6050內部寄存器

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

Mpu6050內部有100多個寄存器。比如:

3d64976a-437f-11ed-96c9-dac502259ad0.png

3d878518-437f-11ed-96c9-dac502259ad0.png

這個寄存器是用來設置加速度屬性的,當bit[4:3] 設置為0,表示3個軸的加速度量程最大為±2g。

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

下面是個IIC總線實例:

用IIC總線實現CPU與MPU-6050的數據查詢

具體代碼如下:

//****************************************
//MPU6050常用內部地址,以下地址在mpu6050內部
//****************************************
#defineSMPLRT_DIV0x19//陀螺儀采樣率,典型值:0x07(125Hz)
#defineCONFIG0x1A//低通濾波頻率,典型值:0x06(5Hz)
#defineGYRO_CONFIG0x1B//陀螺儀自檢及測量范圍,典型值:0x18(不自檢,2000deg/s)
#defineACCEL_CONFIG0x1C//加速計自檢、測量范圍及高通濾波頻率,典型值:0x01(不自檢,2G,5Hz)
#defineACCEL_XOUT_H0x3B
#defineACCEL_XOUT_L0x3C
#defineACCEL_YOUT_H0x3D
#defineACCEL_YOUT_L0x3E
#defineACCEL_ZOUT_H0x3F
#defineACCEL_ZOUT_L0x40
#defineTEMP_OUT_H0x41
#defineTEMP_OUT_L0x42
#defineGYRO_XOUT_H0x43
#defineGYRO_XOUT_L0x44
#defineGYRO_YOUT_H0x45
#defineGYRO_YOUT_L0x46
#defineGYRO_ZOUT_H0x47
#defineGYRO_ZOUT_L0x48
#definePWR_MGMT_10x6B//電源管理,典型值:0x00(正常啟用)
#defineWHO_AM_I0x75//IIC地址寄存器(默認數值0x68,只讀)
#defineSlaveAddress0xD0//IIC寫入時的地址字節數據,+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 )


voidmydelay_ms(inttime)
{
  inti,j;
  while(time--)
  {
    for(i=0;i5;i++)
      for(j=0;j514;j++);
  }
}
/**********************************************************************
*@briefiicreadabyteprogrambody
*@param[in]slave_addr,addr,&data
*@returnNone
**********************************************************************/


void iic_read(unsigned char slave_addr, unsigned char addr, unsigned char *data)
{
  /*根據mpu6050的datasheet,要讀取數據必須先執行寫操作:寫入一個從設備地址,
  然后執行讀操作,才能讀取到該內部寄存器的內容*/
  I2C5.I2CDS=slave_addr;//將從機地址寫入I2CDS寄存器中
  I2C5.I2CCON=(1<7)|(1<6)|(1<5);//設置時鐘并使能中斷
  I2C5.I2CSTAT=0xf0;//[7:6]設置為0b11,主機發送模式;
  //往[5:4]位寫0b11,即產生啟動信號,發出IICDS寄存器中的地址
  
  while(!(I2C5.I2CCON&(1<4)));//等待傳輸結束,傳輸結束后,I2CCON [4]位為1,標識有中斷發生;
  
  // 此位為1時,SCL線被拉低,此時I2C傳輸停止;
  I2C5.I2CDS=addr;//寫命令值
  I2C5.I2CCON=I2C5.I2CCON&(~(1<4));//I2CCON[4]位清0,繼續傳輸
  while(!(I2C5.I2CCON&(1<4)));//等待傳輸結束
  
  I2C5.I2CSTAT = 0xD0; // I2CSTAT[5:4]位寫0b01,發出停止信號
  I2C5.I2CDS=slave_addr|1;//表示要讀出數據
  
  I2C5.I2CCON=(1<7)|(1<6)|(1<5);//設置時鐘并使能中斷
  I2C5.I2CSTAT = 0xb0;//[7:6]位0b10,主機接收模式;
  
  //往[5:4]位寫0b11,即產生啟動信號,發出IICDS寄存器中的地址
  //I2C5.I2CCON=I2C5.I2CCON&(~(1<
  
  while(!(I2C5.I2CCON & (1 << 4)));//等待傳輸結束,接收數據
  
  I2C5.I2CCON&=~((1<<7)|(1<4));/*Resumetheoperation&noack*/
  //I2CCON[4]位清0,繼續傳輸,接收數據,
   // 主機接收器接收到最后一字節數據后,不發出應答信號 no ack   
  
  // 從機發送器釋放SDA線,以允許主機發出P信號,停止傳輸;
  while(!(I2C5.I2CCON&(1<4)));//等待傳輸結束
  
  I2C5.I2CSTAT=0x90;
  *data=I2C5.I2CDS;
  I2C5.I2CCON&=~(1<<4);/*cleaninterruptpendingbit*/
  mydelay_ms(10);
  *data=I2C5.I2CDS;
}
/**************************************************************
 *@briefiicwriteabyteprogrambody
*@param[in]slave_addr,addr,data
*@returnNone
*************************************************************/


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(!(I2C5.I2CCON & (1 << 4)));
  I2C5.I2CDS=addr;
  I2C5.I2CCON=I2C5.I2CCON&(~(1<4));
  while(!(I2C5.I2CCON&(1<4)));
  
  I2C5.I2CDS=data;
  I2C5.I2CCON=I2C5.I2CCON&(~(1<4));
  
  while(!(I2C5.I2CCON & (1 << 4)));
  
  I2C5.I2CSTAT=0xd0;
  I2C5.I2CCON=I2C5.I2CCON&(~(1<4));
  mydelay_ms(10);
}
void MPU6050_Init ()
{
  iic_write(SlaveAddress,PWR_MGMT_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某個內部寄存器的內容*/
int get_data(unsigned char addr)
{
  chardata_h,data_l;
  
  iic_read(SlaveAddress,addr,&data_h);
  iic_read(SlaveAddress,addr+1,&data_l);
  return(data_h<<8)|data_l;
}
/*
*裸機代碼,不同于LINUX應用層,一定加循環控制
 */
intmain(void)
{
  intdata;
  unsigned char zvalue;


  GPB.CON=(GPB.CON&~(0xff<<8))|0x33<<8;//GPBCON[3],I2C_5_SCLGPBCON[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("
**********I2Ctest!!***********
");
  while(1)
  {
    data = get_data(GYRO_ZOUT_H);
    
    printf("GYRO-->Z<---?%x",data);
    data=get_data(GYRO_XOUT_H);
    printf(" GYRO --> X <--- %x", data);
    
    printf("
");
    mydelay_ms(1000);
  }
  return0;
}

實驗結果如下:

********** 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  

讀寫操作代碼解析:

寫入一個數據流程:

3dbdce02-437f-11ed-96c9-dac502259ad0.png

讀數據流程:

3df34a32-437f-11ed-96c9-dac502259ad0.png

上圖閱讀注意點:

  1. 從設備地址是在用的時候應該左移一位|讀寫位,比如寫reg=0x68<1|0,即0xD0;

  2. 主設備發出S信號,需要將I2CSTATn 的bite:5設置為1;

  3. 主設備發出p信號,需要將I2CSTATn 的bite:5設置為0;

  4. 主機發送數據需要將寄存器I2CCONn的bit:4置0,to reume the operation;

  5. 主機等待從設備發送的ack或者data,需要輪訓判斷I2CCONn的bit:4是否置1;

  6. 代碼的理解除了結合功能流程圖、時序圖、源代碼還要結合寄存器說明;

  7. 代碼的編寫順序必須嚴格按照時序和模塊流程圖執行;

  8. 時序中的每一個數據信號(包括ack、data、reg)的產生或者發送對應的代碼都用箭頭以及相同的顏色框處;

  9. 對于read操作,NACK的回復需要在接收最后一個data之前設置I2CCONn :7位為0,這樣在收到從設備的data后,才會將SDA拉低。

審核編輯:郭婷


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 微控制器
    +關注

    關注

    48

    文章

    7542

    瀏覽量

    151316
  • 處理器
    +關注

    關注

    68

    文章

    19259

    瀏覽量

    229652
  • 控制器
    +關注

    關注

    112

    文章

    16332

    瀏覽量

    177808

原文標題:I2C內核架構分析

文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    Linux內核中描述I2C的四個核心結構體

    I2C核心維護了i2c_bus結構體,提供了I2C總線驅動和設備驅動的注冊、注銷方法,維護了I2C總線的驅動、設備鏈表,實現了設備、驅動的匹配探測。此部分代碼由Linux
    的頭像 發表于 09-04 09:35 ?1473次閱讀
    Linux<b class='flag-5'>內核</b>中描述<b class='flag-5'>I2C</b>的四個核心結構體

    Linux內核I2C系統的設計思路

    [ 導讀] 本文通過閱讀內核代碼,來梳理一下I2C子系統的整體視圖。在開發I2C設備驅動程序時,往往缺乏對于系統整體的認識,沒有一個清晰的思路。所以從高層級來分析一下
    發表于 09-06 09:40 ?520次閱讀
    Linux<b class='flag-5'>內核</b>中<b class='flag-5'>I2C</b>系統的設計思路

    i2c總線ppt(I2C總線器件應用)

    I2C總線器件應用第一節 I2C總線器件應用概述I2C總線工作原理I2C總線系統結構I2C總線系統結構如圖7-1所示。其中,SCL是時鐘線,
    發表于 08-13 17:34 ?0次下載

    I2C Guid I2C指南

    I2C Guid  I2C指南 The I2C bus is used in a wide rangeof applications because it is simpleand
    發表于 04-23 13:55 ?36次下載

    什么是i2c總線

    什么是i2c總線  下載請點擊: i2c總線協議中文版 
    發表于 11-05 09:26 ?2919次閱讀

    基于CPLD的I2C總線接口設計

    在電路設計中,I2C總線是比較常用的兩線式串行通信方式,大多數的CPU都擅長于并口操作,不具備直接操作I2C總線接口的能力。為了使不具備I2C總線接口能力的CPU通過對并口的簡單操作實現對I2
    發表于 02-12 16:11 ?95次下載
    基于CPLD的<b class='flag-5'>I2C</b>總線接口設計

    i2c

    單片機i2c總線操作;單片機i2c總線操作;單片機i2c總線操作;
    發表于 05-17 11:09 ?35次下載

    介紹關于I2C波形的捕獲與分析

    通過此段視頻,您將了解到如何如何對I2C波形進行捕獲與分析
    的頭像 發表于 06-25 15:05 ?8180次閱讀

    Linux的I2C驅動架構

    1.???? Linux的I2C驅動架構Linux中I2C總線的驅動分為兩個部分,總線驅動(BUS)和設備驅動(DEVICE)。其中總線驅動的職責,是為系統中每個I2C
    發表于 04-02 14:38 ?676次閱讀

    Linux驅動中的I2C驅動架構詳細分析

    其實I2C接口非常的簡單,即使用51單片機的gpio來模擬I2C,編寫一個e2prom或者其他I2C接口的驅動程序,也不是什么難事,幾百行代碼就能搞定。但是Linux 的
    發表于 08-01 17:35 ?3次下載
    Linux驅動中的<b class='flag-5'>I2C</b>驅動<b class='flag-5'>架構</b>詳細<b class='flag-5'>分析</b>

    Linux內核I2C子系統的整體視圖

    本文通過閱讀內核代碼,來梳理一下I2C子系統的整體視圖。在開發I2C設備驅動程序時,往往缺乏對于系統整體的認識,沒有一個清晰的思路。所以從高層級來分析一下
    的頭像 發表于 12-31 10:40 ?2181次閱讀
    Linux<b class='flag-5'>內核</b>中<b class='flag-5'>I2C</b>子系統的整體視圖

    嵌入式內核及驅動開發-09IIC子系統框架使用(I2C協議和時序,I2C驅動框架,I2C從設備驅動開發,MPU6050硬件連接

    從設備adapter i2c 控制器對象數據包對象讀寫數據設備樹中添加MPU6050信息內核選配添加設備樹節點編寫驅動程序 mpu6050_i2c_drv.cI2c協議和時序I2c介紹
    發表于 12-06 14:06 ?17次下載
    嵌入式<b class='flag-5'>內核</b>及驅動開發-09IIC子系統框架使用(<b class='flag-5'>I2C</b>協議和時序,<b class='flag-5'>I2C</b>驅動框架,<b class='flag-5'>I2C</b>從設備驅動開發,MPU6050硬件連接

    硬件I2C與模擬I2C

    硬件I2C對應芯片上的I2C外設,有相應I2C驅動電路,其所使用的I2C管腳也是專用的,因而效率要遠高于軟件模擬的I2C;一般也較為穩定,但
    發表于 12-28 19:14 ?81次下載
    硬件<b class='flag-5'>I2C</b>與模擬<b class='flag-5'>I2C</b>

    I2C控制器驅動介紹

    控制器驅動 I2C 總線驅動重點是 I2C 適配器驅動,這里要用到兩個重要的數據結構:i2c_adapter 和 i2c_algorithm。其中,Linux
    的頭像 發表于 07-22 15:38 ?1480次閱讀
    <b class='flag-5'>I2C</b>控制器驅動介紹

    I2C子系統SW Architecture

    適配器(控制器)驅動,這里用到兩個重要的數據結構:i2c_adapter 和 i2c_algorithm。其中,Linux 內核將 SOC 的 I2C 適配器(控制器)抽象成
    的頭像 發表于 07-22 16:01 ?946次閱讀
    <b class='flag-5'>I2C</b>子系統SW Architecture
    主站蜘蛛池模板: 亚洲国产精麻豆| 甜性涩爱快播| 中文字幕一区二区三区在线观看| 国产私拍福利精品视频| 日韩久久影院| ppypp日本欧美一区二区| 免费A级毛片无码鲁大师| 影音先锋亚洲AV少妇熟女| 好吊日视频在线| 亚洲不卡视频在线观看| 国产精品青青在线麻豆| 色妞色视频一区二区三区四区| xxxx俄罗斯1819| 欧美亚洲国产手机在线有码 | 中文字幕在线观看亚洲| 精品国产影院| 亚洲人精品午夜射精日韩| 国精产品一区一区三区有限在线| 亚欧成人毛片一区二区三区四区| 国产99久久久国产精品免费看| 日本精品久久久久中文字幕| 冰山高冷受被c到哭np双性 | 国产亚洲精品 在线视频 香蕉| 无码免费视频AAAAAA片草莓| 国产国产人免费观看在线视频| 色欲无码国产喷水AV精品| 公主纯肉高H文| 私人玩物黑丝| 国产免费人成在线看视频| 胸大美女又黄的网站| 国产呦精品一区二区三区下载| 亚洲精品不卡视频| 花蝴蝶在线观看免费8| 野花香在线观看免费观看大全动漫| 精品亚洲永久免费精品| 伊在香蕉国产在线视频| 久久中文字幕亚洲| 99久久免费精品国产| 欧美特级特黄a大片免费| 成人AV精品视频| 天天国产在线精品亚洲|