class I2CTarget -- 一個 I2C 目標裝置

I2C 目標是連接至 I2C 匯流排並由 I2C 控制器控制的裝置。I2C 目標可有多種形式。machine.I2CTarget 類別實作了一個 I2C 目標,可組態為記憶體/暫存器裝置,或透過回呼函式組態為任意 I2C 裝置(若 port 支援)。

適用於 OpenMV Cam M4 / M7 / H7 / H7 Plus / Pure Thermal / RT1062 / AE3。

記憶體裝置情況的使用範例:

from machine import I2CTarget

# Create the backing memory for the I2C target.
mem = bytearray(8)

# Create an I2C target.  Depending on the port, extra parameters
# may be required to select the peripheral and/or pins to use.
i2c = I2CTarget(addr=67, mem=mem)

# At this point an I2C controller can read and write `mem`.
...

# Deinitialise the I2C target.
i2c.deinit()

請注意,某些 port 需要將 id,以及可能的 sclsda 接腳傳入 I2CTarget 建構式,以選擇其所連接的硬體 I2C 實例與接腳。

組態為記憶體裝置時,亦可註冊以接收事件。例如在記憶體被讀取/寫入時收到通知:

from machine import I2CTarget

# Define an IRQ handler, for I2C events.
def irq_handler(i2c_target):
    flags = i2c_target.irq().flags()
    if flags & I2CTarget.IRQ_END_READ:
        print("controller read target at addr", i2c_target.memaddr)
    if flags & I2CTarget.IRQ_END_WRITE:
        print("controller wrote target at addr", i2c_target.memaddr)

# Create the I2C target and register to receive default events.
mem = bytearray(8)
i2c = I2CTarget(addr=67, mem=mem)
i2c.irq(irq_handler)

更複雜的 I2C 裝置可使用完整的事件集來實作。例如,查看事件被觸發時的原始事件:

from machine import I2CTarget

# Define an IRQ handler that prints the event id and responds to reads/writes.
def irq_handler(i2c_target, buf=bytearray(1)):
    flags = i2c_target.irq().flags()
    print(flags)
    if flags & I2CTarget.IRQ_READ_REQ:
        i2c_target.write(buf)
    if flags & I2CTarget.IRQ_WRITE_REQ:
        i2c_target.readinto(buf)

# Create the I2C target and register to receive all events.
i2c = I2CTarget(addr=67)
all_triggers = (
    I2CTarget.IRQ_ADDR_MATCH_READ
    | I2CTarget.IRQ_ADDR_MATCH_WRITE
    | I2CTarget.IRQ_READ_REQ
    | I2CTarget.IRQ_WRITE_REQ
    | I2CTarget.IRQ_END_READ
    | I2CTarget.IRQ_END_WRITE
)
i2c.irq(irq_handler, trigger=all_triggers, hard=True)

建構式

class machine.I2CTarget(id: int, addr: int, *, addrsize: int = 7, mem: bytearray | None = None, mem_addrsize: int = 8, scl: Pin | None = None, sda: Pin | None = None)

使用下列參數建構並回傳一個新的 I2CTarget 物件:

  • id 用於識別特定的 I2C 周邊裝置。允許的值取決於特定的 port/開發板。某些 port 具有預設值,此情況下可省略此參數。

  • addr 是目標的 I2C 位址。

  • addrsize 是 I2C 目標位址的位元數。有效值為 7 與 10。

  • mem 是一個具備緩衝協定且可寫入的物件。若未指定,則沒有後備記憶體,資料必須使用 I2CTarget.readinto()I2CTarget.write() 方法進行讀寫。

  • mem_addrsize 是記憶體位址的位元數。有效值為 0、8、16、24 與 32。

  • scl 是一個接腳物件,指定要用於 SCL 的接腳。

  • sda 是一個接腳物件,指定要用於 SDA 的接腳。

請注意,某些 port/開發板會有 sclsda 的預設值,可在此建構式中變更。其他則會有無法變更的 sclsda 固定值。

一般方法

deinit() None

解除初始化 I2C 目標。呼叫此方法之後,硬體將不再回應 I2C 匯流排上的請求,且無法再呼叫其他方法。

readinto(buf: bytearray) int

將 I2C 控制器寫入的任何待處理位元組讀取至給定的緩衝區。回傳讀取的位元組數。

write(buf: bytes) int

從給定的緩衝區寫出位元組,以便在 I2C 控制器送出讀取請求後傳遞給它。回傳寫入的位元組數。大多數 port 此方法一次只接受一個位元組。

irq(handler: Callable[[I2CTarget], None] | None = None, trigger: int = IRQ_END_READ | IRQ_END_WRITE, hard: bool = False) None

安裝一個 IRQ handler,當 trigger 所選擇的其中一個事件觸發時即會被調用。trigger 是由 IRQ_* 常數以 OR 運算組合而成的位元遮罩;預設在每次控制器端讀取或寫入結束時觸發。

hard=True 會註冊一個硬中斷處理常式(回呼函式中不進行堆積配置)。預設為排程式回呼函式。傳入 handler=None 以停用該中斷。

備註

IRQ_ADDR_MATCH_READIRQ_ADDR_MATCH_WRITEIRQ_READ_REQIRQ_WRITE_REQ 必須由硬 IRQ 回呼函式(hard=True)處理,因為這些事件必須與硬體同步地被確認。IRQ_END_READIRQ_END_WRITE 可由軟或硬回呼函式處理;所有事件共用單一處理常式,因此若有任一事件需要硬回呼函式,則全部都需要。

當建構式提供記憶體緩衝區時,驅動程式會抑制僅寫入記憶體位址之交易的 IRQ_END_WRITE。即使軟 IRQ 排程器延後了回呼函式,這也能使交易結束事件保持有意義。

memaddr

I2C 控制器最近所選定之記憶體位址的整數值(僅在建構式中指定了 mem 時有效)。

常數

每個 IRQ_* 常數都是一個旗標位元。將它們以 OR 運算組合,以建立供 irq() 使用的 trigger 遮罩。在處理常式內部,可透過 self.irq().flags() 與各常數進行 AND 運算來取得已觸發的事件集。

IRQ_ADDR_MATCH_READ: int

當控制器為了讀取交易而對此目標定址時觸發(位址位元組已收到,且讀寫位元設為 1)。僅限硬 IRQ。

IRQ_ADDR_MATCH_WRITE: int

當控制器為了寫入交易而對此目標定址時觸發(位址位元組已收到,且讀寫位元設為 0)。僅限硬 IRQ。

IRQ_READ_REQ: int

當控制器向目標請求一個位元組時觸發。處理常式必須在控制器的時脈週期完成前呼叫 write() 以提供該位元組。僅限硬 IRQ。

IRQ_WRITE_REQ: int

當控制器已將一個位元組時脈輸入至目標時觸發。處理常式必須在控制器送出下一個位元組之前呼叫 readinto() 以取得該位元組。僅限硬 IRQ。

IRQ_END_READ: int

當控制器完成一次讀取交易(收到 STOP / 重複的 START)時觸發。可由硬或軟 IRQ 回呼函式處理。

IRQ_END_WRITE: int

當控制器完成一次寫入交易(收到 STOP / 重複的 START)時觸發。可由硬或軟 IRQ 回呼函式處理。當建構式提供了 mem 緩衝區時,會抑制僅寫入記憶體位址之交易的此事件。