clase I2CTarget – un dispositivo target de I2C¶
Un target de I2C es un dispositivo que se conecta a un bus I2C y es controlado por un controlador I2C. Los targets de I2C pueden adoptar muchas formas. La clase machine.I2CTarget implementa un target de I2C que puede configurarse como un dispositivo de memoria/registros, o como un dispositivo I2C arbitrario mediante funciones de retorno (callbacks) (si el puerto lo admite).
Disponible en la OpenMV Cam M4 / M7 / H7 / H7 Plus / Pure Thermal / RT1062 / AE3.
Ejemplo de uso para el caso de un dispositivo de memoria:
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()
Tenga en cuenta que algunos puertos requieren que se pase un id, y quizás pines scl y sda, al constructor de I2CTarget, para seleccionar la instancia I2C de hardware y los pines a los que se conecta.
Cuando se configura como dispositivo de memoria, también es posible registrarse para recibir eventos. Por ejemplo, para ser notificado cuando se lee/escribe la memoria:
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)
Pueden implementarse dispositivos I2C más complejos usando el conjunto completo de eventos. Por ejemplo, para ver los eventos en bruto a medida que se disparan:
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)
Constructores¶
- 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)¶
Construye y devuelve un nuevo objeto I2CTarget usando los siguientes parámetros:
id identifica un periférico I2C en particular. Los valores permitidos dependen del puerto/placa concreto. Algunos puertos tienen un valor predeterminado, en cuyo caso este parámetro puede omitirse.
addr es la dirección I2C del target.
addrsize es el número de bits en la dirección del target I2C. Los valores válidos son 7 y 10.
mem es un objeto con el protocolo de búfer que es escribible. Si no se especifica, no hay memoria de respaldo y los datos deben leerse/escribirse usando los métodos
I2CTarget.readinto()eI2CTarget.write().mem_addrsize es el número de bits en la dirección de memoria. Los valores válidos son 0, 8, 16, 24 y 32.
scl es un objeto pin que especifica el pin a usar para SCL.
sda es un objeto pin que especifica el pin a usar para SDA.
Tenga en cuenta que algunos puertos/placas tendrán valores predeterminados de scl y sda que pueden cambiarse en este constructor. Otros tendrán valores fijos de scl y sda que no pueden cambiarse.
Métodos generales¶
- deinit() None¶
Desinicializa el target de I2C. Después de llamar a este método, el hardware dejará de responder a las solicitudes en el bus I2C, y no se podrá llamar a ningún otro método.
- readinto(buf: bytearray) int¶
Lee en el búfer dado los bytes pendientes escritos por el controlador I2C. Devuelve el número de bytes leídos.
- write(buf: bytes) int¶
Escribe los bytes del búfer dado, para pasarlos al controlador I2C después de que este envíe una solicitud de lectura. Devuelve el número de bytes escritos. La mayoría de los puertos solo aceptan un byte a la vez en este método.
- irq(handler: Callable[[I2CTarget], None] | None = None, trigger: int = IRQ_END_READ | IRQ_END_WRITE, hard: bool = False) None¶
Instala un manejador de IRQ
handlerque se invoca cuando se dispara uno de los eventos seleccionados portrigger.triggeres una máscara de bits de constantesIRQ_*combinadas con OR; el valor predeterminado se dispara al final de cada lectura o escritura del lado del controlador.hard=Trueregistra un manejador de interrupción dura (sin asignación de heap en la función de retorno). El valor predeterminado es una función de retorno programada. Pasehandler=Nonepara deshabilitar la interrupción.Nota
IRQ_ADDR_MATCH_READ,IRQ_ADDR_MATCH_WRITE,IRQ_READ_REQeIRQ_WRITE_REQdeben manejarse mediante una función de retorno de IRQ dura (hard=True) porque los eventos tienen que confirmarse de forma síncrona con el hardware.IRQ_END_READeIRQ_END_WRITEpueden manejarse mediante funciones de retorno blandas o duras; todos los eventos comparten un único manejador, así que si algún evento necesita una función de retorno dura, todos la necesitan.Cuando se suministra un búfer de memoria al constructor, el controlador suprime
IRQ_END_WRITEpara la transacción que solo escribe la dirección de memoria. Esto mantiene significativos los eventos de fin de transacción incluso cuando el planificador de IRQ blandas difiere la función de retorno.
- memaddr¶
El valor entero de la dirección de memoria más reciente que fue seleccionada por el controlador I2C (solo válido si se especificó
memen el constructor).
Constantes¶
Cada constante
IRQ_*es un bit de bandera. Combínelas con OR para construir una máscaratriggerparairq(). Dentro del manejador, el conjunto de eventos disparados puede recuperarse medianteself.irq().flags()combinado con AND con cada constante.- IRQ_ADDR_MATCH_READ: int¶
Se dispara cuando un controlador direcciona este target para una transacción de lectura (el byte de dirección se ha recibido con el bit de lectura/escritura puesto a
1). Solo IRQ dura.
- IRQ_ADDR_MATCH_WRITE: int¶
Se dispara cuando un controlador direcciona este target para una transacción de escritura (el byte de dirección se ha recibido con el bit de lectura/escritura puesto a
0). Solo IRQ dura.
- IRQ_READ_REQ: int¶
Se dispara cuando el controlador está solicitando un byte del target. El manejador debe llamar a
write()para suministrar el byte antes de que se complete el ciclo de reloj del controlador. Solo IRQ dura.
- IRQ_WRITE_REQ: int¶
Se dispara cuando el controlador ha introducido un byte en el target mediante el reloj. El manejador debe llamar a
readinto()para recuperar el byte antes de que el controlador envíe el siguiente. Solo IRQ dura.
- IRQ_END_READ: int¶
Se dispara cuando el controlador ha terminado una transacción de lectura (ha recibido STOP / START repetido). Puede manejarse mediante una función de retorno de IRQ dura o blanda.
- IRQ_END_WRITE: int¶
Se dispara cuando el controlador ha terminado una transacción de escritura (ha recibido STOP / START repetido). Puede manejarse mediante una función de retorno de IRQ dura o blanda. Se suprime para la transacción que escribe la dirección de memoria cuando se suministró un búfer
memal constructor.