คลาส CAN -- โปรโตคอล Controller Area Network

CAN เป็นโปรโตคอลอนุกรมแบบสองสายที่ใช้สำหรับการส่งข้อความแบบเรียลไทม์ที่เชื่อถือได้ระหว่างโหนดหนึ่งโหนดขึ้นไปที่เชื่อมต่อกับบัสร่วมกัน CAN 2.0 ได้รับการกำหนดมาตรฐานใน ISO-11898 และปัจจุบันเป็นที่รู้จักในชื่อ CAN Classic

นอกจากนี้ยังมีโปรโตคอลใหม่กว่าที่เข้ากันได้แบบย้อนหลังชื่อว่า CAN FD (CAN with Flexible Data-Rate) ไดรเวอร์ machine.CAN ในปัจจุบันยังไม่รองรับฟีเจอร์ CAN FD หากต้องการ CAN FD ให้ใช้ pyb.CAN บน STM32

การรองรับ CAN ต้องการคอนโทรลเลอร์ (มักเป็นอุปกรณ์ต่อพ่วงภายในไมโครคอนโทรลเลอร์) และทรานซีฟเวอร์ภายนอกสำหรับปรับระดับสัญญาณลงบัส CAN

รองรับบน OpenMV Cam STM32 (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6 รวมถึงรุ่น Arduino ที่มีการต่อทรานซีฟเวอร์) ยังไม่รองรับบน OpenMV Cam RT1062 (พอร์ต mimxrt) หรือ OpenMV Cam AE3 (พอร์ต alif)

อินเทอร์เฟซ machine.CAN เป็นอินเทอร์เฟซการส่งข้อความ CAN ระดับต่ำพื้นฐานที่แยก CAN คอนโทรลเลอร์ออกเป็นคิวลำดับความสำคัญขาออกสำหรับส่งข้อความ คิวขาเข้าสำหรับรับข้อความ และกลไกสำหรับรายงานข้อผิดพลาด

Note

โมดูล can และ aiocan ของ micropython-lib ที่วางแผนไว้จะเป็นวิธีที่แนะนำสำหรับการใช้ CAN กับ MicroPython

คอนสตรักเตอร์

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

สร้างออบเจ็กต์ CAN คอนโทรลเลอร์ด้วย id ที่กำหนด:

  • id ระบุออบเจ็กต์ CAN คอนโทรลเลอร์เฉพาะ โดยขึ้นอยู่กับบอร์ดและพอร์ต

  • อาร์กิวเมนต์อื่น ๆ ทั้งหมดจะถูกส่งไปยัง CAN.init() ต้องระบุอาร์กิวเมนต์อย่างน้อยหนึ่งตัว (bitrate)

เวอร์ชันในอนาคตของคลาสนี้อาจยอมรับอาร์กิวเมนต์คีย์เวิร์ดเฉพาะพอร์ตที่นี่ซึ่งกำหนดค่าฮาร์ดแวร์ด้วย ปัจจุบันยังไม่มีการนำอาร์กิวเมนต์คีย์เวิร์ดดังกล่าวมาใช้

ตัวอย่าง

สร้างและเริ่มต้น CAN คอนโทรลเลอร์ 1 ด้วยบิตเรต 500kbps:

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

เมธอด

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 คือหนึ่งในค่าที่แสดงภายใต้ โหมด ซึ่งระบุโหมดการทำงานที่ต้องการ ค่าเริ่มต้นคือการทำงาน "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 หากระบุทั้งหมดนี้

Note

ฮาร์ดแวร์คอนโทรลเลอร์แต่ละตัวอาจมีข้อจำกัดเพิ่มเติมเกี่ยวกับค่าที่ถูกต้องสำหรับพารามิเตอร์เหล่านี้ และจะเรียก ValueError หากค่าที่กำหนดไม่ได้รับการสนับสนุน

Note

ฮาร์ดแวร์คอนโทรลเลอร์เฉพาะอาจยอมรับพารามิเตอร์คีย์เวิร์ดเสริมสำหรับฟีเจอร์เฉพาะฮาร์ดแวร์เช่นการโอเวอร์แซมปลิง

set_filters(filters: list | tuple | None) None

ตั้งค่าตัวกรองรับในคอนโทรลเลอร์ CAN filters สามารถเป็น:

  • None เพื่อรับข้อความขาเข้าทั้งหมด หรือ

  • [] หรือ () เพื่อปิดใช้งานการรับข้อความทั้งหมด หรือ

  • อิเทอเรเบิลของรายการหนึ่งรายการขึ้นไปที่กำหนดเกณฑ์ตัวกรอง แต่ละรายการควรเป็น tuple หรือ list ที่มีสามองค์ประกอบ:

    • identifier คือตัวระบุ CAN (int)

    • bit_mask คือบิตมาสก์สำหรับบิตในฟิลด์ตัวระบุ CAN (int)

    • flags คือจำนวนเต็มที่มีบิตศูนย์หรือมากกว่าที่กำหนดใน แฟล็กข้อความ ถูกตั้งค่า ระบุคุณสมบัติที่ข้อความขาเข้าต้องตรงกัน ไม่ใช่ทุกคอนโทรลเลอร์ที่รองรับการกรองบนทุกแฟล็ก ValueError จะถูกเรียกหากมีการร้องขอแฟล็กที่ไม่รองรับ

ข้อความขาเข้าจะถูกยอมรับหากบิตที่มาสก์ใน bit_mask ตรงกันระหว่างตัวระบุข้อความและค่า identifier ของตัวกรอง และแฟล็กที่ตั้งค่าในตัวกรองตรงกับข้อความขาเข้า

หากบิต CAN.FLAG_EXT_ID ถูกตั้งค่าในแฟล็ก ตัวกรองจะตรงกับ Extended CAN ID เท่านั้น หากบิต CAN.FLAG_EXT_ID ไม่ได้ถูกตั้งค่า ตัวกรองจะตรงกับ Standard CAN ID เท่านั้น

ตัวกรองทั้งหมดจะถูก OR เข้าด้วยกันในคอนโทรลเลอร์ การส่ง list หรือ tuple ว่างสำหรับอาร์กิวเมนต์ filters หมายความว่าจะไม่มีการรับข้อความ

คอนโทรลเลอร์ CAN บางตัวกำหนดให้ตัวกรองแต่ละตัวต้องเชื่อมโยงกับ FIFO รับเพียงตัวเดียว ในกรณีเหล่านี้ รายการตัวกรองในอาร์กิวเมนต์จะถูกจัดสรรแบบ round-robin ให้กับ FIFO ที่มีอยู่ ไดรเวอร์นี้ไม่แยกความแตกต่างระหว่าง FIFO ใน IRQ รับ

Note

หากผู้เรียกส่งอิเทอเรเบิลที่มีรายการมากกว่า CAN.FILTERS_MAX ValueError จะถูกเรียก

Note

หาก identifier หรือ bit_mask อยู่นอกช่วงสำหรับประเภท ID ที่ระบุ ValueError พร้อมเหตุผล "invalid id" จะถูกเรียก

ตัวอย่าง

รับข้อความขาเข้าทั้งหมด:

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 คือจำนวนเต็มที่มีบิตศูนย์หรือมากกว่าที่กำหนดใน แฟล็กข้อความ ถูกตั้งค่า ระบุคุณสมบัติของข้อความ CAN ขาออก (Extended ID, Remote Transmission Request เป็นต้น)

หากข้อความถูกจัดคิวเพื่อส่งออกบัสสำเร็จ ฟังก์ชันจะคืนค่าจำนวนเต็มในช่วง 0 ถึง CAN.TX_QUEUE_LEN (ไม่รวม) ค่านี้คือดัชนีบัฟเฟอร์ส่งที่ข้อความถูกจัดคิวเพื่อส่ง และสามารถใช้โดยฟังก์ชัน CAN.cancel_send และในเหตุการณ์ CAN.IRQ_TX

หากคิวเต็มการส่งจะล้มเหลวและคืนค่า None

การส่งอาจล้มเหลวและคืนค่า None ด้วย หากค่า id ที่ให้มามีลำดับความสำคัญเท่ากับข้อความที่มีอยู่ในคิวส่งและฮาร์ดแวร์คอนโทรลเลอร์ CAN ไม่สามารถรับประกันว่าข้อความที่มี ID เดียวกันจะถูกส่งออกบัสในลำดับเดียวกันกับที่เพิ่มเข้าคิว หากต้องการจัดคิวข้อความไม่ว่าจะเป็นอย่างไร ให้ส่งค่า CAN.FLAG_UNORDERED ในอาร์กิวเมนต์ flags แฟล็กนี้ระบุว่าไม่เป็นไรที่จะส่งข้อความที่มี CAN ID เดียวกันออกบัสในลำดับใดก็ได้

หากคอนโทรลเลอร์อยู่ในสถานะข้อผิดพลาด "Bus Off" หรือปิดใช้งาน การเรียกฟังก์ชันนี้จะเรียก OSError

Note

การนำไปใช้ระดับต่ำที่ตั้งใจนี้ออกแบบมาเพื่อให้ผู้เรียกสามารถสร้างคิวซอฟต์แวร์ของข้อความขาออกได้

Important

"คิวส่ง" CAN ไม่ใช่คิว FIFO แต่เรียงตามลำดับความสำคัญ และแม้ว่าจะสามารถรองรับได้ถึง CAN.TX_QUEUE_LEN รายการ อาจมีข้อจำกัดฮาร์ดแวร์อื่น ๆ เกี่ยวกับข้อความที่สามารถจัดคิวในเวลาเดียวกันได้

Remote Transmission Request

หากบิต CAN.FLAG_RTR ถูกตั้งค่าในอาร์กิวเมนต์ flags คอนโทรลเลอร์จะส่ง Remote Transmission Request แทนข้อความ ในกรณีนี้เนื้อหาของอาร์กิวเมนต์ data จะถูกละเว้น คอนโทรลเลอร์จะส่งคำขอที่ฟิลด์ความยาว DLC เท่ากับความยาวของอาร์กิวเมนต์ data

ตัวอย่าง

พยายามส่งข้อความที่มีเพย์โหลด 3 ไบต์ 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

Note

ต้องเรียก 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 คือจำนวนเต็มที่มีบิตศูนย์หรือมากกว่าที่กำหนดใน แฟล็กข้อความ ถูกตั้งค่า ระบุข้อมูลเมตาดาต้าเกี่ยวกับข้อความที่ได้รับ

  • ดัชนี 3 คือจำนวนเต็มที่มีบิตศูนย์หรือมากกว่าที่กำหนดใน แฟล็กข้อผิดพลาดการรับ ถูกตั้งค่า ค่าที่ไม่ใช่ศูนย์ใด ๆ ระบุปัญหาที่อาจเกิดขึ้นเมื่อรับข้อความ CAN แฟล็กเหล่านี้จะถูกรีเซ็ตภายในคอนโทรลเลอร์ทุกครั้งที่ฟังก์ชันนี้คืนค่า

Remote Transmission Request

หาก Remote Transmission Request ถูกรับแล้วบิต CAN.FLAG_RTR จะถูกตั้งค่าในดัชนี 2 และ memoryview ที่ดัชนี 1 จะมีศูนย์ทั้งหมด โดยมีความยาวเท่ากับฟิลด์ DLC ของคำขอที่ได้รับ

ตัวอย่าง
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 คือฟังก์ชันที่จะถูกเรียกเมื่อเหตุการณ์อินเทอร์รัปต์ทริกเกอร์ ตัวจัดการต้องรับอาร์กิวเมนต์เพียงหนึ่งตัวซึ่งเป็นอินสแตนซ์ CAN

  • trigger กำหนดค่าเหตุการณ์ที่สามารถสร้างอินเทอร์รัปต์ได้ ค่าที่เป็นไปได้คือมาสก์ของหนึ่งหรือมากกว่าของสิ่งต่อไปนี้:

    • เหตุการณ์ CAN.IRQ_RX เกิดขึ้นหลังจาก CAN คอนโทรลเลอร์ได้รับข้อความอย่างน้อยหนึ่งข้อความเข้า RX FIFO (หมายความว่า CAN.recv() จะคืนค่าสำเร็จ)

    • เหตุการณ์ CAN.IRQ_TX เกิดขึ้นหลังจาก CAN คอนโทรลเลอร์ส่งข้อความออกบัส CAN สำเร็จหรือล้มเหลวในการส่งข้อความ ทริกเกอร์นี้มีข้อกำหนดเพิ่มเติมสำหรับตัวจัดการ ดู แฟล็ก IRQ สำหรับรายละเอียด

    • เหตุการณ์ CAN.IRQ_STATE เกิดขึ้นเมื่อ CAN คอนโทรลเลอร์เปลี่ยนไปสู่สถานะข้อผิดพลาดที่รุนแรงยิ่งขึ้น เรียก CAN.state() เพื่อรับสถานะที่อัปเดต

  • hard หากเป็น True จะใช้อินเทอร์รัปต์แบบ hard ซึ่งช่วยลดความล่าช้าระหว่างเหตุการณ์ CAN คอนโทรลเลอร์และการเรียกตัวจัดการ ตัวจัดการอินเทอร์รัปต์แบบ hard อาจไม่จัดสรรหน่วยความจำ ดู การเขียนตัวจัดการอินเทอร์รัปต์

คืนค่าออบเจ็กต์ irq หากเรียกโดยไม่มีอาร์กิวเมนต์จะคืนค่าออบเจ็กต์ irq ที่กำหนดค่าไว้ก่อนหน้า

ดู แฟล็ก IRQ สำหรับตัวอย่าง

cancel_send(index: int) bool

ร้องขอให้ CAN คอนโทรลเลอร์ยกเลิกการส่งข้อความออกบัส

อาร์กิวเมนต์ index ระบุบัฟเฟอร์ส่งเดี่ยว ควรเป็นจำนวนเต็มในช่วง 0 ถึง CAN.TX_QUEUE_LEN (ไม่รวม) โดยทั่วไปนี่จะเป็นค่าที่ CAN.send() คืนค่ามาก่อนหน้า

ผลลัพธ์คือ True หากข้อความกำลังรอส่งในบัฟเฟอร์นี้และการส่งถูกยกเลิก

ผลลัพธ์คือ False หากไม่เช่นนั้น (ไม่มีข้อความรอส่งในบัฟเฟอร์นี้ หรือการส่งสำเร็จแล้ว)

ควรใช้เหตุการณ์ IRQ CAN.IRQ_TX เพื่อตรวจสอบว่าข้อความถูกส่งแน่นอนหรือไม่ แต่โปรดทราบว่ามีเงื่อนไขการแย่งชิงที่อาจเกิดขึ้นหากการส่งถูกยกเลิกแล้วใช้บัฟเฟอร์เดียวกันในการส่งข้อความอื่น (โดยเฉพาะอย่างยิ่งหาก CAN คอนโทรลเลอร์ IRQ ไม่ใช่ "hard")

state() int

คืนค่าจำนวนเต็มที่ระบุสถานะปัจจุบันของคอนโทรลเลอร์ ค่าจะเป็นหนึ่งในค่าที่กำหนดใน สถานะ

สถานะข้อผิดพลาดที่มีความรุนแรงน้อยกว่าอาจล้างโดยอัตโนมัติหากบัสฟื้นตัว แต่สถานะ 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

Note

ขึ้นอยู่กับคอนโทรลเลอร์ ค่าเหล่านี้อาจล้นกลับเป็น 0 หลังจากค่าหนึ่ง

Note

หากคอนโทรลเลอร์ไม่รองรับตัวนับเฉพาะ จะคืนค่า None สำหรับองค์ประกอบ list นั้น

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

คืนค่า list ขององค์ประกอบที่ระบุการตั้งค่าเวลาปัจจุบันที่กำหนดค่าใน CAN คอนโทรลเลอร์ ซึ่งสามารถใช้เพื่อตรวจสอบการตั้งค่าเวลาสำหรับการดีบัก ผลลัพธ์คือ list ของค่าหกค่า หากระบุพารามิเตอร์ list เสริมแล้ว ออบเจ็กต์ list ที่ให้มาจะถูกอัปเดตและคืนค่าเป็นผลลัพธ์เพื่อหลีกเลี่ยงการจัดสรร

รายการ list ประกอบด้วย:

  • บิตเรตที่แน่นอนที่ใช้โดยคอนโทรลเลอร์ อาจแตกต่างจากอาร์กิวเมนต์ bitrate ที่ส่งไปยัง CAN.init() เนื่องจากการแบ่งปริมาณเพื่อให้ตรงตามข้อจำกัดฮาร์ดแวร์

  • ความกว้างการกระโดดซิงโครไนซ์ใหม่ (SJW) ในหน่วยควอนตัมเวลาสำหรับบิตนามแฝง มีความหมายเดียวกันกับพารามิเตอร์ sjw ของ CAN.init()

  • ตำแหน่งของจุดตัวอย่างในหน่วยควอนตัมเวลาสำหรับบิตนามแฝง มีความหมายเดียวกันกับพารามิเตอร์ tseg1 ของ CAN.init()

  • ตำแหน่งของจุดส่งสัญญาณในหน่วยควอนตัมเวลาสำหรับบิตนามแฝง มีความหมายเดียวกันกับพารามิเตอร์ tseg2 ของ CAN.init()

  • ข้อมูลเวลา CAN FD None สำหรับคอนโทรลเลอร์ที่ไม่รองรับ CAN FD หรือหาก CAN FD ไม่ได้เริ่มต้น มิฉะนั้นจะเป็น nested list ของสี่องค์ประกอบที่สอดคล้องกับรายการด้านบนแต่ใช้กับฟีเจอร์ CAN FD BRS

  • ข้อมูลเวลาเฉพาะคอนโทรลเลอร์เสริม ขึ้นอยู่กับคอนโทรลเลอร์ นี่จะเป็น None หากคอนโทรลเลอร์ไม่รายงานใด ๆ หรือจะเป็น list ความยาวคงที่ที่มีองค์ประกอบเฉพาะกับฮาร์ดแวร์คอนโทรลเลอร์เฉพาะ

Note

หากยังไม่ได้เรียก 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()

ค่าคงที่

TX_QUEUE_LEN: int

จำนวนสูงสุดของข้อความ CAN ที่สามารถจัดคิวในคิวข้อความฮาร์ดแวร์ขาออกของคอนโทรลเลอร์ "ดัชนีบัฟเฟอร์ส่ง" ที่ใช้โดย CAN.send(), CAN.cancel_send() และ แฟล็ก IRQ จะอยู่ในช่วงนี้

โหมด

ค่าเหล่านี้แสดงโหมดการทำงานของคอนโทรลเลอร์ ตามที่ส่งไปยัง 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 บัสเลย พิน CAN TX และ RX ยังคงว่าง

สถานะ

ค่าเหล่านี้คืนค่าโดย 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() เพื่อดำเนินการต่อ

แฟล็กข้อความ

ค่าเหล่านี้แสดงข้อมูลเมตาดาต้าเกี่ยวกับข้อความ CAN ฟังก์ชัน CAN.send(), CAN.recv() และ CAN.set_filters() รับหรือคืนค่าจำนวนเต็มที่ประกอบด้วยแฟล็กเหล่านี้ศูนย์หรือมากกว่า bitwise ORed เข้าด้วยกัน

FLAG_RTR: int

ระบุว่าข้อความเป็น remote transmission request

FLAG_EXT_ID: int

หากตั้งค่า ระบุว่าตัวระบุข้อความเป็น Extended (29-bit) หากไม่ตั้งค่า ระบุว่าตัวระบุข้อความเป็น Standard (11-bit)

FLAG_UNORDERED: int

หากตั้งค่าในอาร์กิวเมนต์ flags ของ CAN.send() ระบุว่าไม่เป็นไรหากข้อความที่มี CAN ID เดียวกันถูกส่งในลำดับใดก็ได้บนบัส

มิฉะนั้น การพยายามจัดคิวข้อความหลายรายการที่มี ID เดียวกันอาจส่งผลให้ CAN.send() ล้มเหลวหากฮาร์ดแวร์คอนโทรลเลอร์ไม่สามารถบังคับใช้การเรียงลำดับได้

แฟล็กนี้ไม่เคยถูกตั้งค่าบนข้อความที่ได้รับ และถูกละเว้นโดย CAN.set_filters()

แฟล็กข้อผิดพลาดการรับ

ผลลัพธ์ของ CAN.recv() มีค่าจำนวนเต็มที่ประกอบด้วยแฟล็กเหล่านี้ศูนย์หรือมากกว่า bitwise ORed เข้าด้วยกัน หากตั้งค่า แฟล็กเหล่านี้ระบุปัญหาทั่วไปที่อาจเกิดขึ้นเมื่อรับข้อความ CAN

RECV_ERR_FULL: int

FIFO ฮาร์ดแวร์ที่รับข้อความนี้เต็ม และข้อความขาเข้าเพิ่มเติมอาจสูญหาย

RECV_ERR_OVERRUN: int

FIFO ฮาร์ดแวร์ที่รับข้อความนี้เต็ม และข้อความขาเข้าหนึ่งข้อความขึ้นไปสูญหาย

ค่า IRQ

IRQ_RX: int

ส่งไปยังอาร์กิวเมนต์ trigger ของ irq() เพื่อเรียกตัวจัดการทุกครั้งที่ CAN คอนโทรลเลอร์ได้รับข้อความสมบูรณ์เข้า RX FIFO ภายในตัวจัดการให้อ่านข้อความด้วย recv()

IRQ_TX: int

ส่งไปยังอาร์กิวเมนต์ trigger ของ irq() เพื่อเรียกตัวจัดการทุกครั้งที่ CAN คอนโทรลเลอร์จบความพยายามในการส่ง (สำเร็จหรือล้มเหลว) ภายในตัวจัดการให้ใช้บิตเพิ่มเติมด้านล่างเพื่อกู้คืนว่า mailbox ใดเสร็จสิ้นและล้มเหลวหรือไม่ -- ดู แฟล็ก IRQ

IRQ_STATE: int

ส่งไปยังอาร์กิวเมนต์ trigger ของ irq() เพื่อเรียกตัวจัดการทุกครั้งที่คอนโทรลเลอร์เปลี่ยนระหว่างค่า STATE_* (active / warning / passive / bus-off) ใช้ state() ภายในตัวจัดการเพื่ออ่านสถานะใหม่

IRQ_TX_FAILED: int

แฟล็กสถานะที่อาจถูกตั้งค่าใน irq().flags() เมื่อเหตุการณ์ IRQ_TX เกิดขึ้น ระบุว่าความพยายามในการส่งล้มเหลว (โดยทั่วไปเพราะ cancel_send() ถูกเรียก หรือคอนโทรลเลอร์เข้าสู่สถานะข้อผิดพลาด)

IRQ_TX_IDX_SHIFT: int

ตำแหน่งบิตของฟิลด์ transmit-mailbox-index ภายในค่า irq().flags() ระหว่างเหตุการณ์ IRQ_TX ดัชนี mailbox ถูกแยกออกมาเป็น (flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK

IRQ_TX_IDX_MASK: int

บิตมาสก์ของฟิลด์ transmit-mailbox-index ภายในค่า irq().flags() ระหว่างเหตุการณ์ IRQ_TX ดัชนีที่แยกออกมาตรงกับจำนวนเต็มที่คืนค่าโดยการเรียก send() ที่สอดคล้องกัน (จำนวนเต็มในช่วง 0 ถึง TX_QUEUE_LEN)

แฟล็ก IRQ

การเรียก CAN.irq() ลงทะเบียนตัวจัดการอินเทอร์รัปต์ด้วยทริกเกอร์หนึ่งหรือมากกว่า CAN.IRQ_RX, CAN.IRQ_TX และ CAN.IRQ_STATE

ฟังก์ชันคืนค่าออบเจ็กต์ IRQ และการเรียกฟังก์ชัน flags() บนออบเจ็กต์นี้คืนค่าจำนวนเต็มที่ระบุว่าเหตุการณ์ทริกเกอร์ใดทริกเกอร์อินเทอร์รัปต์ ตัวจัดการ CAN IRQ ควรเรียกฟังก์ชัน flags() ซ้ำ ๆ จนกว่าจะคืนค่า 0

เมื่อฟังก์ชัน flags() คืนค่าพร้อมบิต CAN.IRQ_TX ถูกตั้งค่า ตัวจัดการยังสามารถตรวจสอบบิตแฟล็กต่อไปนี้ในผลลัพธ์สำหรับข้อมูลเพิ่มเติมเกี่ยวกับเหตุการณ์ TX:

  • บิต CAN.IRQ_TX_FAILED ถูกตั้งค่าหากการส่งล้มเหลว โดยทั่วไปนี้จะเกิดขึ้นเฉพาะเมื่อมีการเรียก CAN.cancel_send() แม้ว่าอาจเกิดขึ้นหากคอนโทรลเลอร์เข้าสู่สถานะข้อผิดพลาด

  • CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFT คือบริเวณ bitmasked ของค่า flags ที่เก็บดัชนีของบัฟเฟอร์ส่งที่สร้างเหตุการณ์ นี่จะเป็นจำนวนเต็มในช่วง 0 ถึง CAN.TX_QUEUE_LEN (ไม่รวม) และจะตรงกับผลลัพธ์ของการเรียก CAN.send() ก่อนหน้า

ตัวอย่าง IRQ_TX

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)

Important

หากตั้งค่าทริกเกอร์ CAN.IRQ_TX ตัวจัดการ ต้อง เรียก flags() ซ้ำ ๆ จนกว่าจะคืนค่า 0 ดังที่แสดงในตัวอย่างนี้ มิฉะนั้น CAN อินเทอร์รัปต์อาจไม่ถูกเปิดใช้งานใหม่อย่างถูกต้อง