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 יישלחו אל הבאס באותו סדר שבו הן נוספו לתור. כדי להכניס את ההודעה לתור בכל זאת, העבירו את ה-flagCAN.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 כלשהן.
States¶
ערכים אלה מוחזרים על ידי
CAN.state()ומשקפים את מצב השגיאה של בקר CAN:- 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_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.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 לא יאופשרו מחדש כראוי.