classe I2CTarget – um dispositivo alvo I2C

Um alvo I2C é um dispositivo que se conecta a um barramento I2C e é controlado por um controlador I2C. Os alvos I2C podem assumir muitas formas. A classe machine.I2CTarget implementa um alvo I2C que pode ser configurado como um dispositivo de memória/registradores, ou como um dispositivo I2C arbitrário usando callbacks (se suportado pela porta).

Disponível na OpenMV Cam M4 / M7 / H7 / H7 Plus / Pure Thermal / RT1062 / AE3.

Exemplo de uso para o caso de um dispositivo de memória:

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()

Observe que algumas portas exigem que um id, e talvez os pinos scl e sda, sejam passados ao construtor de I2CTarget, para selecionar a instância de I2C de hardware e os pinos aos quais ela se conecta.

Quando configurado como um dispositivo de memória, também é possível registrar-se para receber eventos. Por exemplo, para ser notificado quando a memória é lida/escrita:

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)

Dispositivos I2C mais complexos podem ser implementados usando o conjunto completo de eventos. Por exemplo, para ver os eventos brutos à medida que são acionados:

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)

Construtores

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)

Constrói e retorna um novo objeto I2CTarget usando os seguintes parâmetros:

  • id identifica um periférico I2C específico. Os valores permitidos dependem da porta/placa específica. Algumas portas têm um valor padrão, caso em que este parâmetro pode ser omitido.

  • addr é o endereço I2C do alvo.

  • addrsize é o número de bits no endereço do alvo I2C. Os valores válidos são 7 e 10.

  • mem é um objeto com o protocolo de buffer que é gravável. Se não for especificado, não há memória de respaldo e os dados devem ser lidos/escritos usando os métodos I2CTarget.readinto() e I2CTarget.write().

  • mem_addrsize é o número de bits no endereço de memória. Os valores válidos são 0, 8, 16, 24 e 32.

  • scl é um objeto de pino que especifica o pino a ser usado para SCL.

  • sda é um objeto de pino que especifica o pino a ser usado para SDA.

Observe que algumas portas/placas terão valores padrão de scl e sda que podem ser alterados neste construtor. Outras terão valores fixos de scl e sda que não podem ser alterados.

Métodos Gerais

deinit() None

Desinicializa o alvo I2C. Após este método ser chamado, o hardware não responderá mais a requisições no barramento I2C, e nenhum outro método poderá ser chamado.

readinto(buf: bytearray) int

Lê para o buffer fornecido quaisquer bytes pendentes escritos pelo controlador I2C. Retorna o número de bytes lidos.

write(buf: bytes) int

Escreve os bytes do buffer fornecido, para serem passados ao controlador I2C após ele enviar uma requisição de leitura. Retorna o número de bytes escritos. A maioria das portas aceita apenas um byte por vez neste método.

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

Instala um manipulador de IRQ handler que é invocado quando um dos eventos selecionados por trigger é disparado. trigger é uma máscara de bits de constantes IRQ_* combinadas com OR; o padrão dispara ao final de cada leitura ou escrita do lado do controlador.

hard=True registra um manipulador de interrupção rígida (sem alocação de heap no callback). O padrão é um callback agendado. Passe handler=None para desabilitar a interrupção.

Nota

IRQ_ADDR_MATCH_READ, IRQ_ADDR_MATCH_WRITE, IRQ_READ_REQ e IRQ_WRITE_REQ devem ser tratados por um callback de IRQ rígida (hard=True), porque os eventos precisam ser confirmados de forma síncrona com o hardware. IRQ_END_READ e IRQ_END_WRITE podem ser tratados por callbacks suaves ou rígidos; todos os eventos compartilham um único manipulador, portanto, se algum evento precisar de um callback rígido, todos precisam.

Quando um buffer de memória é fornecido ao construtor, o driver suprime IRQ_END_WRITE para a transação que apenas escreve o endereço de memória. Isso mantém os eventos de fim de transação significativos mesmo quando o agendador de IRQ suave adia o callback.

memaddr

O valor inteiro do endereço de memória mais recente que foi selecionado pelo controlador I2C (válido apenas se mem foi especificado no construtor).

Constantes

Cada constante IRQ_* é um bit de flag. Combine-as com OR para construir uma máscara trigger para irq(). Dentro do manipulador, o conjunto de eventos disparados pode ser recuperado por meio de self.irq().flags() combinado com AND a cada constante.

IRQ_ADDR_MATCH_READ: int

Dispara quando um controlador endereça este alvo para uma transação de leitura (o byte de endereço foi recebido com o bit de leitura/escrita definido como 1). Apenas IRQ rígida.

IRQ_ADDR_MATCH_WRITE: int

Dispara quando um controlador endereça este alvo para uma transação de escrita (o byte de endereço foi recebido com o bit de leitura/escrita definido como 0). Apenas IRQ rígida.

IRQ_READ_REQ: int

Dispara quando o controlador está solicitando um byte do alvo. O manipulador deve chamar write() para fornecer o byte antes que o ciclo de clock do controlador seja concluído. Apenas IRQ rígida.

IRQ_WRITE_REQ: int

Dispara quando o controlador inseriu um byte no alvo. O manipulador deve chamar readinto() para recuperar o byte antes que o controlador envie o próximo. Apenas IRQ rígida.

IRQ_END_READ: int

Dispara quando o controlador concluiu uma transação de leitura (recebeu STOP / START repetido). Pode ser tratado por um callback de IRQ rígida ou suave.

IRQ_END_WRITE: int

Dispara quando o controlador concluiu uma transação de escrita (recebeu STOP / START repetido). Pode ser tratado por um callback de IRQ rígida ou suave. Suprimido para a transação que escreve o endereço de memória quando um buffer mem foi fornecido ao construtor.