الفئة CAN -- ناقل اتصالات شبكة منطقة التحكم (controller area network)

يطبّق CAN الدعم لكل من CAN الكلاسيكي (bxCAN، المستخدم في OpenMV Cam M4 وM7) وCAN FD (FDCAN، المستخدم في OpenMV Cam H7 وH7 Plus وPure Thermal). على المستوى الفيزيائي يتكوّن ناقل CAN من خطين، RX وTX. لتوصيل OpenMV Cam بناقل CAN يجب عليك استخدام جهاز إرسال واستقبال CAN لتحويل إشارات منطق CAN من وحدة التحكم الدقيقة (MCU) إلى مستويات الجهد الصحيحة على الناقل.

CAN الكلاسيكي في وضع الاسترجاع الحلقي (بدون جهاز إرسال واستقبال):

from pyb import CAN

can = CAN(1, CAN.LOOPBACK)

# Accept messages with id 123, 124, 125 or 126.
can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))

can.send("message!", 123)   # send a message with id 123
can.recv(0)                 # receive a message on FIFO 0

CAN FD مع تمكين جميع الميزات الاختيارية (إطار FD، تبديل معدل البت، معرّفات الإطار الممتدة؛ مرحلة تحكيم بسرعة 500 kbit/s، مرحلة بيانات بسرعة 1 Mbit/s):

from pyb import CAN

can = CAN(
    1,
    CAN.NORMAL,
    baudrate=500_000,
    brs_baudrate=1_000_000,
    sample_point=80,
)

# Accept any id in the range 0xFFF0 .. 0xFFFF.
can.setfilter(0, CAN.RANGE, 0, (0xFFF0, 0xFFFF))

can.send(b"a" * 64, 0xFFFF, fdf=True, brs=True, extframe=True)
can.recv(0)

دوال وحدة CAN التالية ووسائطها متاحة لكل من وحدتي تحكم CAN الكلاسيكية وFD، ما لم يُذكر خلاف ذلك.

المُنشِئات

class pyb.CAN(bus: int | str, *args, **kwargs)

ينشئ كائن CAN على bus المعطى (فهرس طرفية صحيح، مثلاً 1 لـ CAN1، و 2 لـ CAN2). بدون معاملات إضافية يُنشأ الكائن لكن لا تتم تهيئته (فيحتفظ بإعدادات الناقل السابقة، إن وُجدت)؛ أما إذا أُعطيت وسائط إضافية فتتم تهيئة الناقل. انظر CAN.init() للاطلاع على المعاملات المتاحة.

CAN(2) موصول بدبابيس الترويسة نفسها على كل OpenMV Cam يُتيح pyb.CAN (M4 / M7 / H7 / H7 Plus / Pure Thermal):

الإشارة

دبوس الترويسة

ملاحظات

RX

P3

TX

P2

توفّر طرفية CAN إشارات على مستوى المنطق فقط؛ يلزم جهاز إرسال واستقبال CAN خارجي لقيادة ناقل CAN حقيقي.

pyb.CAN غير متاح على OpenMV Cam N6.

الطرائق

init(mode: int, prescaler: int = 100, *, sjw: int = 1, bs1: int = 6, bs2: int = 8, auto_restart: bool = False, baudrate: int = 0, sample_point: int = 75, num_filter_banks: int = 14, brs_sjw: int = 1, brs_bs1: int = 8, brs_bs2: int = 3, brs_baudrate: int = 0, brs_sample_point: int = 75) None

تهيئة ناقل CAN بالمعاملات المعطاة:

  • mode هو أحد التالي: NORMAL، LOOPBACK، SILENT، SILENT_LOOPBACK

  • prescaler هو القيمة التي يُقسَّم بها ساعة دخل CAN لتوليد كمّات زمن البت الاسمي. يمكن أن يكون المقسّم المسبق قيمة بين 1 و1024 شاملة لـ CAN الكلاسيكي، وبين 1 و512 شاملة لـ CAN FD.

  • sjw هو عرض قفزة إعادة التزامن بوحدات كمّات الزمن للبتات الاسمية؛ ويمكن أن يكون قيمة بين 1 و4 شاملة لـ CAN الكلاسيكي، وبين 1 و128 شاملة لـ CAN FD.

  • bs1 يحدّد موقع نقطة أخذ العينة بوحدات كمّات الزمن للبتات الاسمية؛ ويمكن أن يكون قيمة بين 1 و16 شاملة لـ CAN الكلاسيكي، وبين 2 و256 شاملة لـ CAN FD.

  • bs2 يحدّد موقع نقطة الإرسال بوحدات كمّات الزمن للبتات الاسمية؛ ويمكن أن يكون قيمة بين 1 و8 شاملة لـ CAN الكلاسيكي، وبين 2 و128 شاملة لـ CAN FD.

  • auto_restart يحدّد ما إذا كانت وحدة التحكم ستحاول تلقائياً إعادة تشغيل الاتصالات بعد دخولها حالة الانفصال عن الناقل (bus-off)؛ فإذا كان هذا معطّلاً يمكن استخدام restart() لمغادرة حالة الانفصال عن الناقل

  • baudrate إذا وُفِّر معدل باود غير 0، فستحاول هذه الدالة حساب زمن البت الاسمي لـ CAN تلقائياً (متجاوزةً prescaler وbs1 وbs2) بما يحقّق كلاً من baudrate (ضمن .1%) ونقطة العينة المرغوبة sample_point (لأقرب 1%). للتحكم الأدق في توقيت CAN، اضبط معاملات prescaler وbs1 وbs2 مباشرة.

  • sample_point يحدّد موضع أخذ عينة البت بالنسبة إلى زمن البت الاسمي الكامل، معبَّراً عنه كنسبة مئوية صحيحة من زمن البت الاسمي. القيمة الافتراضية لـ sample_point هي 75%. يُتجاهَل هذا المعامل ما لم يُضبَط baudrate.

  • num_filter_banks لـ CAN الكلاسيكي، هذا هو عدد البنوك التي ستُخصَّص لـ CAN(1)، وتُخصَّص بقية البنوك الـ 28 لـ CAN(2).

المعاملات المتبقية موجودة فقط على اللوحات الداعمة لـ CAN FD، وهي تُهيّئ ميزة تبديل معدل البت الاختيارية في CAN FD (BRS):

  • brs_prescaler هو القيمة التي يُقسَّم بها ساعة دخل CAN FD لتوليد كمّات زمن بت البيانات. يمكن أن يكون المقسّم المسبق قيمة بين 1 و32 شاملة.

  • brs_sjw هو عرض قفزة إعادة التزامن بوحدات كمّات الزمن لبتات البيانات؛ ويمكن أن يكون قيمة بين 1 و16 شاملة

  • brs_bs1 يحدّد موقع نقطة أخذ العينة بوحدات كمّات الزمن لبتات البيانات؛ ويمكن أن يكون قيمة بين 1 و32 شاملة

  • brs_bs2 يحدّد موقع نقطة الإرسال بوحدات كمّات الزمن لبتات البيانات؛ ويمكن أن يكون قيمة بين 1 و16 شاملة

  • brs_baudrate إذا وُفِّر معدل باود غير 0، فستحاول هذه الدالة حساب زمن بت بيانات CAN تلقائياً (متجاوزةً brs_prescaler وbrs_bs1 وbrs_bs2) بما يحقّق كلاً من brs_baudrate (ضمن .1%) ونقطة العينة المرغوبة brs_sample_point (لأقرب 1%). للتحكم الأدق في توقيت BRS، اضبط معاملات brs_prescaler وbrs_bs1 وbrs_bs2 مباشرة.

  • brs_sample_point يحدّد موضع أخذ عينة البت بالنسبة إلى زمن البت الاسمي الكامل، معبَّراً عنه كنسبة مئوية صحيحة من زمن البت الاسمي. القيمة الافتراضية لـ brs_sample_point هي 75%. يُتجاهَل هذا المعامل ما لم يُضبَط brs_baudrate.

كمّة الزمن tq هي الوحدة الأساسية للزمن في ناقل CAN. tq هي قيمة المقسّم المسبق لـ CAN مقسومة على PCLK1 (تردد ناقل الطرفيات الداخلي 1)؛ انظر pyb.freq() لتحديد PCLK1.

يتألف البت الواحد من قطعة التزامن، التي تساوي دائماً 1 tq. ثم تليها قطعة البت 1، ثم قطعة البت 2. تقع نقطة أخذ العينة بعد انتهاء قطعة البت 1. وتقع نقطة الإرسال بعد انتهاء قطعة البت 2. ويكون معدل الباود 1/bittime، حيث bittime هو 1 + BS1 + BS2 مضروباً في كمّة الزمن tq.

على سبيل المثال، على OpenMV Cam H7 (PCLK1 = 100 MHz)، يمكن تهيئة CAN بسرعة 250 kbps بنقطة عينة 75% على النحو التالي prescaler=25, sjw=1, bs1=11, bs2=4: tq = 25 / 100 MHz = 250 ns، و bittime = (1 + 11 + 4) × 250 ns = 4 µs، ونقطة العينة = (1 + 11) / 16 = 75%، ويكون معدل الباود 1 / 4 µs = 250 kHz.

انظر قسم bxCAN / FDCAN في دليل مرجع STM32 الخاص بوحدة التحكم الدقيقة (MCU) في OpenMV Cam لمزيد من التفاصيل.

deinit() None

إيقاف ناقل CAN.

restart() None

فرض إعادة تشغيل برمجية لوحدة تحكم CAN دون إعادة ضبط إعداداتها.

إذا دخلت وحدة التحكم حالة الانفصال عن الناقل (bus-off) فلن تشارك بعد ذلك في نشاط الناقل. وإذا لم تكن وحدة التحكم مهيّأة لإعادة التشغيل تلقائياً (انظر init()) فيمكن استخدام هذه الطريقة لإطلاق إعادة تشغيل، وستتبع وحدة التحكم بروتوكول CAN لمغادرة حالة الانفصال عن الناقل والانتقال إلى حالة الخطأ النشط (error active).

state() int

إرجاع حالة وحدة التحكم. يمكن أن تكون القيمة المُرجَعة إحدى التالي:

  • CAN.STOPPED -- وحدة التحكم متوقفة تماماً وأُعيد ضبطها؛

  • CAN.ERROR_ACTIVE -- وحدة التحكم قيد التشغيل وفي حالة الخطأ النشط (كلا TEC وREC أقل من 96)؛

  • CAN.ERROR_WARNING -- وحدة التحكم قيد التشغيل وفي حالة تحذير الخطأ (واحد على الأقل من TEC أو REC يساوي 96 أو أكثر)؛

  • CAN.ERROR_PASSIVE -- وحدة التحكم قيد التشغيل وفي حالة الخطأ السلبي (واحد على الأقل من TEC أو REC يساوي 128 أو أكثر)؛

  • CAN.BUS_OFF -- وحدة التحكم قيد التشغيل لكنها لا تشارك في نشاط الناقل (تجاوز TEC القيمة 255).

info(list: list | None = None) list

الحصول على معلومات حول حالات الخطأ في وحدة التحكم ومخازن TX وRX المؤقتة. إذا أُعطي list فينبغي أن يكون كائن قائمة بثمانية مدخلات على الأقل، وستُملأ بالمعلومات. وإلا فستُنشأ قائمة جديدة وتُملأ. في كلتا الحالتين تكون القيمة المُرجَعة من الطريقة هي القائمة المملوءة.

القيم في القائمة هي:

  • قيمة TEC

  • قيمة REC

  • عدد المرات التي دخلت فيها وحدة التحكم حالة تحذير الخطأ (تلتف إلى 0 بعد 65535)

  • عدد المرات التي دخلت فيها وحدة التحكم حالة الخطأ السلبي (تلتف إلى 0 بعد 65535)

  • عدد المرات التي دخلت فيها وحدة التحكم حالة الانفصال عن الناقل (تلتف إلى 0 بعد 65535)

  • عدد رسائل TX المعلّقة

  • عدد رسائل RX المعلّقة على fifo 0

  • عدد رسائل RX المعلّقة على fifo 1

setfilter(bank: int, mode: int, fifo: int, params: Tuple[int, ...], *, rtr: Tuple[bool, ...] | None = None, extframe: bool = False) None

تهيئة بنك مرشّح:

  • bank هو بنك مرشّح وحدة تحكم CAN الكلاسيكي، أو فهرس مرشّح CAN FD، المراد تهيئته.

  • mode هو الوضع الذي ينبغي أن يعمل به المرشّح، انظر الجداول أدناه.

  • fifo هو الـ fifo (0 أو 1) الذي ينبغي أن تُخزَّن فيه الرسالة، إن قبلها هذا المرشّح.

  • params هو مصفوفة من القيم تعرّف المرشّح. تعتمد محتويات المصفوفة على الوسيط mode.

محتويات مصفوفة params لوحدات تحكم CAN الكلاسيكي (OpenMV Cam M4 / M7):

mode

محتويات params

CAN.LIST16

أربعة معرّفات بطول 16 بت سيتم قبولها.

CAN.LIST32

معرّفان بطول 32 بت سيتم قبولهما.

CAN.MASK16

زوجان من معرّف/قناع بطول 16 بت، مثلاً (1, 3, 4, 4). يقبل الزوج الأول (1, 3) جميع المعرّفات التي يكون فيها البت 0 = 1 والبت 1 = 0؛ ويقبل الزوج الثاني (4, 4) جميع المعرّفات التي يكون فيها البت 2 = 1.

CAN.MASK32

زوج واحد من معرّف/قناع بطول 32 بت (وهو خلاف ذلك مماثل لـ CAN.MASK16).

محتويات مصفوفة params لوحدات تحكم CAN FD (OpenMV Cam H7 / H7 Plus / Pure Thermal):

mode

محتويات params

CAN.RANGE

معرّفان يشكّلان نطاقاً من المعرّفات المقبولة.

CAN.DUAL

معرّفان سيتم قبولهما (مثلاً (1, 2)).

CAN.MASK

زوج واحد من (id, mask) (مثلاً (0x111, 0x7FF)).

  • rtr لوحدات تحكم CAN الكلاسيكي، هذه مصفوفة من القيم المنطقية تحدّد ما إذا كان ينبغي للمرشّح قبول رسالة طلب إرسال عن بُعد. إذا لم يُعطَ هذا الوسيط فإنه يكون False افتراضياً لجميع المدخلات. يعتمد الطول على mode:

    mode

    len(rtr)

    ملاحظات

    CAN.LIST16

    4

    CAN.LIST32

    2

    CAN.MASK16

    2

    CAN.MASK32

    1

    بالنسبة لـ CAN FD يُتجاهَل هذا الوسيط.

  • extframe إذا كان True فسيكون للإطار معرّف ممتد (29 بت)، وإلا فيُستخدَم معرّف قياسي (11 بت).

clearfilter(bank: int, extframe: bool = False) None

مسح بنك مرشّح وتعطيله:

  • bank هو بنك مرشّح وحدة تحكم CAN الكلاسيكي، أو فهرس مرشّح CAN FD، المراد مسحه.

  • extframe لوحدات تحكم CAN FD، إذا كان True، يُمسَح مرشّح ممتد (مهيّأ بـ extframe=True)، وإلا فيُمسَح معرّف قياسي (مهيّأ بـ extframe=False).

any(fifo: int) bool

إرجاع True إذا كانت هناك أي رسالة منتظرة على FIFO، وإلا False.

recv(fifo: int, list: list | None = None, *, timeout: int = 5000) list

استقبال البيانات على الناقل:

  • fifo عدد صحيح، وهو الـ FIFO المراد الاستقبال عليه

  • list هو كائن قائمة اختياري يُستخدَم كقيمة مُرجَعة

  • timeout هو المهلة بالميلي ثانية للانتظار للاستقبال.

القيمة المُرجَعة: قائمة تحتوي على خمس قيم.

  • معرّف الرسالة.

  • قيمة منطقية تشير إلى ما إذا كان معرّف الرسالة قياسياً أم ممتداً.

  • قيمة منطقية تشير إلى ما إذا كانت الرسالة رسالة RTR.

  • قيمة FMI (فهرس مطابقة المرشّح).

  • مصفوفة تحتوي على البيانات.

إذا كان list يساوي None فستُخصَّص قائمة جديدة، إضافةً إلى كائن bytes جديد لاحتواء البيانات (كالعنصر الخامس في القائمة).

إذا لم يكن list يساوي None فينبغي أن يكون كائن قائمة بخمسة عناصر على الأقل. وينبغي أن يكون العنصر الخامس كائن memoryview مُنشأً من إما bytearray أو مصفوفة من النوع 'B' أو 'b'، ويجب أن تتسع هذه المصفوفة لـ 8 بايتات على الأقل. عندئذٍ تُملأ القائمة بالقيم المُرجَعة الأربع الأولى أعلاه، ويُعاد تحجيم كائن memoryview في مكانه إلى حجم البيانات ويُملأ بتلك البيانات. ويمكن إعادة استخدام كائني القائمة وmemoryview نفسيهما في الاستدعاءات اللاحقة لهذه الطريقة، مما يوفّر وسيلة لاستقبال البيانات دون استخدام الكومة (heap). على سبيل المثال:

buf = bytearray(8)
lst = [0, 0, 0, 0, memoryview(buf)]
# No heap memory is allocated in the following call
can.recv(0, lst)
send(data: int | bytes | bytearray, id: int, *, timeout: int = 0, rtr: bool = False, extframe: bool = False, fdf: bool = False, brs: bool = False) None

إرسال رسالة على الناقل:

  • data هي البيانات المراد إرسالها (عدد صحيح للإرسال، أو كائن مخزن مؤقت).

  • id هو معرّف الرسالة المراد إرسالها.

  • timeout هو المهلة بالميلي ثانية للانتظار للإرسال.

  • rtr قيمة منطقية تحدّد ما إذا كانت الرسالة سترسَل كطلب إرسال عن بُعد. إذا كان rtr يساوي True فلن يُستخدَم سوى طول data لملء خانة DLC في الإطار؛ أما البايتات الفعلية في data فلا تُستخدَم.

  • extframe إذا كان True فسيكون للإطار معرّف ممتد (29 بت)، وإلا فيُستخدَم معرّف قياسي (11 بت).

  • fdf لوحدات تحكم CAN FD، إذا ضُبِط على True، فسيكون للإطار تنسيق إطار FD، الذي يدعم حمولات بيانات حتى 64 بايت.

  • brs لوحدات تحكم CAN FD، إذا ضُبِط على True، فسيُمكَّن وضع تبديل معدل البت، حيث تُرسَل مرحلة البيانات بمعدل بت مختلف. انظر CAN.init() لمعاملات تهيئة توقيت بت البيانات.

إذا كانت المهلة 0 فستوضَع الرسالة في أحد ثلاثة مخازن أجهزة مؤقتة وتعود الطريقة فوراً. وإذا كانت المخازن الثلاثة جميعها قيد الاستخدام يُطرَح استثناء. وإذا لم تكن المهلة 0، فإن الطريقة تنتظر حتى تُرسَل الرسالة. وإذا تعذّر إرسال الرسالة ضمن الوقت المحدّد يُطرَح استثناء.

القيمة المُرجَعة: None.

rxcallback(fifo: int, fun: Callable[[CAN, int], None] | None) None

تسجيل دالة لاستدعائها عندما تُقبَل رسالة في FIFO فارغ:

  • fifo هو الـ FIFO المستقبِل.

  • fun هي الدالة المراد استدعاؤها عندما يصبح الـ FIFO غير فارغ.

تأخذ دالة رد النداء وسيطين: الأول هو كائن CAN نفسه؛ والثاني عدد صحيح يشير إلى سبب رد النداء:

السبب

المعنى

0

قُبِلَت رسالة في FIFO فارغ.

1

الـ FIFO ممتلئ.

2

فُقِدَت رسالة بسبب امتلاء FIFO.

مثال على استخدام rxcallback:

def cb0(bus, reason):
  print('cb0')
  if reason == 0:
      print('pending')
  if reason == 1:
      print('full')
  if reason == 2:
      print('overflow')

can = CAN(1, CAN.LOOPBACK)
can.rxcallback(0, cb0)

الثوابت

ثوابت وضع الناقل (الوسيط mode في init()):

NORMAL: int

تشارك وحدة التحكم بشكل طبيعي على الناقل -- ترسل إطاراتها الخاصة وتُقرّ باستلام الإطارات الصالحة.

LOOPBACK: int

وضع الاسترجاع الحلقي الداخلي: تُفصَل وحدة التحكم عن الدبابيس وتوجّه الإطارات المرسَلة مباشرةً إلى مسار الاستقبال. مفيد للاختبارات الذاتية دون جهاز إرسال واستقبال.

SILENT: int

وضع الاستماع فقط: تستقبل وحدة التحكم الإطارات لكنها لا تقود الناقل أبداً (لا ACK ولا إرسال). مفيد للتنصّت على الناقل.

SILENT_LOOPBACK: int

يجمع بين SILENT و LOOPBACK: لا نشاط على الدبابيس ولا إقرارات، مع استرجاع حلقي داخلي لـ TX إلى RX.

ثوابت حالة وحدة التحكم (المُرجَعة من state()):

STOPPED: int

وحدة التحكم متوقفة تماماً وأُعيد ضبطها.

ERROR_ACTIVE: int

وحدة التحكم قيد التشغيل وفي حالة الخطأ النشط (كلا TEC وREC أقل من 96).

ERROR_WARNING: int

وحدة التحكم قيد التشغيل وفي حالة تحذير الخطأ (واحد على الأقل من TEC أو REC يساوي 96 أو أكثر).

ERROR_PASSIVE: int

وحدة التحكم قيد التشغيل وفي حالة الخطأ السلبي (واحد على الأقل من TEC أو REC يساوي 128 أو أكثر).

BUS_OFF: int

وحدة التحكم قيد التشغيل لكنها لا تشارك في نشاط الناقل (تجاوز TEC القيمة 255).

أوضاع مرشّح CAN الكلاسيكي (الوسيط mode في setfilter() على OpenMV Cam M4 / M7):

LIST16: int

تحمل مصفوفة المرشّح params أربعة معرّفات بطول 16 بت سيتم قبولها.

LIST32: int

تحمل مصفوفة المرشّح params معرّفين بطول 32 بت سيتم قبولهما.

MASK16: int

تحمل مصفوفة المرشّح params زوجين من (id, mask) بطول 16 بت.

MASK32: int

تحمل مصفوفة المرشّح params زوجاً واحداً من (id, mask) بطول 32 بت.

أوضاع مرشّح CAN FD (الوسيط mode في setfilter() على OpenMV Cam H7 / H7 Plus / Pure Thermal):

RANGE: int

تحمل مصفوفة المرشّح params معرّفين يشكّلان نطاقاً من المعرّفات المقبولة.

DUAL: int

تحمل مصفوفة المرشّح params معرّفين محدّدين للقبول.

MASK: int

تحمل مصفوفة المرشّح params زوجاً واحداً من (id, mask).