klasa I2CTarget – urządzenie docelowe I2C

Urządzenie docelowe I2C (target) to urządzenie, które łączy się z magistralą I2C i jest sterowane przez kontroler I2C. Urządzenia docelowe I2C mogą przyjmować wiele postaci. Klasa machine.I2CTarget implementuje urządzenie docelowe I2C, które można skonfigurować jako urządzenie pamięci/rejestrów lub jako dowolne urządzenie I2C za pomocą wywołań zwrotnych (jeśli port to obsługuje).

Dostępne na OpenMV Cam M4 / M7 / H7 / H7 Plus / Pure Thermal / RT1062 / AE3.

Przykład użycia w przypadku urządzenia pamięciowego:

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

Należy zauważyć, że niektóre porty wymagają przekazania do konstruktora I2CTarget parametru id, a być może także pinów scl i sda, aby wybrać sprzętową instancję I2C oraz piny, do których się ona podłącza.

Po skonfigurowaniu jako urządzenie pamięciowe możliwe jest również zarejestrowanie się do odbierania zdarzeń. Na przykład w celu powiadomienia o odczycie/zapisie pamięci:

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)

Bardziej złożone urządzenia I2C można zaimplementować, korzystając z pełnego zestawu zdarzeń. Na przykład, aby zobaczyć surowe zdarzenia w momencie ich wyzwalania:

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)

Konstruktory

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)

Konstruuje i zwraca nowy obiekt I2CTarget, używając następujących parametrów:

  • id identyfikuje konkretne urządzenie peryferyjne I2C. Dozwolone wartości zależą od konkretnego portu/płytki. Niektóre porty mają wartość domyślną, w którym to przypadku ten parametr można pominąć.

  • addr to adres I2C urządzenia docelowego.

  • addrsize to liczba bitów w adresie urządzenia docelowego I2C. Prawidłowe wartości to 7 i 10.

  • mem to obiekt obsługujący protokół buforów, który jest zapisywalny. Jeśli nie zostanie podany, nie ma pamięci podkładowej, a dane muszą być odczytywane/zapisywane za pomocą metod I2CTarget.readinto() i I2CTarget.write().

  • mem_addrsize to liczba bitów w adresie pamięci. Prawidłowe wartości to 0, 8, 16, 24 i 32.

  • scl to obiekt pinu określający pin używany dla SCL.

  • sda to obiekt pinu określający pin używany dla SDA.

Należy zauważyć, że niektóre porty/płytki będą miały domyślne wartości scl i sda, które można zmienić w tym konstruktorze. Inne będą miały stałe wartości scl i sda, których nie można zmienić.

Metody ogólne

deinit() None

Deinicjalizuje urządzenie docelowe I2C. Po wywołaniu tej metody sprzęt nie będzie już odpowiadał na żądania na magistrali I2C i nie można wywołać żadnych innych metod.

readinto(buf: bytearray) int

Odczytuje do podanego bufora wszelkie oczekujące bajty zapisane przez kontroler I2C. Zwraca liczbę odczytanych bajtów.

write(buf: bytes) int

Wypisuje bajty z podanego bufora, które mają zostać przekazane kontrolerowi I2C po wysłaniu przez niego żądania odczytu. Zwraca liczbę zapisanych bajtów. Większość portów akceptuje w tej metodzie tylko jeden bajt na raz.

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

Instaluje procedurę obsługi przerwania handler, która jest wywoływana, gdy nastąpi jedno ze zdarzeń wybranych przez trigger. trigger to maska bitowa stałych IRQ_* połączonych operatorem OR; domyślnie wyzwala się na końcu każdego odczytu lub zapisu po stronie kontrolera.

hard=True rejestruje procedurę obsługi twardego przerwania (bez alokacji na stercie w wywołaniu zwrotnym). Wartością domyślną jest zaplanowane wywołanie zwrotne. Przekaż handler=None, aby wyłączyć przerwanie.

Informacja

IRQ_ADDR_MATCH_READ, IRQ_ADDR_MATCH_WRITE, IRQ_READ_REQ i IRQ_WRITE_REQ muszą być obsługiwane przez wywołanie zwrotne twardego przerwania (hard=True), ponieważ zdarzenia te muszą być potwierdzane synchronicznie ze sprzętem. IRQ_END_READ i IRQ_END_WRITE mogą być obsługiwane przez wywołania zwrotne miękkie lub twarde; wszystkie zdarzenia współdzielą jedną procedurę obsługi, więc jeśli jakiekolwiek zdarzenie wymaga twardego wywołania zwrotnego, wymagają go wszystkie.

Gdy do konstruktora dostarczony jest bufor pamięci, sterownik tłumi IRQ_END_WRITE dla transakcji, która jedynie zapisuje adres pamięci. Dzięki temu zdarzenia końca transakcji pozostają znaczące, nawet gdy harmonogram miękkich przerwań odracza wywołanie zwrotne.

memaddr

Wartość całkowita ostatnio wybranego przez kontroler I2C adresu pamięci (prawidłowa tylko wtedy, gdy w konstruktorze podano mem).

Stałe

Każda stała IRQ_* jest bitem flagi. Połącz je operatorem OR, aby zbudować maskę trigger dla irq(). Wewnątrz procedury obsługi zestaw wyzwolonych zdarzeń można odtworzyć za pomocą self.irq().flags() połączonego operatorem AND z każdą stałą.

IRQ_ADDR_MATCH_READ: int

Wyzwala się, gdy kontroler adresuje to urządzenie docelowe na potrzeby transakcji odczytu (bajt adresu został odebrany z bitem odczytu/zapisu ustawionym na 1). Tylko twarde przerwanie.

IRQ_ADDR_MATCH_WRITE: int

Wyzwala się, gdy kontroler adresuje to urządzenie docelowe na potrzeby transakcji zapisu (bajt adresu został odebrany z bitem odczytu/zapisu ustawionym na 0). Tylko twarde przerwanie.

IRQ_READ_REQ: int

Wyzwala się, gdy kontroler żąda bajtu od urządzenia docelowego. Procedura obsługi musi wywołać write(), aby dostarczyć bajt, zanim zakończy się cykl zegara kontrolera. Tylko twarde przerwanie.

IRQ_WRITE_REQ: int

Wyzwala się, gdy kontroler wprowadził (przez zegar) bajt do urządzenia docelowego. Procedura obsługi musi wywołać readinto(), aby pobrać bajt, zanim kontroler wyśle następny. Tylko twarde przerwanie.

IRQ_END_READ: int

Wyzwala się, gdy kontroler zakończył transakcję odczytu (odebrano STOP / powtórzony START). Może być obsługiwane przez wywołanie zwrotne twardego lub miękkiego przerwania.

IRQ_END_WRITE: int

Wyzwala się, gdy kontroler zakończył transakcję zapisu (odebrano STOP / powtórzony START). Może być obsługiwane przez wywołanie zwrotne twardego lub miękkiego przerwania. Tłumione dla transakcji zapisującej adres pamięci, gdy do konstruktora dostarczono bufor mem.