精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

詳解基于Cortex-A9,I2C外設

系統 Linux
本文基于三星Cortex-A9架構,Exynos4412講解I2C原理、以及基于I2C的mpu6050陀螺儀的數據讀取實例(包括在裸機模式下數據的讀取以及基于Linux驅動的讀取)。還會分析Linux內核I2C架構,篇幅過長,絕對干貨。

[[377021]]

 本文基于三星Cortex-A9架構,Exynos4412講解I2C原理、以及基于I2C的mpu6050陀螺儀的數據讀取實例(包括在裸機模式下數據的讀取以及基于Linux驅動的讀取)。還會分析Linux內核I2C架構,篇幅過長,絕對干貨。

裸機篇

本篇首先詳細講解I2C時序,然后講解如何基于三星I2C控制實現裸機讀取從設備信息方法。

前言

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


Exynos4412 i2c控制器綜述

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

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

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

  1. 控制寄存器: I2CCON
  2. 狀態寄存器: I2CSTAT
  3. Tx/Rx數據偏移寄存器:I2CDS
  4. 地址寄存器: I2CADD

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

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

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

Exynos4412 I2C總線接口特性

  1. 共有9個通道,支持多主、從I2C總線接口。其中8個通道作為普通接口(即I2C0、I2C1....),1個通道作為HDMI的專用接口。
  2. 7位地址模式。
  3. 串行,8位單向或雙向的數據傳輸。
  4. 在標準模式中,每秒最多可以傳輸100k位,即12.5kB的數據量。
  5. 在快速模式中,每秒最多可以傳輸400k位,即50kB的數據量。
  6. 支持主機端發送、接收,從機端發送、接收操作。
  7. 支持中斷和查詢方式。

框圖


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

I2C總線接口操作

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

  1. 主機發送模式
  2. 主機接收模式
  3. 從機發送模式
  4. 從機接收模式

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

0、數據有效性


在這里插入圖片描述

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

1. 開始和停止條件

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

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

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

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

下圖為起始和停止信號:


2. 數據傳輸格式

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

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

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



上圖中說明,在傳輸完每個字節數據后,都會有一個應答信號,這個應答信號在第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。


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寄存器以使能串行輸出

下圖為主設備發送模式


下圖為主設備接收模式

下圖為從設備發送模式


下圖為從設備接收模式


I2C控制器寄存器

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


1-- I2C總線控制寄存器

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


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

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

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

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

  • 當發送地址信息或接收到一個從機地址并且吻合時;
  • 當總線仲裁失敗時;
  • 當發送/接收完一個字節的數據(包括響應位)時;

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

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

2 -- I2C狀態寄存器

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


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


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



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

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


【寄存器使用規則

下面先提前講一下具體應用中如何啟動和恢復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上可用)。

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

產品傳輸可透過最高至400kHz的IIC或最高達20MHz的SPI(MPU-6050沒有SPI)。

電路圖

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


1 AD0接地的 值為 0


所以從設備地址為0x68;

2 SCL、SDA連接的i2c_SCL5、i2c_SDA5


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

3 查閱exynos4412 datasheet 6.2.2 Part 1可得


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

MPU6050內部寄存器

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

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



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

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

下面是個IIC總線實例:用IIC總線實現CPU與MPU-6050的數據查詢

具體代碼如下:

  1. //**************************************** 
  2. // MPU6050常用內部地址,以下地址在mpu6050內部 
  3. //**************************************** 
  4. #define SMPLRT_DIV  0x19 //陀螺儀采樣率,典型值:0x07(125Hz) 
  5. #define CONFIG   0x1A //低通濾波頻率,典型值:0x06(5Hz) 
  6. #define GYRO_CONFIG  0x1B //陀螺儀自檢及測量范圍,典型值:0x18(不自檢,2000deg/s) 
  7. #define ACCEL_CONFIG 0x1C //加速計自檢、測量范圍及高通濾波頻率,典型值:0x01(不自檢,2G,5Hz) 
  8. #define ACCEL_XOUT_H 0x3B 
  9. #define ACCEL_XOUT_L 0x3C 
  10. #define ACCEL_YOUT_H 0x3D 
  11. #define ACCEL_YOUT_L 0x3E 
  12. #define ACCEL_ZOUT_H 0x3F 
  13. #define ACCEL_ZOUT_L 0x40 
  14. #define TEMP_OUT_H  0x41 
  15. #define TEMP_OUT_L  0x42 
  16. #define GYRO_XOUT_H  0x43 
  17. #define GYRO_XOUT_L  0x44 
  18. #define GYRO_YOUT_H  0x45 
  19. #define GYRO_YOUT_L  0x46 
  20. #define GYRO_ZOUT_H  0x47 
  21. #define GYRO_ZOUT_L  0x48 
  22. #define PWR_MGMT_1  0x6B //電源管理,典型值:0x00(正常啟用) 
  23. #define WHO_AM_I  0x75 //IIC地址寄存器(默認數值0x68,只讀) 
  24. #define SlaveAddress 0xD0 //IIC寫入時的地址字節數據,+1為讀取 
  25.  
  26. typedef struct { 
  27.         unsigned int CON; 
  28.         unsigned int DAT; 
  29.         unsigned int PUD; 
  30.         unsigned int DRV; 
  31.         unsigned int CONPDN; 
  32.         unsigned int PUDPDN; 
  33. }gpb; 
  34. #define GPB (* (volatile gpb *)0x11400040) 
  35.  
  36. typedef struct { 
  37.         unsigned int I2CCON; 
  38.         unsigned int I2CSTAT; 
  39.         unsigned int I2CADD; 
  40.         unsigned int I2CDS; 
  41.         unsigned int I2CLC; 
  42. }i2c5; 
  43. #define  I2C5 (* (volatile i2c5 *)0x138B0000 ) 
  44.  
  45. void mydelay_ms(int time
  46.   int i, j; 
  47.   while(time--) 
  48.   { 
  49.     for (i = 0; i < 5; i++) 
  50.       for (j = 0; j < 514; j++); 
  51.   } 
  52. /********************************************************************** 
  53.  * @brief            iic read a byte program body 
  54.  * @param[in]    slave_addr, addr, &data 
  55.  * @return         None 
  56.  **********************************************************************/ 
  57.  
  58. void iic_read(unsigned char slave_addr, unsigned char addr, unsigned char *data) 
  59.   /*根據mpu6050的datasheet,要讀取數據必須先執行寫操作:寫入一個從設備地址, 
  60.   然后執行讀操作,才能讀取到該內部寄存器的內容*/ 
  61.   I2C5.I2CDS = slave_addr; //將從機地址寫入I2CDS寄存器中 
  62.   I2C5.I2CCON = (1 << 7)|(1 << 6)|(1 << 5); //設置時鐘并使能中斷 
  63.   I2C5.I2CSTAT = 0xf0;    //[7:6]設置為0b11,主機發送模式; 
  64.   //往[5:4]位寫0b11,即產生啟動信號,發出IICDS寄存器中的地址 
  65.    
  66.   while(!(I2C5.I2CCON & (1 << 4))); // 等待傳輸結束,傳輸結束后,I2CCON [4]位為1,標識有中斷發生;    
  67.    
  68.   // 此位為1時,SCL線被拉低,此時I2C傳輸停止; 
  69.   I2C5.I2CDS = addr;       //寫命令值 
  70.   I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4));// I2CCON [4]位清0,繼續傳輸 
  71.   while(!(I2C5.I2CCON & (1 << 4)));// 等待傳輸結束 
  72.    
  73.   I2C5.I2CSTAT = 0xD0; // I2CSTAT[5:4]位寫0b01,發出停止信號 
  74.   I2C5.I2CDS = slave_addr | 1;  //表示要讀出數據 
  75.    
  76.   I2C5.I2CCON = (1 << 7)|(1 << 6) |(1 << 5) ; //設置時鐘并使能中斷 
  77.   I2C5.I2CSTAT = 0xb0;//[7:6]位0b10,主機接收模式; 
  78.    
  79.   //往[5:4]位寫0b11,即產生啟動信號,發出IICDS寄存器中的地址 
  80.   //    I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4));    如果強行關閉,將讀取不到數據 
  81.    
  82.   while(!(I2C5.I2CCON & (1 << 4)));//等待傳輸結束,接收數據 
  83.    
  84.   I2C5.I2CCON &= ~((1<<7)|(1 << 4));/* Resume the operation  & no ack*/ 
  85.    // I2CCON [4]位清0,繼續傳輸,接收數據,    
  86.    // 主機接收器接收到最后一字節數據后,不發出應答信號 no ack    
  87.    
  88.   // 從機發送器釋放SDA線,以允許主機發出P信號,停止傳輸; 
  89.   while(!(I2C5.I2CCON & (1 << 4)));// 等待傳輸結束 
  90.    
  91.   I2C5.I2CSTAT = 0x90; 
  92.   *data = I2C5.I2CDS; 
  93.   I2C5.I2CCON &= ~(1<<4);  /*clean interrupt pending bit  */ 
  94.   mydelay_ms(10); 
  95.   *data = I2C5.I2CDS; 
  96. /************************************************************** 
  97.  * @brief            iic write a byte program body 
  98.  * @param[in]    slave_addr, addr, data 
  99.  * @return         None 
  100.  *************************************************************/ 
  101.  
  102. void iic_write (unsigned char slave_addr, unsigned char addr, unsigned char data) 
  103.   I2C5.I2CDS = slave_addr; 
  104.   I2C5.I2CCON = (1 << 7)|(1 << 6)|(1 << 5) ; 
  105.   I2C5.I2CSTAT = 0xf0; 
  106.  
  107.   while(!(I2C5.I2CCON & (1 << 4))); 
  108.   I2C5.I2CDS = addr; 
  109.   I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4)); 
  110.   while(!(I2C5.I2CCON & (1 << 4))); 
  111.    
  112.   I2C5.I2CDS = data; 
  113.   I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4)); 
  114.    
  115.   while(!(I2C5.I2CCON & (1 << 4))); 
  116.    
  117.   I2C5.I2CSTAT = 0xd0; 
  118.   I2C5.I2CCON = I2C5.I2CCON & (~(1 << 4)); 
  119.   mydelay_ms(10); 
  120. void MPU6050_Init () 
  121.   iic_write(SlaveAddress, PWR_MGMT_1, 0x00); 
  122.   iic_write(SlaveAddress, SMPLRT_DIV, 0x07); 
  123.   iic_write(SlaveAddress, CONFIG, 0x06); 
  124.   iic_write(SlaveAddress, GYRO_CONFIG, 0x18); 
  125.   iic_write(SlaveAddress, ACCEL_CONFIG, 0x01); 
  126. /*讀取mpu6050某個內部寄存器的內容*/ 
  127. int get_data(unsigned char addr) 
  128.   char data_h, data_l; 
  129.    
  130.   iic_read(SlaveAddress, addr, &data_h); 
  131.   iic_read(SlaveAddress, addr+1, &data_l); 
  132.   return (data_h<<8)|data_l; 
  133. /* 
  134.  *  裸機代碼,不同于LINUX 應用層, 一定加循環控制 
  135.  */ 
  136. int main(void) 
  137.   int data; 
  138.   unsigned char zvalue; 
  139.  
  140.   GPB.CON = (GPB.CON & ~(0xff<<8)) | 0x33<<8; // GPBCON[3], I2C_5_SCL GPBCON[2], I2C_5_SDAmydelay_ms(100); 
  141.   uart_init(); 
  142.    
  143.   /*---------------------------------------------------------------*/  
  144.   I2C5.I2CSTAT = 0xD0; 
  145.   I2C5.I2CCON &= ~(1<<4);  /*clean interrupt pending bit  */ 
  146.    
  147.   /*--------------------------------------------------------------*/ 
  148.   mydelay_ms(100); 
  149.   MPU6050_Init(); 
  150.   mydelay_ms(100); 
  151.  
  152.   printf("\n********** I2C test!! ***********\n"); 
  153.   while(1) 
  154.   { 
  155.     data = get_data(GYRO_ZOUT_H); 
  156.      
  157.     printf(" GYRO --> Z <---:Hex: %x", data); 
  158.     data = get_data(GYRO_XOUT_H); 
  159.     printf(" GYRO --> X <---:Hex: %x", data); 
  160.      
  161.     printf("\n"); 
  162.     mydelay_ms(1000); 
  163.   } 
  164.   return 0; 

實驗結果如下:

  1. ********** I2C test!! ***********   
  2. GYRO --> Z <---:Hex: 1c GYRO --> X <---:Hex: feda   
  3. GYRO --> Z <---:Hex: fefc GYRO --> X <---:Hex: fed6   
  4. GYRO --> Z <---:Hex: fefe GYRO --> X <---:Hex: fed6   
  5. GYRO --> Z <---:Hex: fefe GYRO --> X <---:Hex: fedc   
  6. GYRO --> Z <---:Hex: fefe GYRO --> X <---:Hex: feda   
  7. GYRO --> Z <---:Hex: fefc GYRO --> X <---:Hex: fed6   
  8. GYRO --> Z <---:Hex: fefe GYRO --> X <---:Hex: feda   
  9. GYRO --> Z <---:Hex: fcf2 GYRO --> X <---:Hex: 202   
  10. GYRO --> Z <---:Hex: ec GYRO --> X <---:Hex: faa0   
  11. GYRO --> Z <---:Hex: 4c GYRO --> X <---:Hex: e   
  12. GYRO --> Z <---:Hex: fe GYRO --> X <---:Hex: fed8   
  13. GYRO --> Z <---:Hex: 0 GYRO --> X <---:Hex: fede   
  14. GYRO --> Z <---:Hex: 0 GYRO --> X <---:Hex: feda   

讀寫操作代碼解析:

寫入一個數據流程:


讀數據流程:


上圖閱讀注意點:

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

 

責任編輯:姜華 來源: 一口Linux
相關推薦

2021-01-26 06:15:42

Cortex-A9 R嵌入式系統啟動代碼

2020-12-22 11:54:42

C語言Cortex-A9LED匯編

2021-01-16 11:40:28

ARM嵌入式開發ADC應用

2020-12-30 15:17:25

Cortex-A9UARTprintf函數

2021-01-06 05:42:42

Cortex-A9 R嵌入式系統 RTC

2022-06-13 09:21:45

I2C DriverI2C 子系統

2021-01-08 12:06:59

WDT定時裝置

2017-03-16 08:30:19

Android ThAndroidI2C

2017-08-11 18:25:25

Linuxi2c

2022-05-27 09:00:09

I2C子系統協議

2010-07-01 16:45:05

I2C總線協議

2010-06-08 16:25:35

I2C總線協議

2023-04-07 09:14:31

硬件通信串口通信實驗

2022-06-12 07:30:13

I3C通訊協議

2021-12-06 08:50:27

I2C拉電阻阻值架構

2023-09-13 15:33:57

I2C鴻蒙

2022-06-18 09:02:00

I2C 子系統通信協議

2010-06-08 16:21:50

I2C總線協議

2022-06-07 08:42:21

高速模式HS mode

2021-09-08 15:44:56

鴻蒙HarmonyOS應用
點贊
收藏

51CTO技術棧公眾號

日本免费黄色小视频| 国产精品久久电影观看| 天堂www中文在线资源| 成av人片在线观看www| 国产日韩欧美精品在线| 91精品在线观看视频| 日韩精品人妻中文字幕| 日韩在线不卡| av资源网一区| 国产精品成熟老女人| 久草网站在线观看| 久久综合影院| 日韩一二三区不卡| 欧美日韩精品久久| 无码人妻久久一区二区三区不卡| 中文字幕av一区二区三区四区| 亚洲综合免费观看高清完整版| 国产一区二区三区色淫影院 | 亚洲成av人片一区二区三区| 91精品国产自产在线老师啪 | 国产一区二区三区在线观看网站| 污污的视频免费| 福利写真视频网站在线| 久久无码av三级| 91欧美激情另类亚洲| 久久不卡免费视频| 97欧美在线视频| 亚洲精品国产综合久久| 99九九99九九九99九他书对| 咪咪网在线视频| 国产亚洲成aⅴ人片在线观看 | 午夜精品久久久久久毛片| 国产在线精品免费av| 精品调教chinesegay| 在线观看18视频网站| 少妇人妻偷人精品一区二区| 免费观看久久久4p| 久久免费视频这里只有精品| 日韩精品久久久久久久的张开腿让| 一区二区在线免费播放| 欧美日韩国产一二三| 中文字幕日本最新乱码视频| 国产高清不卡视频| 热久久一区二区| 91精品成人久久| 粉嫩av性色av蜜臀av网站| 美女精品一区最新中文字幕一区二区三区| 欧美一区二区在线免费观看| 国产又大又黄又猛| 成人小电影网站| 成人国产精品免费观看视频| 国产精品视频yy9099| 国产成人免费看| 亚洲先锋成人| 欧美成人精品激情在线观看| 国产探花在线视频| 久久精品黄色| 欧美性xxxx18| av免费观看大全| 久久青青色综合| 亚洲免费观看高清完整版在线| 日本在线观看一区二区| 青青草超碰在线| 91在线视频观看| 国产在线精品一区二区中文| 亚洲精品97久久中文字幕| 国产麻豆视频精品| 亚洲综合色av| 国产xxxxxx| 国产一区视频导航| 91久久精品国产91性色| 夜夜躁狠狠躁日日躁av| 激情六月婷婷综合| 久久香蕉国产线看观看av| 国产福利在线导航| 色777狠狠狠综合伊人| 伊人久久久久久久久久久久久| a级在线免费观看| 精品国产一区二区三区| 在线精品国产欧美| 超碰97av在线| 日韩欧美在线中字| 欧美高清视频一区二区| 久久久无码人妻精品无码| 精品一区二区三区免费看| 欧美一区二区三区人| 99久久综合网| 国产精品任我爽爆在线播放| 日韩精品日韩在线观看| 亚洲区免费视频| 九九久久精品| 爽爽爽爽爽爽爽成人免费观看| 人人干在线观看| 亚洲在线久久| 亚洲高清av在线| 极品白嫩丰满美女无套| 久久人体av| 欧美顶级少妇做爰| 一区二区在线免费观看视频| 成人av激情人伦小说| 亚洲美女福利视频网站| 国产第一页精品| 午夜久久美女| 欧美一区二区影院| 91精品国产色综合久久不8| 粉嫩av亚洲一区二区图片| 久久青青草原| 美女免费久久| 婷婷夜色潮精品综合在线| 日韩在线第三页| 精品午夜视频| 亚洲欧美成人网| 手机在线中文字幕| 国产色综合网| 国产一区二区在线免费视频| 日本黄色三级视频| 国产精品天天摸av网| 成人黄色片免费| 三级成人黄色影院| 夜夜夜精品看看| 99蜜桃臀久久久欧美精品网站| 日韩久久一区| 日韩电影网在线| 久久久久亚洲av片无码| 香蕉久久夜色精品国产| 91久久精品在线| 狠狠躁日日躁夜夜躁av| 91香蕉视频污在线| 日韩精品在线观看av| 日韩欧国产精品一区综合无码| 精品国产一区久久| av资源在线免费观看| 一本色道久久| 97久草视频| 在线观看a视频| 精品国产福利在线| 久久久久久久久久久久国产精品| 欧美一区二区性| 91福利视频网| av免费观看在线| 国产亚洲人成网站| 国产原创popny丨九色| 美女精品久久| 日韩在线观看免费| 中文在线资源天堂| 久久午夜色播影院免费高清| 国产xxxx振车| 精品国产第一国产综合精品| 中文字幕亚洲在线| 一级片在线观看免费| 成人毛片在线观看| 四虎永久免费网站| 欧美va视频| 日韩www在线| 久草福利资源在线观看| 国产精品99久久久久久有的能看| 欧美精品久久久| a毛片不卡免费看片| 欧美三级在线视频| 日韩av片在线| 三级欧美韩日大片在线看| 久久久久久久久久久久久久一区| 免费网站在线观看人| 欧美岛国在线观看| 免费在线观看av网址| 国产成人av网站| 国产日产欧美一区二区| 国产一区一区| 久久精视频免费在线久久完整在线看| 黄色av网站免费| 久久久久久久久97黄色工厂| 女人扒开屁股爽桶30分钟| 欧美人妖在线观看| 国产精品69精品一区二区三区| 免费在线观看一级毛片| 欧美色图片你懂的| 中文字幕求饶的少妇| 蜜桃视频在线观看一区二区| 亚洲午夜精品久久久中文影院av| 天天综合视频在线观看| 欧美日韩国产经典色站一区二区三区| 黄色片网站在线播放| 久久99热这里只有精品| 日本三日本三级少妇三级66| 无码国模国产在线观看| 欧美精品福利视频| 亚洲日本中文字幕在线| 欧美性极品xxxx娇小| 人人妻人人澡人人爽| 久久国产人妖系列| 超级碰在线观看| 国产精品18hdxxxⅹ在线| 97国产精品视频| 国产最新视频在线| 884aa四虎影成人精品一区| 久久免费黄色网址| 91免费观看视频| 欧美精品久久久久久久久25p| 91精品观看| 国产精品伊人日日| 欧美三区四区| 精品综合久久久久久97| 无码人妻久久一区二区三区| 国产精品萝li| 女性生殖扒开酷刑vk| 亚洲专区一区二区三区| av动漫免费观看| 91麻豆精品国产91久久久久推荐资源| 欧美激情国内偷拍| 无码国产精品96久久久久| 欧美猛男男办公室激情| 日本少妇全体裸体洗澡| 日本一区二区免费在线观看视频| 中文国产在线观看| 夜夜嗨网站十八久久| 亚洲精品国产精品国自产| 国产一区二区三区不卡av| 国产情人节一区| 成人观看网址| 久久九九全国免费精品观看| 天天操天天干天天| 69精品人人人人| 51国产偷自视频区视频| 亚洲男人都懂的| 三级网站在线免费观看| 国产成人精品免费在线| 8x8x最新地址| 亚洲欧美不卡| 国产亚洲精品久久久久久久| 欧美理论在线播放| 国产在线精品一区| 伊人久久亚洲| 国产精品一区二区久久久久| 嗯~啊~轻一点视频日本在线观看| 久久精品最新地址| 黄色av网站在线免费观看| 亚洲国产另类久久精品| 精品国产乱码久久久久久蜜臀网站| 91九色02白丝porn| 国产成人无码精品| 亚洲激情五月婷婷| 国产又粗又猛又爽又黄的视频四季| 99re热这里只有精品免费视频 | 日韩主播视频在线| 亚洲精品无码国产| 一本一道久久综合狠狠老| 天天综合狠狠精品| 精品在线播放| 快播日韩欧美| 爽爽窝窝午夜精品一区二区| 古典武侠综合av第一页| 日韩精品一区二区三区免费视频| 国产专区欧美专区| 欧美美女福利视频| 国产97免费视| 美女日韩欧美| 国产精品99久久久久久久久久久久 | 四虎成人在线| 日本精品久久久| 伊人久久视频| 日本免费一区二区三区视频观看| zzzwww在线看片免费| 午夜精品久久久久久99热软件| 天天色天天射天天综合网| 欧美一卡二卡三卡| 国产乱人乱偷精品视频a人人澡| 欧美日韩一区二区三区视频| 国产精品午夜一区二区| 欧美视频一区二区三区在线观看 | 日本视频在线播放| 久久精品久久精品亚洲人| 超碰个人在线| 久久99国产综合精品女同| 18网站在线观看| 欧美黄色片免费观看| 国语对白在线刺激| 68精品久久久久久欧美| 国产精品专区免费| 国产精品黄色影片导航在线观看| 国产精品天堂蜜av在线播放| 成人美女av在线直播| 日韩欧美中文字幕一区二区三区| 亚洲最大的免费| 国产精品视屏| 日韩av免费电影| 性欧美69xoxoxoxo| 国产欧美综合一区| 国产精品av久久久久久麻豆网| 欧美精品一区免费| 日韩av一二三| 最好看的中文字幕| 99re这里只有精品6| 久久国产柳州莫菁门| 亚洲视频精选在线| 国产午夜精品无码| 色综合咪咪久久| 91精品国自产| 亚洲精品在线观| 飘雪影视在线观看免费观看 | 日韩美女激情视频| 亚洲综合资源| 韩日午夜在线资源一区二区 | 亚洲色图第一页| 91国内在线| 日韩美女中文字幕| 国产精品久久久久久久久久辛辛 | 高清不卡一二三区| 伊人网在线视频观看| 亚洲男人的天堂网| 狠狠人妻久久久久久| 6080日韩午夜伦伦午夜伦| 午夜小视频在线播放| 日韩在线免费观看视频| www555久久| 国产日韩欧美中文| 久久夜色电影| 中文精品视频一区二区在线观看| 亚洲国内精品| 日韩在线一区视频| 久久午夜老司机| 国产一级片视频| 欧美日韩一区三区| 亚洲欧洲综合在线| 欧美成人午夜激情视频| 九色porny丨国产首页在线| 国产精品久久久久久搜索| 91麻豆精品国产91久久久久推荐资源| 欧美日韩精品久久| 黑人一区二区| 亚洲欧美日韩网站| 久久一区二区三区四区| 久久久久久久久精| 欧美日本一道本在线视频| 亚洲av成人无码网天堂| 欧美精品做受xxx性少妇| a屁视频一区二区三区四区| 国内精品视频在线播放| 欧美日韩1区| 中文字幕精品一区二区三区在线| 久久久久久**毛片大全| 国产精品第一页在线观看| 6080午夜不卡| 免费大片黄在线观看视频网站| 日本精品久久中文字幕佐佐木| 丁香5月婷婷久久| 高清无码一区二区在线观看吞精| 免费国产亚洲视频| 亚洲自拍偷拍图| 在线视频一区二区三| 欧美日韩在线精品一区二区三区激情综 | 中文字幕一区二区三区中文字幕 | 久久久人成影片一区二区三区观看| 日韩欧乱色一区二区三区在线 | 九九热爱视频精品视频| 欧美牲交a欧美牲交| 成人午夜电影小说| 久久精品免费在线| 欧美mv日韩mv亚洲| 黄网av在线| 国产精品视频500部| 欧美色图首页| 久久久久久久人妻无码中文字幕爆| 一区二区三区不卡视频 | 视频免费一区| 国产日韩av在线播放| 91视频精品| 在线一区二区不卡| 亚洲免费看黄网站| 精品人妻一区二区三区浪潮在线| 免费97视频在线精品国自产拍| 国产日韩欧美中文在线| 日本免费黄色小视频| 成人性生交大片免费看中文| 九九九国产视频| 亚洲毛片在线观看| 日本精品在线一区| 一区二区高清视频| 国产美女一区二区三区| 久久久久久久久久网站| 精品国偷自产国产一区| 国产伦理精品| 久99久在线| 日韩电影免费在线| 午夜精品久久久久99蜜桃最新版| 91精品国产日韩91久久久久久| 秋霞影院午夜丰满少妇在线视频| 成人午夜激情免费视频| 国产精品v日韩精品v欧美精品网站| 久久无码人妻一区二区三区| 国产成人综合在线播放| 国产无遮挡又黄又爽| 亚洲欧美日韩国产成人| 午夜不卡一区| 久久综合色视频| 中文字幕+乱码+中文字幕一区| 国产美女自慰在线观看| 性欧美视频videos6一9| 国产欧美一区二区精品久久久| 一起操在线视频| 午夜激情综合网|