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.