class CAN – פרוטוקול Controller Area Network

CAN הוא פרוטוקול טורי דו-חוטי המשמש למסירה אמינה של הודעות בזמן אמת בין צומת אחד או יותר המחוברים לבאס משותף. CAN 2.0 תוקנן בתקן ISO-11898, וכיום הוא ידוע גם בשם CAN Classic.

קיים גם פרוטוקול חדש יותר ותואם לאחור בשם CAN FD (CAN with Flexible Data-Rate). מנהל ההתקן machine.CAN אינו תומך כרגע בתכונות CAN FD; השתמשו ב-pyb.CAN ב-STM32 אם אתם זקוקים ל-CAN FD.

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

זמין במצלמות OpenMV מבוססות STM32 (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6, וכן הגרסאות הממותגות Arduino המחווטות עם מקלט-משדר). אינו נתמך עדיין ב-OpenMV Cam RT1062 (פורט mimxrt) או ב-OpenMV Cam AE3 (פורט alif).

הממשק machine.CAN הוא ממשק בסיסי ברמה נמוכה להעברת הודעות CAN המפשט בקר CAN כתור עדיפויות יוצא לשליחת הודעות, תור נכנס לקבלת הודעות, ומנגנונים לדיווח על שגיאות.

הערה

מודולי micropython-lib המתוכננים can ו-aiocan יהיו הדרך המומלצת להשתמש ב-CAN עם MicroPython.

Constructor

class machine.CAN(id: int, *args, **kwargs)

בניית אובייקט בקר CAN בעל ה-id הנתון:

  • id מזהה אובייקט בקר CAN מסוים; הוא ספציפי ללוח ולפורט.

  • כל יתר הארגומנטים מועברים אל CAN.init(). יש לספק לפחות ארגומנט אחד (bitrate).

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

Example

בנייה ואתחול של בקר CAN מס« 1 עם bitrate של 500kbps:

from machine import CAN
can = CAN(1, 500_000)

Methods

init(bitrate: int, mode: int = CAN.MODE_NORMAL, sample_point: int = 75, sjw: int = 1, tseg1: int | None = None, tseg2: int | None = None) None

אתחול הבאס של CAN עם הפרמטרים הנתונים:

  • bitrate הוא קצב הביטים הרצוי של הבאס בביטים לשנייה.

  • mode הוא אחד מהערכים המוצגים תחת Modes, ומציין את מצב הפעולה הרצוי. ברירת המחדל היא פעולה ”normal“ על הבאס.

הפרמטרים הבאים אופציונליים ונוגעים לתזמוני הביטים של CAN. ברוב המקרים ניתן להשאיר פרמטרים אלה בערכי ברירת המחדל:

  • sample_point הוא אחוז שלם מזמן ביט הנתונים. הוא מציין את מיקום דגימת הביט ביחס לכלל זמן הביט הנומינלי. מנהל ההתקן של CAN יחשב את הפרמטרים בהתאם. פרמטר זה מתעלמים ממנו אם tseg1 ו-tseg2 מוגדרים.

  • sjw הוא רוחב קפיצת הסנכרון מחדש ביחידות של קוונטות זמן עבור ביטים נומינליים; הוא יכול להיות ערך בין 1 ל-4 כולל עבור CAN קלאסי.

  • tseg1 מגדיר את מיקום נקודת הדגימה ביחידות של קוונטות זמן עבור ביטים נומינליים; הוא יכול להיות ערך בין 1 ל-16 כולל עבור CAN קלאסי. זהו סכום הפאזות Prop_Seg ו-Phase_Seg1 כפי שהוגדרו בתקן ISO-11898. אם ערך זה מוגדר אז יש להגדיר גם את tseg2 ומתעלמים מ-sample_point.

  • tseg2 מגדיר את מיקום נקודת השידור ביחידות של קוונטות הזמן עבור ביטים נומינליים; הוא יכול להיות ערך בין 1 ל-8 כולל עבור CAN קלאסי. זה מתאים ל-Phase_Seg2 בתקן ISO-11898. אם ערך זה מוגדר אז יש להגדיר גם את tseg1.

אם ארגומנטים אלה מצוינים אז בקר CAN מוגדר נכון עבור ה-bitrate הרצוי והמספר הכולל המצוין של קוונטות זמן לכל ביט. הערכים tseg1 ו-tseg2 גוברים על הארגומנט sample_point אם כולם סופקו.

הערה

חומרת בקר מסוימת עשויה להטיל הגבלות נוספות על ערכים תקפים עבור פרמטרים אלה, ותעלה ValueError אם ערך נתון אינו נתמך.

הערה

חומרת בקר ספציפית עשויה לקבל פרמטרים אופציונליים נוספים בעלי מילות מפתח עבור תכונות ספציפיות לחומרה כגון oversampling.

set_filters(filters: list | tuple | None) None

הגדרת מסנני קליטה בבקר CAN. filters יכול להיות:

  • None כדי לקבל את כל ההודעות הנכנסות, או

  • [] או () כדי לבטל את קליטת כל ההודעות, או

  • איטרבל של פריט אחד או יותר המגדירים את קריטריוני הסינון. כל פריט צריך להיות tuple או list בעל שלושה אלמנטים:

    • identifier הוא מזהה CAN (int).

    • bit_mask הוא מסכת ביטים עבור הביטים בשדה מזהה CAN (int).

    • flags הוא מספר שלם עם אפס או יותר מהביטים המוגדרים ב-Message Flags. זה מציין מאפיינים שההודעה הנכנסת צריכה להתאים להם. לא כל הבקרים תומכים בסינון על כל ה-flags, ValueError מועלה אם מתבקש flag שאינו נתמך.

הודעות נכנסות מתקבלות אם הביטים הממוסכים ב-bit_mask תואמים בין מזהה ההודעה לערך identifier של המסנן, וה-flags המוגדרים במסנן תואמים את ההודעה הנכנסת.

אם הביט CAN.FLAG_EXT_ID מוגדר ב-flags, המסנן תואם רק מזהי CAN מורחבים (Extended). אם הביט CAN.FLAG_EXT_ID אינו מוגדר, המסנן תואם רק מזהי CAN רגילים (Standard).

כל המסננים מאוחדים בפעולת OR בתוך הבקר. העברת רשימה או tuple ריקים עבור ארגומנט המסננים פירושה שלא יתקבלו הודעות.

חלק מבקרי CAN דורשים שכל מסנן יהיה משויך ל-FIFO קליטה אחד בלבד. במקרים אלה, פריטי המסנן בארגומנט מוקצים לסירוגין (round-robin) ל-FIFO-ים הזמינים. מנהל התקן זה אינו מבחין בין FIFO-ים ב-IRQ הקליטה.

הערה

אם הקורא מעביר איטרבל עם יותר פריטים מ-CAN.FILTERS_MAX, יועלה ValueError.

הערה

אם ה-identifier או ה-bit_mask חורגים מהטווח עבור סוג ה-ID המצוין, יועלה ValueError עם הסיבה ”invalid id“.

Examples

קבלת כל ההודעות הנכנסות:

can.set_filters(None)

קבלת הודעות בעלות ערכי Standard ID 0x301 ו-0x700 בלבד:

can.set_filters(((0x301, 0x7FF, 0),
                 (0x700, 0x7FF, 0)))

קבלת הודעות בעלות ערכי Standard ID בטווח 0x300-0x3FF, וערך Extended ID 0x50700 בלבד:

can.set_filters(((0x300, 0x700, 0),
                 (0x50700, 0x1FFF_FFFF, CAN.FLAG_EXT_ID)))
FILTERS_MAX: int

ערך קבוע הקורא את המספר המרבי של מסנני קליטה הנתמכים עבור בקר חומרה זה.

שימו לב שחלק מהבקרים עשויים להטיל הגבלות חומרה מורכבות יותר על מספר המסננים בשימוש (לדוגמה, ספירה נפרדת של מסנני Standard ו-Extended ID). במקרים אלה CAN.set_filters עשוי להעלות ValueError גם כאשר מגבלת FILTERS_MAX לא נחרגה.

send(id: int, data: bytes, flags: int = 0) int | None

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

  • id הוא ערך מזהה CAN שלם.

  • data הוא אובייקט bytes (או דומה) המכיל את נתוני הודעת CAN, או מתאר Remote Transmission Request (ראו להלן).

  • flags הוא מספר שלם עם אפס או יותר מהביטים המוגדרים ב-Message Flags, המציין מאפיינים של הודעת CAN היוצאת (Extended ID, Remote Transmission Request וכו«).

אם ההודעה הוכנסה בהצלחה לתור לשידור אל הבאס, הפונקציה מחזירה מספר שלם בטווח 0 עד CAN.TX_QUEUE_LEN (לא כולל). ערך זה הוא אינדקס חוצץ השידור שבו ההודעה הוכנסה לתור לשליחה, וניתן להשתמש בו על ידי הפונקציה CAN.cancel_send ובאירועי CAN.IRQ_TX.

אם התור מלא אז השליחה תיכשל ו-None מוחזר.

השליחה יכולה גם להיכשל ולהחזיר None אם ערך ה-id שסופק בעל עדיפות שווה להודעה קיימת בתור השידור וחומרת בקר CAN אינה יכולה להבטיח שהודעות בעלות אותו ID יישלחו אל הבאס באותו סדר שבו הן נוספו לתור. כדי להכניס את ההודעה לתור בכל זאת, העבירו את ה-flag CAN.FLAG_UNORDERED בארגומנט flags. flag זה מציין שזה בסדר לשלוח הודעות בעלות אותו מזהה CAN אל הבאס בכל סדר.

אם הבקר נמצא במצב השגיאה ”Bus Off“ או מושבת, קריאה לפונקציה זו תעלה OSError.

הערה

מימוש זה ברמה נמוכה במכוון מתוכנן כך שהקורא יוכל להקים תור תוכנה של הודעות יוצאות.

חשוב

”תור השידור“ של CAN אינו תור FIFO, הוא ממוין לפי עדיפויות, ולמרות שהוא יכול להכיל עד CAN.TX_QUEUE_LEN פריטים, ייתכנו הגבלות חומרה אחרות על הודעות שניתן להכניס לתור בו-זמנית.

Remote Transmission Requests

אם הביט CAN.FLAG_RTR מוגדר בארגומנט flags אז הבקר ישלח Remote Transmission Request במקום הודעה. במקרה זה מתעלמים מתוכן הארגומנט data. הבקר ישלח בקשה שבה שדה האורך DLC שווה לאורך הארגומנט data.

Examples

ניסיון לשלוח הודעה עם מטען של שלושה בתים 0a0b0c ו-Standard ID 0x200:

can.send(0x200, b"\x0a\x0b\x0c", 0)

ניסיון לשלוח הודעה עם מטען ריק ו-Extended ID 0x180008. ציון שהבקר יכול לשלוח הודעות בעלות ID זה בכל סדר, למקרה שהודעות אחרות כבר נמצאות בתור לשליחה עם אותו ID:

can.send(0x180008, b"", can.FLAG_EXT_ID | can.FLAG_UNORDERED)

ניסיון לשלוח Remote Transmission Request באורך 8 בתים ו-Standard ID 0x555:

can.send(0x555, b" " * 8, can.FLAG_RTR)
recv(arg: list | None = None) list | None

החזרת הודעת CAN שהתקבלה על ידי הבקר, בהתאם למסננים שהוגדרו על ידי CAN.set_filters().

פונקציה זו מקבלת ארגומנט אופציונלי יחיד, אם הוא מסופק אז הוא חייב להיות list בעל לפחות 4 אלמנטים שבהם האלמנט השני הוא אובייקט memoryview המתייחס ל-bytearray או אובייקט דומה בעל קיבולת מספקת להכיל כל הודעת CAN שתתקבל (8 בתים עבור CAN Classic, 64 בתים עבור CAN FD). ה-list שסופק יוחזר כתוצאה מוצלחת, ונמנעת הקצאת זיכרון בתוך הפונקציה.

אם לא התקבלו הודעות על ידי בקר CAN, פונקציה זו מחזירה None.

הערה

יש לקרוא ל-CAN.set_filters לפני שניתן יהיה לקבל הודעות כלשהן על ידי הבקר. כדי לקבל את כל ההודעות, קראו ל-set_filters(None).

אם הודעה התקבלה על ידי בקר CAN, פונקציה זו מחזירה list בעל 4 אלמנטים:

  • אינדקס 0 הוא ה-CAN ID של ההודעה שהתקבלה, כמספר שלם.

  • אינדקס 1 הוא memoryview המספק גישה לנתוני ההודעה שהתקבלה.

    • אם arg אינו מסופק אז זהו memoryview המחזיק את הבתים שהתקבלו. memoryview זה מגובה על ידי bytearray שהוקצה לאחרונה גדול מספיק להכיל כל הודעת CAN שתתקבל. הדבר מאפשר שימוש חוזר בטוח בתוצאה כ-arg עתידי, כדי לחסוך בהקצאות זיכרון.

    • אם arg מסופק אז ה-memoryview שסופק ישונה בגודלו כך שיחזיק בדיוק את הבתים שהתקבלו. הקורא אחראי לוודא שהאובייקט המגבה את ה-memoryview יכול להחזיק הודעת CAN בכל אורך.

  • אינדקס 2 הוא מספר שלם עם אפס או יותר מהביטים המוגדרים ב-Message Flags. הוא מציין מטא-נתונים על ההודעה שהתקבלה.

  • אינדקס 3 הוא מספר שלם עם אפס או יותר מהביטים המוגדרים ב-Receive Error Flags. כל ערך שאינו אפס מציין בעיות אפשריות בעת קבלת הודעות CAN. flags אלה מאופסים בתוך הבקר בכל פעם שפונקציה זו חוזרת.

Remote Transmission Requests

אם מתקבל Remote Transmission Request אז הביט CAN.FLAG_RTR יוגדר באינדקס 2 וה-memoryview באינדקס 1 יכיל אפסים בלבד, באורך השווה לשדה DLC של הבקשה שהתקבלה.

Example
can.set_filters(None)   # receive all
while True:
    res = can.recv()
    if res:
        can_id, data, flags, errs = res
        print("Received", hex(can_id), data.hex(), hex(flags), hex(errs))
    else:
        time.sleep_ms(1)  # not a good pattern, use the irq instead!
irq(handler: Callable[[CAN], None] | None = None, trigger: int = 0, hard: bool = False) None

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

  • handler היא פונקציה שתיקרא כאשר אירוע הפסיקה מופעל. ה-handler חייב לקבל ארגומנט אחד בדיוק שהוא המופע של CAN.

  • trigger מגדיר את האירוע/ים שיכולים לחולל פסיקה. הערכים האפשריים הם מסכה של אחד או יותר מהבאים:

    • אירוע CAN.IRQ_RX מתרחש לאחר שבקר CAN קיבל לפחות הודעה אחת אל ה-RX FIFO שלו (כלומר ש-CAN.recv() תחזיר בהצלחה).

    • אירוע CAN.IRQ_TX מתרחש לאחר שבקר CAN שלח בהצלחה הודעה אל הבאס של CAN או נכשל בשליחת הודעה. ל-trigger זה יש דרישות נוספות עבור ה-handler, ראו IRQ flags לפרטים.

    • אירוע CAN.IRQ_STATE מתרחש כאשר בקר CAN עבר למצב שגיאה חמור יותר. קראו ל-CAN.state() כדי לקבל את המצב המעודכן.

  • hard אם True, נעשה שימוש בפסיקה קשיחה. הדבר מצמצם את ההשהיה בין אירוע בקר CAN לבין קריאת ה-handler. ייתכן ש-handler-ים של פסיקה קשיחה לא יוכלו להקצות זיכרון; ראו כתיבת מטפלי פסיקה.

מחזיר אובייקט irq. אם נקרא ללא ארגומנטים אז מוחזר אובייקט irq שהוגדר קודם לכן.

ראו IRQ flags לדוגמה.

cancel_send(index: int) bool

בקשה מבקר CAN לבטל שליחת הודעה אל הבאס.

הארגומנט index מזהה חוצץ שידור יחיד. הוא צריך להיות מספר שלם בטווח 0 עד CAN.TX_QUEUE_LEN (לא כולל). בדרך כלל זה יהיה ערך שהוחזר קודם לכן על ידי CAN.send().

התוצאה היא True אם הודעה הייתה ממתינה לשידור בחוצץ זה והשידור בוטל.

התוצאה היא False אחרת (או שלא הייתה הודעה ממתינה לשידור בחוצץ זה, או שהשידור כבר הצליח).

יש להשתמש באירוע ה-IRQ CAN.IRQ_TX כדי לקבוע אם הודעה אכן נשלחה או לא, אך שימו לב שקיימים מצבי תחרות (race conditions) פוטנציאליים אם שידור מבוטל ואז אותו חוצץ משמש לשליחת הודעה אחרת (במיוחד אם IRQ של בקר CAN אינו ”קשיח“).

state() int

מחזיר ערך שלם המציין את המצב הנוכחי של הבקר. הערך יהיה אחד מהערכים המוגדרים ב-States.

מצבי שגיאה בחומרה נמוכה יותר עשויים להתנקות אוטומטית אם הבאס מתאושש, אך מהמצב CAN.STATE_BUS_OFF ניתן להתאושש רק על ידי קריאה ל-CAN.restart().

get_counters(list: list | None = None, /) list

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

פריטי ה-list הם:

  • ערך TEC (Transmit Error Counter)

  • ערך REC (Receive Error Counter)

  • מספר הפעמים שהבקר נכנס למצב Warning ממצב Active.

  • מספר הפעמים שהבקר נכנס למצב Error Passive ממצב Warning.

  • מספר הפעמים שהבקר נכנס למצב Bus Off ממצב Error Passive.

  • המספר הכולל של הודעות TX ממתינות בתור החומרה.

  • המספר הכולל של הודעות RX ממתינות בתור החומרה.

  • מספר הפעמים שהתרחשה גלישת RX (overrun).

הערה

בהתאם לבקר, ערכים אלה עשויים לגלוש בחזרה ל-0 לאחר ערך מסוים.

הערה

אם בקר אינו תומך במונה מסוים, הוא יחזיר None עבור אותו אלמנט ב-list.

get_timings(list: list | None = None, /) list

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

פריטי ה-list הם:

  • ה-bitrate המדויק שבו משתמש הבקר. עשוי להשתנות מהארגומנט bitrate שהועבר אל CAN.init() עקב קוונטיזציה לעמידה באילוצי החומרה.

  • רוחב קפיצת הסנכרון מחדש (SJW) ביחידות של קוונטות זמן עבור ביטים נומינליים. בעל אותה משמעות כמו הפרמטר sjw של CAN.init().

  • מיקום נקודת הדגימה ביחידות של קוונטות זמן עבור ביטים נומינליים. בעל אותה משמעות כמו הפרמטר tseg1 של CAN.init().

  • מיקום נקודת השידור ביחידות של קוונטות זמן עבור ביטים נומינליים. בעל אותה משמעות כמו הפרמטר tseg2 של CAN.init().

  • מידע תזמון של CAN FD. None עבור בקרים שאינם תומכים ב-CAN FD, או אם CAN FD לא אותחל. אחרת, list מקונן של ארבעה אלמנטים המתאימים לפריטים שלעיל אך החלים על תכונת CAN FD BRS.

  • מידע תזמון אופציונלי הספציפי לבקר. בהתאם לבקר זה יהיה None אם הבקר אינו מדווח על כך, או שזה יהיה list באורך קבוע שאלמנטיו ספציפיים לבקר חומרה מסוים.

הערה

אם CAN.init() לא נקראה אז פונקציה זו עדיין מחזירה תוצאה, אך התוצאה תלויה בפנים הבקר ועשויה לא להיות מדויקת.

restart() None

גורם לבקר לצאת מ-STATE_BUS_OFF מבלי לנקות מצב פנימי אחר. כמו כן מנקה חלק ממוני השגיאות (תמיד את מספר הפעמים שכל מצב שגיאה נכנס אליו, ואפשר גם TEC ו-REC בהתאם לבקר).

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

שימו לב שפונקציה זו עשויה לגרום או לא לגרום לבקר לצאת ממצב ”Error Passive“, בהתאם לכך אם חומרת הבקר מאפסת את TEC ו-REC או לא.

deinit() None

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

לא נקראות פסיקות IRQ_TX או IRQ_RX בתגובה לקריאה לפונקציה זו.

ראו גם CAN.restart().

Constants

TX_QUEUE_LEN: int

המספר המרבי של הודעות CAN שניתן להכניס לתור הודעות החומרה היוצא של הבקר. ”אינדקסי חוצץ השידור“ המשמשים את CAN.send(), CAN.cancel_send() ו-IRQ flags יהיו בטווח זה.

Modes

ערכים אלה מייצגים מצבי פעולה של הבקר, כפי שמועברים אל CAN.init(). ייתכן שלא כל הבקרים תומכים בכל המצבים.

שינוי המצב של בקר פועל מחייב קריאה ל-CAN.deinit() ולאחר מכן קריאה ל-CAN.init() שוב עם המצב החדש.

MODE_NORMAL: int

הבקר פעיל כצומת רשת CAN רגיל (יאשר הודעות תקפות ועשוי לשדר שגיאות בהתאם ל-State הנוכחי שלו).

MODE_SLEEP: int

בקר CAN ישן במצב צריכת חשמל נמוכה. בהתאם לבקר, ייתכן שזה יתמוך בהערת הבקר ובמעבר ל-CAN.MODE_NORMAL אם מתקבלת תעבורת CAN.

MODE_LOOPBACK: int

מצב בדיקה. בקר CAN עדיין מחובר לבאס החיצוני, אך גם יקבל את ההודעות ששידר בעצמו ויתעלם משגיאות ACK כלשהן.

MODE_SILENT: int

בקר CAN מקבל הודעות אך אינו מקיים אינטראקציה עם הבאס של CAN (כולל שליחת ACK-ים, שגיאות וכו«).

MODE_SILENT_LOOPBACK: int

מצב בדיקה שאינו דורש כלל חיבור של מקלט-משדר CAN. בקר CAN מקבל את ההודעות ששידר בעצמו מבלי לקיים כלל אינטראקציה עם הבאס של CAN. הפינים TX ו-RX של CAN נשארים במצב חוסר פעילות.

States

ערכים אלה מוחזרים על ידי CAN.state() ומשקפים את מצב השגיאה של בקר CAN:

STATE_STOPPED: int

הבקר לא אותחל.

STATE_ACTIVE: int

הבקר פעיל ומוני השגיאות TEC ו-REC שניהם מתחת לסף האזהרה של 96. ראו CAN.get_counters().

STATE_WARNING: int

הבקר פעיל אך לפחות אחד ממוני השגיאות TEC ו-REC נמצא בין 96 ל-127. ראו CAN.get_counters().

STATE_PASSIVE: int

הבקר נמצא במצב ”Error Passive“ כלומר הוא אינו משדר עוד שגיאות אקטיביות אל הבאס, אך הוא פונקציונלי במובנים אחרים. למצב זה נכנסים כאשר לפחות אחד ממוני השגיאות TEC ו-REC הוא 128 או יותר, אך TEC קטן מ-255. ראו CAN.get_counters().

STATE_BUS_OFF: int

הבקר נמצא במצב Bus-Off, כלומר מונה השגיאות TEC גדול מ-255. בקר CAN לא יקיים אינטראקציה עם הבאס במצב זה, ויש להפעילו מחדש באמצעות CAN.restart() כדי להמשיך.

Message Flags

ערכים אלה מייצגים מטא-נתונים על הודעת CAN. הפונקציות CAN.send(), CAN.recv() ו-CAN.set_filters() מקבלות או מחזירות ערך שלם המורכב מאפס או יותר מ-flags אלה המאוחדים בפעולת OR ברמת הסיביות.

FLAG_RTR: int

מציין שהודעה היא remote transmission request.

FLAG_EXT_ID: int

אם מוגדר, מציין שמזהה הודעה הוא מורחב (Extended, 29 ביט). אם אינו מוגדר, מציין שמזהה הודעה הוא רגיל (Standard, 11 ביט).

FLAG_UNORDERED: int

אם מוגדר בארגומנט ה-flags של CAN.send(), מציין שזה בסדר אם הודעות בעלות אותו מזהה CAN נשלחות בכל סדר אל הבאס.

אחרת ניסיון להכניס לתור מספר הודעות בעלות אותו ID עלול לגרום לכישלון של CAN.send() אם חומרת הבקר אינה יכולה לאכוף סדר.

flag זה לעולם אינו מוגדר בהודעות שהתקבלו, ומתעלמים ממנו ב-CAN.set_filters().

Receive Error Flags

תוצאת CAN.recv() כוללת ערך שלם המורכב מאפס או יותר מ-flags אלה המאוחדים בפעולת OR ברמת הסיביות. אם מוגדרים, flags אלה מציינים בעיות כלליות אפשריות בקבלת הודעות CAN.

RECV_ERR_FULL: int

ה-FIFO החומרתי שבו התקבלה הודעה זו מלא, והודעות נכנסות נוספות עלולות לאבד.

RECV_ERR_OVERRUN: int

ה-FIFO החומרתי שבו התקבלה הודעה זו מלא, והודעה נכנסת אחת או יותר אבדה.

IRQ values

IRQ_RX: int

העבירו אל הארגומנט trigger של irq() כדי להפעיל את ה-handler בכל פעם שבקר CAN קיבל הודעה שלמה אל ה-RX FIFO. בתוך ה-handler, קראו את ההודעה באמצעות recv().

IRQ_TX: int

העבירו אל הארגומנט trigger של irq() כדי להפעיל את ה-handler בכל פעם שבקר CAN מסיים ניסיון שידור (הצלחה או כישלון). בתוך ה-handler, השתמשו בביטים הנוספים שלהלן כדי לשחזר איזו תיבת דואר (mailbox) הושלמה והאם היא נכשלה – ראו IRQ flags.

IRQ_STATE: int

העבירו אל הארגומנט trigger של irq() כדי להפעיל את ה-handler בכל פעם שהבקר עובר בין ערכי ה-STATE_* (active / warning / passive / bus-off). השתמשו ב-state() בתוך ה-handler כדי לקרוא את המצב החדש.

IRQ_TX_FAILED: int

flag סטטוס שעשוי להיות מוגדר ב-irq().flags() כאשר אירוע IRQ_TX מופעל. מציין שניסיון השידור נכשל (בדרך כלל משום ש-cancel_send() נקראה, או שהבקר נכנס למצב שגיאה).

IRQ_TX_IDX_SHIFT: int

מיקום הביט של שדה אינדקס תיבת-דואר-השידור בתוך ערך ה-irq().flags() במהלך אירוע IRQ_TX. אינדקס תיבת הדואר מחולץ כ-(flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK.

IRQ_TX_IDX_MASK: int

מסכת ביטים של שדה אינדקס תיבת-דואר-השידור בתוך ערך ה-irq().flags() במהלך אירוע IRQ_TX. האינדקס המחולץ תואם את המספר השלם שהוחזר על ידי קריאת send() המתאימה (int בטווח 0 עד TX_QUEUE_LEN).

IRQ flags

קריאה ל-CAN.irq() רושמת handler של פסיקה עם אחד או יותר מה-triggers CAN.IRQ_RX, CAN.IRQ_TX ו-CAN.IRQ_STATE.

הפונקציה מחזירה אובייקט IRQ, וקריאה לפונקציה flags() על אובייקט זה מחזירה מספר שלם המציין איזה אירוע/י trigger חוללו את הפסיקה. handler של CAN IRQ צריך לקרוא לפונקציה flags() שוב ושוב עד שהיא מחזירה 0.

כאשר הפונקציה flags() חוזרת עם הביט CAN.IRQ_TX מוגדר, ה-handler יכול גם לבדוק את ביטי ה-flag הבאים בתוצאה לקבלת מידע נוסף על אירוע ה-TX:

  • הביט CAN.IRQ_TX_FAILED מוגדר אם השידור נכשל. בדרך כלל זה יקרה רק אם CAN.cancel_send() נקראה, אם כי זה עשוי לקרות גם אם הבקר נכנס למצב שגיאה.

  • CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFT הוא אזור ממוסך-ביטים של ערך ה-flags המחזיק את אינדקס חוצץ השידור שחולל את האירוע. זה יהיה מספר שלם בטווח 0 עד CAN.TX_QUEUE_LEN (לא כולל), ויתאים לתוצאת קריאה קודמת ל-CAN.send().

IRQ_TX Example

from machine import CAN

def irq_send(can):
    while flags := can.irq().flags():
        if flags & can.IRQ_TX:
            idx = (flags >> can.IRQ_TX_IDX_SHIFT) & can.IRQ_TX_IDX_MASK
            success = not (flags & can.IRQ_TX_FAILED)
            print("irq_send", idx, success)

can = CAN(1, 500_000)
can.irq(irq_send, trigger=can.IRQ_TX, hard=True)

חשוב

אם ה-trigger CAN.IRQ_TX מוגדר אז ה-handler חייב לקרוא ל-flags() שוב ושוב עד שהיא מחזירה 0, כפי שמוצג בדוגמה זו. אחרת, ייתכן שפסיקות CAN לא יאופשרו מחדש כראוי.