<button id="ssm6u"><optgroup id="ssm6u"></optgroup></button>
  • 跳轉至

    I2C總線接口

    概要

    本節教程為大家簡要介紹I2C總線協議,并以一個簡單的例程教會大家在MicroPython下使用I2C

    什么是I2C

    I2C(Inter-integrated Circuit)最早是飛利浦在1982年開發設計的一種總線協議。I2C總線支持設備之間的短距離通信,用于處理器和一些外圍設備之間的接口,它只需要兩根信號線來完成信息交換。

    通信原理

    物理接線

    I2C最少只需要兩根線,和異步串口類似,但可以支持多個從(slave)設備,和SPI不同的是,I2C可以支持多主機(mul-master)系統,允許有多個master并且每個master都可以與所有的slaves通信(master之間不可通過I2C通信,并且每個master只能輪流使用I2C總線)。master是指啟動數據傳輸的設備并在總線上生成時鐘信號以驅動該傳輸,而被尋址的通信設備都作為slaves。

    I2C通訊只需要2條雙向總線:

    功能編號 含義
    SDA(serial data:串行數據線) 傳輸數據,SDA線傳輸數據是大端傳輸,每次傳輸一個字節
    SCL(serial clock:串行時鐘線) 同步數據收發

    我們以最為簡單的一個主機對應多個從機為例,進行接下來的原理科普。

    數據有效性

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

    換言之,SCL為高電平時表示有效數據,SDA為高電平表示“1”,低電平表示“0”;SCL為低電平時表示無效數據,此時SDA會進行電平切換,為下次數據表示做準備。如圖13-1為數據有效性的時序圖。

    起始條件S和停止條件P

    • 起始條件S:當SCL高電平時,SDA由高電平向低電平轉換;

    • 停止條件P:當SCL高電平時,SDA由低電平向高電平轉換。

    起始和停止條件一般由主機產生??偩€在起始條件后處于busy的狀態,在停止條件的某段時間后,總線才再次處于空閑狀態。如下圖為起始和停止條件的信號產生時序圖。

    數據格式

    I2C傳輸的數據以字節為單位,每個字節必須為8位,可以傳輸任意多個字節,上圖中以一個字節的數據為例進行分析,I2C的數據格式具有以下特點:

    • 每個字節后必須跟一個響應位 ACK(如上圖中的SCL上ACK),因此實際上傳輸一個字節(8位)的數據需要花費9位的時間。

    • SDA上首先傳輸字節的最高位,從上圖中我們可以看出,位數編號的發送順序從左至右 是 Bit7-Bit0

    響應ACK

    數據接收方收到傳輸的一個字節數據后,需要給出響應,此時處在第九個時鐘,發送端釋放SDA線控制權 ,將SDA電平拉高,由接收方控制。

    接收方表示成功的接收到了8位一個字節的數據,便將SDA拉低為低電平,即ACK信號,表示應答

    PDU

    當你理解了時序圖之后,接下來我們為大家貼出I2C的PDU(Protocol Data Unit:協議數據單元,即數據格式):

    以下圖片均來自網絡

    硬件資源

    ESP32 本身擁有 2 個 I2C 總線接口,根據用戶的配置,總線接口可以用作 I2C 主機或從機模式。

    然而遺憾的是,MicroPython ESP32上的I2C是軟件模擬的,并沒有充分利用到ESP32的硬件資源。

    理論上來講,大部分同時支持輸入與輸出的GPIO都能夠被配置為I2C的管腳資源。

    I2C API文檔

    class machine.I2C(scl, sda, freq)

    scl: I2C設備時鐘引腳對象
    sda: I2C設備數據線引腳對象
    freq: SCL時鐘頻率 0 <freq≤ 500000(Hz)

    定義I2C

    示例:

    from machine import I2C, Pin
    I2C = I2C(scl=Pin(5), sda=Pin(4), freq=100000)
    

    常用類函數

    I2C.init(scl, sda, freq)

    函數說明:初始化構造I2C總線。

    scl:SCL信號線的I/O口
    sda:SDA信號線的I/O口
    freq:SCL時鐘頻率

    示例:

    I2C.init(scl=Pin(5), sda=Pin(4), freq=100000)
    
    I2C.scan()

    函數說明:掃描0x08到0x77之間的I2C地址,并返回設備列表。
    示例:

    I2C.scan()
    
    I2C.start()

    函數說明:在總線上觸發START狀態(SCL為高電平時,SDA轉為低電平)。
    示例:

    I2C.start()
    
    I2C.stop()

    函數說明:在總線上觸發STOP狀態 (SCL為高電平時,SDA轉為高電平)。
    示例:

    I2C.stop()
    
    I2C.write(buf)

    函數說明:buf中的數據寫入到總線,并返回寫入的字節數。

    buf:存儲數據的緩沖區
    

    注意
    使用write()函數時要與start函數一起使用,否則無法返回寫入的字節數。
    示例:

    buf = b'123'
    I2C.start()
    I2C.write(buf)
    
    I2C.readinto(buf, nack=True)

    函數說明:從總線上讀取數據并存放到buf,無返回值。

    buf:存儲數據的緩沖區
    

    注意:
    讀取的字節數是buf的長度。在接收到最后一個字節之前,總線將發送ACK信號。在接收到最后一個字節后,如果nack為True,那么將發送一個NACK信號,否則將發送一個ACK信號。 示例:

    buf=bytearray(3)
    I2C.readinto(buf)
    

    標準總線操作

    下面介紹的函數是標準的I2C主模式讀寫操作。

    I2C.readfrom(addr, nbytes)

    函數說明:從指定地址設備讀取數據,返回讀取對象,這個對象與I2C設備有關。

    addr:I2C設備地址(可由scan函數讀取出來)
    nbytes:要讀取數據的大小

    示例:

    >>> print(I2C.scan())
    [24]
    >>> data = I2C.readfrom(24, 8)
    >>> print(data)
    b'\x00\x02\x00\x00\xe8\x03\xe8\x03'
    
    I2C.readfrom_into(addr, buf)

    函數說明:從指定地址設備讀取buf.len()個數據到buf。

    addr:I2C設備地址(可由scan函數讀取出來)
    buf:存儲數據的緩沖區

    示例:

    >>> buf = bytearray(8)
    >>> I2C.readfrom_into(24, buf)
    >>> print(buf)
    bytearray(b'\x00\x02\x00\x00\xe8\x03\xe8\x03')
    
    I2C.writeto(addr, buf)

    函數說明:將buf中的數據寫入設備,并返回寫入數據的大小。

    addr:I2C設備地址(可由scan函數讀取出來)
    buf:存儲數據的緩沖區

    示例:

    >>> b = bytearray(3)
    >>> b[0] = 24
    >>> b[1] = 111
    >>> b[2] = 107
    >>> i = I2C.writeto(24,b)
    3
    

    內存操作

    某些 I2C 設備作為存儲設備 (或一組寄存器) ,可以讀取或者寫入。這種情況下,有兩個地址和 I2C 事務相關: 從設備地址和內存地址。下面方法用于和這些設備進行通信。

    I2C.readfrom_mem(addr, memaddr, nbytes, addrsize=8)

    函數說明:從I2C設備的寄存器中讀取并返回數據。

    addr:I2C設備地址(可由scan函數讀取出來)
    memaddr:寄存器地址
    nbytes:要讀取的字節大小
    addrsize:指定地址大小,默認為8位(在ESP8266上這個參數無效,地址大小總是8位)

    示例:

    b = I2C. readfrom_mem(24,  0x58, 3)
    print(b)
    

    運行結果:

    b'\x00\x02\x01'
    
    I2C.readfrom_mem_into(addr, memaddr, buf, addrsize=8)

    函數說明:從I2C設備的寄存器中讀取buf.len()個數據到buf,無返回值。

    addr:I2C設備地址(可由scan函數讀取出來)
    memaddr:寄存器地址
    buf:存儲數據的緩沖區
    addrsize:指定地址大小,默認為8位(在ESP8266上這個參數無效,地址大小總是8位),讀取數據數量是buf的長度。

    示例:

    buf=bytearray(8)
    I2C.readfrom_mem_into(24, 0x58, buf)
    
    I2C.writeto_mem(addr, memaddr, buf, addrsize=8)

    函數說明: 將buf 中的數據全部寫入到從設備 addr 的內存 memaddr。

    addr:I2C設備地址(可由scan函數讀取出來)
    memaddr:寄存器地址
    buf:存儲數據的緩沖區
    addrsize:指定地址大小,默認為8位(在ESP8266上這個參數無效,地址大小總是8位),讀取數據數量是buf的長度。

    示例:

    buf = b'123'
    I2C.writeto_mem(24, 0x58, buf)
    

    綜合示例

    TODO


    韩国精品无码一区二区三区,精品无码一区二区三区AV,欧洲丰满美熟女乱又伦AV,亚洲午夜久久久影院伊人