class I2CTarget – התקן יעד I2C

יעד I2C הוא התקן המתחבר לאפיק I2C ונשלט על ידי בקר I2C. יעדי I2C יכולים ללבוש צורות רבות. המחלקה machine.I2CTarget מממשת יעד I2C שניתן להגדירו כהתקן זיכרון/אוגרים, או כהתקן I2C שרירותי באמצעות פונקציות callback (אם נתמך על ידי הפורט).

זמין ב-OpenMV Cam M4 / M7 / H7 / H7 Plus / Pure Thermal / RT1062 / AE3.

דוגמת שימוש למקרה של התקן זיכרון:

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

שים לב שחלק מהפורטים דורשים העברת id, ואולי פיני scl ו-sda, לבנאי I2CTarget, כדי לבחור את מופע ה-I2C החומרתי ואת הפינים שאליהם הוא מתחבר.

כאשר מוגדר כהתקן זיכרון, ניתן גם להירשם לקבלת אירועים. למשל כדי לקבל התראה כאשר הזיכרון נקרא/נכתב:

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)

התקני I2C מורכבים יותר ניתן לממש באמצעות מערך האירועים המלא. למשל, כדי לראות את האירועים הגולמיים בעת הפעלתם:

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)

בנאים (Constructors)

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)

בונה ומחזיר אובייקט I2CTarget חדש באמצעות הפרמטרים הבאים:

  • id מזהה התקן I2C היקפי מסוים. הערכים המותרים תלויים בפורט/לוח המסוים. לחלק מהפורטים יש ברירת מחדל ובמקרה זה ניתן להשמיט פרמטר זה.

  • addr היא כתובת ה-I2C של היעד.

  • addrsize הוא מספר הביטים בכתובת יעד ה-I2C. הערכים החוקיים הם 7 ו-10.

  • mem הוא אובייקט בעל פרוטוקול החוצץ שניתן לכתיבה. אם לא צוין אז אין זיכרון תומך ויש לקרוא/לכתוב נתונים באמצעות המתודות I2CTarget.readinto() ו-I2CTarget.write().

  • mem_addrsize הוא מספר הביטים בכתובת הזיכרון. הערכים החוקיים הם 0, 8, 16, 24 ו-32.

  • scl הוא אובייקט פין המציין את הפין שישמש עבור SCL.

  • sda הוא אובייקט פין המציין את הפין שישמש עבור SDA.

שים לב שחלק מהפורטים/לוחות יכללו ערכי ברירת מחדל של scl ו-sda שניתן לשנותם בבנאי זה. לאחרים יהיו ערכים קבועים של scl ו-sda שלא ניתן לשנותם.

מתודות כלליות

deinit() None

בטל את אתחול יעד ה-I2C. לאחר קריאה למתודה זו החומרה לא תגיב עוד לבקשות על אפיק ה-I2C, ולא ניתן לקרוא למתודות אחרות.

readinto(buf: bytearray) int

קרא אל החוצץ הנתון כל בית ממתין שנכתב על ידי בקר ה-I2C. מחזיר את מספר הבתים שנקראו.

write(buf: bytes) int

כתוב החוצה את הבתים מהחוצץ הנתון, כדי להעבירם לבקר ה-I2C לאחר שהוא שולח בקשת קריאה. מחזיר את מספר הבתים שנכתבו. רוב הפורטים מקבלים רק בית אחד בכל פעם במתודה זו.

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

התקן מטפל פסיקות handler המופעל כאשר אחד מהאירועים שנבחרו על ידי trigger מתרחש. trigger הוא מסכת ביטים של קבועי IRQ_* המאוגדים יחד ב-OR; ברירת המחדל מופעלת בסיום כל קריאה או כתיבה בצד הבקר.

hard=True רושם מטפל פסיקה-קשיחה (ללא הקצאת heap בתוך פונקציית ה-callback). ברירת המחדל היא callback מתוזמן. העבר handler=None כדי להשבית את הפסיקה.

הערה

IRQ_ADDR_MATCH_READ, IRQ_ADDR_MATCH_WRITE, IRQ_READ_REQ ו-IRQ_WRITE_REQ חייבים להיות מטופלים על ידי callback של פסיקה קשיחה (hard=True) משום שהאירועים חייבים לקבל אישור באופן סינכרוני עם החומרה. IRQ_END_READ ו-IRQ_END_WRITE עשויים להיות מטופלים על ידי callback רך או קשיח; כל האירועים חולקים מטפל יחיד, ולכן אם אירוע כלשהו זקוק ל-callback קשיח, כולם זקוקים לכך.

כאשר חוצץ זיכרון מסופק לבנאי, המנהל מדכא את IRQ_END_WRITE עבור הטרנזקציה שרק כותבת את כתובת הזיכרון. הדבר שומר על משמעות אירועי סוף-הטרנזקציה גם כאשר מתזמן הפסיקה-הרכה דוחה את ה-callback.

memaddr

הערך השלם של כתובת הזיכרון האחרונה שנבחרה על ידי בקר ה-I2C (תקף רק אם mem צוין בבנאי).

קבועים

כל קבוע IRQ_* הוא ביט דגל. אגד אותם יחד ב-OR כדי לבנות מסכת trigger עבור irq(). בתוך המטפל ניתן לשחזר את מערך האירועים שהתרחשו באמצעות self.irq().flags() המאוגד ב-AND עם כל קבוע.

IRQ_ADDR_MATCH_READ: int

מתרחש כאשר בקר מכוון לי יעד זה עבור טרנזקציית קריאה (בית הכתובת התקבל כשביט הקריאה/כתיבה מוגדר ל-1). פסיקה-קשיחה בלבד.

IRQ_ADDR_MATCH_WRITE: int

מתרחש כאשר בקר מכוון ליעד זה עבור טרנזקציית כתיבה (בית הכתובת התקבל כשביט הקריאה/כתיבה מוגדר ל-0). פסיקה-קשיחה בלבד.

IRQ_READ_REQ: int

מתרחש כאשר הבקר מבקש בית מהיעד. המטפל חייב לקרוא ל-write() כדי לספק את הבית לפני שמחזור השעון של הבקר מסתיים. פסיקה-קשיחה בלבד.

IRQ_WRITE_REQ: int

מתרחש כאשר הבקר העביר בית אל היעד (clocked in). המטפל חייב לקרוא ל-readinto() כדי לאחזר את הבית לפני שהבקר שולח את הבא. פסיקה-קשיחה בלבד.

IRQ_END_READ: int

מתרחש כאשר הבקר סיים טרנזקציית קריאה (קיבל STOP / START חוזר). עשוי להיות מטופל על ידי callback של פסיקה קשיחה או רכה.

IRQ_END_WRITE: int

מתרחש כאשר הבקר סיים טרנזקציית כתיבה (קיבל STOP / START חוזר). עשוי להיות מטופל על ידי callback של פסיקה קשיחה או רכה. מדוכא עבור הטרנזקציה שכותבת את כתובת הזיכרון כאשר חוצץ mem סופק לבנאי.