class I2CTarget – un périphérique cible I2C

Une cible I2C est un périphérique qui se connecte à un bus I2C et qui est contrôlé par un contrôleur I2C. Les cibles I2C peuvent prendre de nombreuses formes. La classe machine.I2CTarget implémente une cible I2C qui peut être configurée comme un dispositif de mémoire/registre, ou comme un périphérique I2C arbitraire à l’aide de fonctions de rappel (si le port le prend en charge).

Disponible sur l’OpenMV Cam M4 / M7 / H7 / H7 Plus / Pure Thermal / RT1062 / AE3.

Exemple d’utilisation dans le cas d’un dispositif de mémoire

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

Notez que certains ports nécessitent qu’un id, et éventuellement des broches scl et sda, soient passés au constructeur I2CTarget afin de sélectionner l’instance I2C matérielle et les broches auxquelles elle se connecte.

Lorsqu’il est configuré comme un dispositif de mémoire, il est également possible de s’enregistrer pour recevoir des événements. Par exemple, pour être notifié lorsque la mémoire est lue/écrite

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)

Des périphériques I2C plus complexes peuvent être implémentés à l’aide de l’ensemble complet des événements. Par exemple, pour visualiser les événements bruts au fur et à mesure de leur déclenchement

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)

Constructeurs

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)

Construit et renvoie un nouvel objet I2CTarget en utilisant les paramètres suivants :

  • id identifie un périphérique I2C particulier. Les valeurs autorisées dépendent du port/de la carte considérés. Certains ports ont une valeur par défaut, auquel cas ce paramètre peut être omis.

  • addr est l’adresse I2C de la cible.

  • addrsize est le nombre de bits de l’adresse de la cible I2C. Les valeurs valides sont 7 et 10.

  • mem est un objet prenant en charge le protocole tampon et accessible en écriture. S’il n’est pas spécifié, il n’y a pas de mémoire sous-jacente et les données doivent être lues/écrites à l’aide des méthodes I2CTarget.readinto() et I2CTarget.write().

  • mem_addrsize est le nombre de bits de l’adresse mémoire. Les valeurs valides sont 0, 8, 16, 24 et 32.

  • scl est un objet broche spécifiant la broche à utiliser pour SCL.

  • sda est un objet broche spécifiant la broche à utiliser pour SDA.

Notez que certains ports/cartes auront des valeurs par défaut de scl et sda qui peuvent être modifiées dans ce constructeur. D’autres auront des valeurs fixes de scl et sda qui ne peuvent pas être modifiées.

Méthodes générales

deinit() None

Désinitialise la cible I2C. Après l’appel de cette méthode, le matériel ne répondra plus aux requêtes sur le bus I2C, et aucune autre méthode ne pourra être appelée.

readinto(buf: bytearray) int

Lit dans le tampon donné les octets en attente écrits par le contrôleur I2C. Renvoie le nombre d’octets lus.

write(buf: bytes) int

Écrit les octets du tampon donné, destinés à être transmis au contrôleur I2C après qu’il a envoyé une requête de lecture. Renvoie le nombre d’octets écrits. La plupart des ports n’acceptent qu’un seul octet à la fois pour cette méthode.

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

Installe un gestionnaire d’IRQ handler qui est invoqué lorsque l’un des événements sélectionnés par trigger se déclenche. trigger est un masque binaire de constantes IRQ_* combinées par OU ; par défaut, le déclenchement se produit à la fin de chaque lecture ou écriture côté contrôleur.

hard=True enregistre un gestionnaire d’interruption matérielle (pas d’allocation sur le tas dans la fonction de rappel). La valeur par défaut est une fonction de rappel planifiée. Passez handler=None pour désactiver l’interruption.

Note

IRQ_ADDR_MATCH_READ, IRQ_ADDR_MATCH_WRITE, IRQ_READ_REQ et IRQ_WRITE_REQ doivent être traités par une fonction de rappel d’IRQ matérielle (hard=True) car ces événements doivent être acquittés de façon synchrone avec le matériel. IRQ_END_READ et IRQ_END_WRITE peuvent être traités par des fonctions de rappel logicielles ou matérielles ; tous les événements partagent un unique gestionnaire, donc si un événement nécessite une fonction de rappel matérielle, tous la nécessitent.

Lorsqu’un tampon mémoire est fourni au constructeur, le pilote supprime l’événement IRQ_END_WRITE pour la transaction qui ne fait qu’écrire l’adresse mémoire. Cela préserve le sens des événements de fin de transaction, même lorsque le planificateur d’IRQ logicielles diffère la fonction de rappel.

memaddr

La valeur entière de la dernière adresse mémoire qui a été sélectionnée par le contrôleur I2C (valide uniquement si mem a été spécifié dans le constructeur).

Constantes

Chaque constante IRQ_* est un bit indicateur. Combinez-les par OU pour construire un masque trigger pour irq(). À l’intérieur du gestionnaire, l’ensemble des événements déclenchés peut être récupéré via self.irq().flags() combiné par ET avec chaque constante.

IRQ_ADDR_MATCH_READ: int

Se déclenche lorsqu’un contrôleur adresse cette cible pour une transaction de lecture (l’octet d’adresse a été reçu avec le bit de lecture/écriture positionné à 1). IRQ matérielle uniquement.

IRQ_ADDR_MATCH_WRITE: int

Se déclenche lorsqu’un contrôleur adresse cette cible pour une transaction d’écriture (l’octet d’adresse a été reçu avec le bit de lecture/écriture positionné à 0). IRQ matérielle uniquement.

IRQ_READ_REQ: int

Se déclenche lorsque le contrôleur demande un octet à la cible. Le gestionnaire doit appeler write() pour fournir l’octet avant la fin du cycle d’horloge du contrôleur. IRQ matérielle uniquement.

IRQ_WRITE_REQ: int

Se déclenche lorsque le contrôleur a transféré un octet vers la cible. Le gestionnaire doit appeler readinto() pour récupérer l’octet avant que le contrôleur n’envoie le suivant. IRQ matérielle uniquement.

IRQ_END_READ: int

Se déclenche lorsque le contrôleur a terminé une transaction de lecture (réception d’un STOP / d’un START répété). Peut être traité par une fonction de rappel d’IRQ matérielle ou logicielle.

IRQ_END_WRITE: int

Se déclenche lorsque le contrôleur a terminé une transaction d’écriture (réception d’un STOP / d’un START répété). Peut être traité par une fonction de rappel d’IRQ matérielle ou logicielle. Supprimé pour la transaction qui écrit l’adresse mémoire lorsqu’un tampon mem a été fourni au constructeur.