class CAN -- Giao thức Controller Area Network

CAN là giao thức nối tiếp hai dây được sử dụng để truyền thông tin đáng tin cậy theo thời gian thực giữa một hoặc nhiều nút kết nối với một bus chung. CAN 2.0 được chuẩn hóa trong ISO-11898 và hiện còn được gọi là CAN Classic.

Ngoài ra còn có một giao thức mới hơn, tương thích ngược, có tên CAN FD (CAN với Tốc độ Dữ liệu Linh hoạt). Driver machine.CAN hiện chưa hỗ trợ các tính năng CAN FD; hãy dùng pyb.CAN trên STM32 nếu bạn cần CAN FD.

Hỗ trợ CAN yêu cầu một bộ điều khiển (thường là ngoại vi tích hợp trong vi điều khiển) và một bộ thu phát ngoài để chuyển mức tín hiệu lên bus CAN.

Hỗ trợ trên các OpenMV Cam STM32 (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6, cùng các phiên bản mang thương hiệu Arduino có kết nối bộ thu phát). Chưa hỗ trợ trên OpenMV Cam RT1062 (cổng mimxrt) hoặc OpenMV Cam AE3 (cổng alif).

Giao diện machine.CAN là giao diện nhắn tin CAN cơ bản mức thấp trừu tượng hóa một bộ điều khiển CAN thành hàng đợi ưu tiên gửi đi cho việc truyền tin, hàng đợi nhận cho việc nhận tin, và các cơ chế báo cáo lỗi.

Ghi chú

Các mô-đun micropython-lib canaiocan đang được lên kế hoạch sẽ là cách được khuyến nghị để sử dụng CAN với MicroPython.

Hàm khởi tạo

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

Khởi tạo một đối tượng bộ điều khiển CAN với id cho trước:

  • id xác định một đối tượng bộ điều khiển CAN cụ thể; giá trị này phụ thuộc vào board và cổng.

  • Tất cả các đối số còn lại được truyền vào CAN.init(). Cần cung cấp ít nhất một đối số (bitrate).

Các phiên bản tương lai của lớp này cũng có thể chấp nhận các đối số từ khóa đặc thù cho cổng để cấu hình phần cứng. Hiện tại chưa có đối số từ khóa như vậy được triển khai.

Ví dụ

Khởi tạo bộ điều khiển CAN 1 với tốc độ baud 500kbps:

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

Phương thức

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

Khởi tạo bus CAN với các tham số cho trước:

  • bitrate là tốc độ bit mong muốn của bus, tính bằng bit mỗi giây.

  • mode là một trong các giá trị được liệt kê trong Các chế độ, chỉ định chế độ hoạt động mong muốn. Mặc định là chế độ hoạt động "bình thường" trên bus.

Các tham số tiếp theo là tùy chọn và liên quan đến thời gian bit CAN. Trong hầu hết các trường hợp, bạn có thể để các tham số này ở giá trị mặc định:

  • sample_point là tỷ lệ phần trăm nguyên của thời gian bit dữ liệu. Nó xác định vị trí lấy mẫu bit so với toàn bộ thời gian bit danh nghĩa. Driver CAN sẽ tính toán các tham số tương ứng. Tham số này bị bỏ qua nếu tseg1tseg2 được đặt.

  • sjw là chiều rộng nhảy đồng bộ lại, tính bằng đơn vị thời gian quanta cho bit danh nghĩa; có thể là giá trị từ 1 đến 4 bao gồm cho CAN classic.

  • tseg1 xác định vị trí điểm lấy mẫu tính bằng đơn vị thời gian quanta cho bit danh nghĩa; có thể là giá trị từ 1 đến 16 bao gồm cho CAN classic. Đây là tổng của hai pha Prop_SegPhase_Seg1 như được định nghĩa trong tiêu chuẩn ISO-11898. Nếu giá trị này được đặt thì tseg2 cũng phải được đặt và sample_point sẽ bị bỏ qua.

  • tseg2 xác định vị trí điểm truyền tính bằng đơn vị thời gian quanta cho bit danh nghĩa; có thể là giá trị từ 1 đến 8 bao gồm cho CAN classic. Tương ứng với Phase_Seg2 trong tiêu chuẩn ISO-11898. Nếu giá trị này được đặt thì tseg1 cũng phải được đặt.

Nếu các đối số này được chỉ định, bộ điều khiển CAN sẽ được cấu hình đúng cho bitrate mong muốn và tổng số thời gian quanta mỗi bit được chỉ định. Các giá trị tseg1tseg2 ghi đè lên đối số sample_point nếu tất cả chúng đều được cung cấp.

Ghi chú

Phần cứng bộ điều khiển cụ thể có thể có các hạn chế bổ sung về giá trị hợp lệ cho các tham số này, và sẽ phát sinh ValueError nếu giá trị đưa vào không được hỗ trợ.

Ghi chú

Phần cứng bộ điều khiển cụ thể có thể chấp nhận thêm các tham số từ khóa tùy chọn cho các tính năng đặc thù phần cứng như oversampling.

set_filters(filters: list | tuple | None) None

Đặt bộ lọc nhận trong bộ điều khiển CAN. filters có thể là:

  • None để chấp nhận tất cả thông điệp đến, hoặc

  • [] hoặc () để vô hiệu hóa tất cả việc nhận thông điệp, hoặc

  • Một iterable gồm một hoặc nhiều phần tử định nghĩa tiêu chí lọc. Mỗi phần tử là một tuple hoặc list với ba phần tử:

    • identifier là định danh CAN (int).

    • bit_mask là mặt nạ bit cho các bit trong trường định danh CAN (int).

    • flags là số nguyên với không hoặc nhiều bit được định nghĩa trong Cờ thông điệp. Điều này xác định các thuộc tính mà thông điệp đến cần phải khớp. Không phải tất cả bộ điều khiển đều hỗ trợ lọc theo tất cả các cờ, ValueError sẽ được phát sinh nếu một cờ không được hỗ trợ được yêu cầu.

Thông điệp đến được chấp nhận nếu các bit được che bởi bit_mask khớp giữa định danh thông điệp và giá trị identifier của bộ lọc, và các cờ được đặt trong bộ lọc khớp với thông điệp đến.

Nếu bit CAN.FLAG_EXT_ID được đặt trong flags, bộ lọc chỉ khớp với Extended CAN ID. Nếu bit CAN.FLAG_EXT_ID không được đặt, bộ lọc chỉ khớp với Standard CAN ID.

Tất cả các bộ lọc được ORed với nhau trong bộ điều khiển. Truyền một list hoặc tuple rỗng cho đối số filters có nghĩa là không có thông điệp nào sẽ được nhận.

Một số bộ điều khiển CAN yêu cầu mỗi bộ lọc chỉ được liên kết với một FIFO nhận. Trong các trường hợp này, các phần tử bộ lọc trong đối số được phân bổ theo kiểu round-robin cho các FIFO có sẵn. Driver này không phân biệt giữa các FIFO trong IRQ nhận.

Ghi chú

Nếu caller truyền một iterable với nhiều phần tử hơn CAN.FILTERS_MAX, ValueError sẽ được phát sinh.

Ghi chú

Nếu identifier hoặc bit_mask nằm ngoài phạm vi cho loại ID được chỉ định, ValueError với lý do "invalid id" sẽ được phát sinh.

Các ví dụ

Nhận tất cả thông điệp đến:

can.set_filters(None)

Chỉ nhận các thông điệp có giá trị Standard ID là 0x301 và 0x700:

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

Chỉ nhận các thông điệp có giá trị Standard ID trong khoảng 0x300-0x3FF và Extended ID 0x50700:

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

Giá trị hằng số cho biết số lượng bộ lọc nhận tối đa được hỗ trợ cho bộ điều khiển phần cứng này.

Lưu ý rằng một số bộ điều khiển có thể có các hạn chế phần cứng phức tạp hơn về số lượng bộ lọc đang sử dụng (ví dụ: đếm bộ lọc Standard và Extended ID riêng lẻ). Trong các trường hợp này CAN.set_filters có thể phát sinh ValueError ngay cả khi giới hạn FILTERS_MAX chưa bị vượt quá.

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

Sao chép một thông điệp CAN mới vào hàng đợi truyền phần cứng của bộ điều khiển để gửi lên bus. Hàng đợi truyền là hàng đợi ưu tiên được sắp xếp theo độ ưu tiên định danh CAN (định danh số nhỏ hơn có độ ưu tiên cao hơn).

  • id là giá trị định danh CAN nguyên.

  • data là đối tượng bytes (hoặc tương tự) chứa dữ liệu thông điệp CAN, hoặc mô tả một Remote Transmission Request (xem bên dưới).

  • flags là số nguyên với không hoặc nhiều bit được định nghĩa trong Cờ thông điệp, xác định thuộc tính của thông điệp CAN gửi đi (Extended ID, Remote Transmission Request, v.v.)

Nếu thông điệp được xếp hàng thành công để truyền lên bus, hàm trả về một số nguyên trong khoảng 0 đến CAN.TX_QUEUE_LEN (không bao gồm). Giá trị này là chỉ số bộ đệm truyền nơi thông điệp được xếp hàng để gửi, và có thể được sử dụng bởi hàm CAN.cancel_send và trong các sự kiện CAN.IRQ_TX.

Nếu hàng đợi đầy thì lệnh gửi sẽ thất bại và None được trả về.

Lệnh gửi cũng có thể thất bại và trả về None nếu giá trị id được cung cấp có cùng độ ưu tiên với một thông điệp đang tồn tại trong hàng đợi truyền và phần cứng bộ điều khiển CAN không thể đảm bảo rằng các thông điệp có cùng ID sẽ được gửi lên bus theo đúng thứ tự chúng được thêm vào hàng đợi. Để xếp hàng thông điệp dù sao, hãy truyền cờ CAN.FLAG_UNORDERED trong đối số flags. Cờ này cho biết việc gửi các thông điệp có cùng CAN ID lên bus theo bất kỳ thứ tự nào là được phép.

Nếu bộ điều khiển đang ở trạng thái lỗi "Bus Off" hoặc bị vô hiệu hóa thì việc gọi hàm này sẽ phát sinh OSError.

Ghi chú

Triển khai mức thấp có chủ ý này được thiết kế để caller có thể tạo một hàng đợi phần mềm cho các thông điệp gửi đi.

Quan trọng

"Hàng đợi truyền" CAN không phải là hàng đợi FIFO, nó được sắp xếp theo độ ưu tiên, và mặc dù nó có thể chứa tới CAN.TX_QUEUE_LEN phần tử nhưng có thể có các hạn chế phần cứng khác về các thông điệp có thể được xếp hàng cùng một lúc.

Remote Transmission Requests

Nếu bit CAN.FLAG_RTR được đặt trong đối số flags thì bộ điều khiển sẽ gửi Remote Transmission Request thay vì thông điệp. Trong trường hợp này nội dung của đối số data bị bỏ qua. Bộ điều khiển sẽ gửi một yêu cầu trong đó trường độ dài DLC bằng với độ dài của đối số data.

Các ví dụ

Thử gửi thông điệp với payload ba byte 0a0b0c và Standard ID 0x200:

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

Thử gửi thông điệp với payload rỗng và Extended ID 0x180008. Cho biết bộ điều khiển có thể gửi các thông điệp có ID này theo bất kỳ thứ tự nào, trong trường hợp có các thông điệp khác đã được xếp hàng để gửi với cùng ID:

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

Thử gửi Remote Transmission Request với độ dài 8 byte và Standard ID 0x555:

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

Trả về một thông điệp CAN đã được bộ điều khiển nhận, theo các bộ lọc được đặt bởi CAN.set_filters().

Hàm này nhận một đối số tùy chọn duy nhất, nếu được cung cấp thì nó phải là một list có ít nhất 4 phần tử trong đó phần tử thứ hai là đối tượng memoryview tham chiếu đến bytearray hoặc đối tượng tương tự có đủ dung lượng để chứa bất kỳ thông điệp CAN đã nhận nào (8 byte cho CAN Classic, 64 byte cho CAN FD). List được cung cấp sẽ được trả về như kết quả thành công và tránh cấp phát bộ nhớ bên trong hàm.

Nếu không có thông điệp nào được bộ điều khiển CAN nhận, hàm này trả về None.

Ghi chú

CAN.set_filters phải được gọi trước khi bộ điều khiển có thể nhận bất kỳ thông điệp nào. Để nhận tất cả thông điệp, hãy gọi set_filters(None).

Nếu một thông điệp đã được bộ điều khiển CAN nhận, hàm này trả về một list với 4 phần tử:

  • Index 0 là CAN ID của thông điệp đã nhận, dưới dạng số nguyên.

  • Index 1 là một memoryview cung cấp quyền truy cập vào dữ liệu thông điệp đã nhận.

    • Nếu arg không được cung cấp thì đây là memoryview giữ các byte đã nhận. memoryview này được hỗ trợ bởi một bytearray mới được cấp phát đủ lớn để chứa bất kỳ thông điệp CAN đã nhận nào. Điều này cho phép kết quả được tái sử dụng an toàn như arg trong tương lai để tiết kiệm bộ nhớ cấp phát.

    • Nếu arg được cung cấp thì memoryview được cung cấp sẽ được thay đổi kích thước để chứa đúng các byte đã nhận. Caller có trách nhiệm đảm bảo đối tượng hỗ trợ memoryview có thể chứa thông điệp CAN có độ dài bất kỳ.

  • Index 2 là số nguyên với không hoặc nhiều bit được định nghĩa trong Cờ thông điệp. Nó chỉ ra siêu dữ liệu về thông điệp đã nhận.

  • Index 3 là số nguyên với không hoặc nhiều bit được định nghĩa trong Cờ lỗi nhận. Bất kỳ giá trị khác 0 nào đều chỉ ra các vấn đề tiềm ẩn khi nhận thông điệp CAN. Các cờ này được đặt lại bên trong bộ điều khiển mỗi khi hàm này trả về.

Remote Transmission Requests

Nếu nhận được Remote Transmission Request thì bit CAN.FLAG_RTR sẽ được đặt ở Index 2 và memoryview ở Index 1 sẽ chứa toàn số không, với độ dài bằng trường DLC của yêu cầu đã nhận.

Ví dụ
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

Đặt hàm handler ngắt để được gọi khi một hoặc nhiều sự kiện được đánh dấu trong trigger đã xảy ra.

  • handler là hàm được gọi khi sự kiện ngắt kích hoạt. Handler phải nhận đúng một đối số là thể hiện CAN.

  • trigger cấu hình (các) sự kiện có thể tạo ra ngắt. Các giá trị có thể là mặt nạ của một hoặc nhiều giá trị sau:

    • Sự kiện CAN.IRQ_RX xảy ra sau khi bộ điều khiển CAN đã nhận ít nhất một thông điệp vào RX FIFO (nghĩa là CAN.recv() sẽ trả về thành công).

    • Sự kiện CAN.IRQ_TX xảy ra sau khi bộ điều khiển CAN đã gửi thành công một thông điệp lên bus CAN hoặc gửi thất bại. Trigger này có các yêu cầu bổ sung cho handler, xem Cờ IRQ để biết chi tiết.

    • Sự kiện CAN.IRQ_STATE xảy ra khi bộ điều khiển CAN chuyển sang trạng thái lỗi nghiêm trọng hơn. Gọi CAN.state() để nhận trạng thái cập nhật.

  • hard nếu True, một ngắt cứng sẽ được sử dụng. Điều này giảm độ trễ giữa sự kiện bộ điều khiển CAN và thời điểm handler được gọi. Các handler ngắt cứng không được cấp phát bộ nhớ; xem Viết trình xử lý ngắt.

Trả về một đối tượng irq. Nếu được gọi không có đối số thì một đối tượng irq đã được cấu hình trước đó sẽ được trả về.

Xem Cờ IRQ để biết ví dụ.

cancel_send(index: int) bool

Yêu cầu bộ điều khiển CAN hủy gửi một thông điệp lên bus.

Đối số index xác định một bộ đệm truyền đơn lẻ. Nó phải là số nguyên trong khoảng 0 đến CAN.TX_QUEUE_LEN (không bao gồm). Thông thường đây sẽ là giá trị trước đó được trả về bởi CAN.send().

Kết quả là True nếu một thông điệp đang chờ truyền trong bộ đệm này và việc truyền đã bị hủy.

Kết quả là False trong trường hợp khác (không có thông điệp nào đang chờ truyền trong bộ đệm này, hoặc việc truyền đã thành công).

Sự kiện IRQ CAN.IRQ_TX nên được sử dụng để xác định liệu một thông điệp có chắc chắn được gửi hay không, nhưng lưu ý rằng có thể xảy ra race condition nếu một lần truyền bị hủy và sau đó cùng bộ đệm đó được sử dụng để gửi thông điệp khác (đặc biệt nếu IRQ bộ điều khiển CAN không phải là ngắt "cứng").

state() int

Trả về giá trị số nguyên chỉ ra trạng thái hiện tại của bộ điều khiển. Giá trị sẽ là một trong các giá trị được định nghĩa trong Các trạng thái.

Các trạng thái lỗi ít nghiêm trọng hơn có thể tự động xóa nếu bus phục hồi, nhưng trạng thái CAN.STATE_BUS_OFF chỉ có thể phục hồi bằng cách gọi CAN.restart().

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

Trả về các giá trị bộ đếm lỗi của bộ điều khiển. Kết quả là một list gồm tám giá trị. Nếu tham số list tùy chọn được chỉ định thì đối tượng list được cung cấp sẽ được cập nhật và trả về như kết quả để tránh cấp phát bộ nhớ.

Các phần tử của list là:

  • Giá trị TEC (Transmit Error Counter)

  • Giá trị REC (Receive Error Counter)

  • Số lần bộ điều khiển vào trạng thái Warning từ trạng thái Active.

  • Số lần bộ điều khiển vào trạng thái Error Passive từ trạng thái Warning.

  • Số lần bộ điều khiển vào trạng thái Bus Off từ trạng thái Error Passive.

  • Tổng số thông điệp TX đang chờ trong hàng đợi phần cứng.

  • Tổng số thông điệp RX đang chờ trong hàng đợi phần cứng.

  • Số lần xảy ra RX overrun.

Ghi chú

Tùy thuộc vào bộ điều khiển, các giá trị này có thể tràn về 0 sau một giá trị nhất định.

Ghi chú

Nếu bộ điều khiển không hỗ trợ một bộ đếm cụ thể, nó sẽ trả về None cho phần tử list đó.

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

Trả về một list các phần tử chỉ ra các thời gian hiện tại được cấu hình trong bộ điều khiển CAN. Có thể sử dụng để xác minh thời gian cho mục đích gỡ lỗi. Kết quả là một list gồm sáu giá trị. Nếu tham số list tùy chọn được chỉ định thì đối tượng list được cung cấp sẽ được cập nhật và trả về như kết quả để tránh cấp phát bộ nhớ.

Các phần tử của list là:

  • Tốc độ bit chính xác được sử dụng bởi bộ điều khiển. Có thể khác với đối số bitrate được truyền vào CAN.init() do lượng hóa để đáp ứng các ràng buộc phần cứng.

  • Chiều rộng nhảy đồng bộ lại (SJW) tính bằng đơn vị thời gian quanta cho bit danh nghĩa. Có cùng ý nghĩa với tham số sjw của CAN.init().

  • Vị trí điểm lấy mẫu tính bằng đơn vị thời gian quanta cho bit danh nghĩa. Có cùng ý nghĩa với tham số tseg1 của CAN.init().

  • Vị trí điểm truyền tính bằng đơn vị thời gian quanta cho bit danh nghĩa. Có cùng ý nghĩa với tham số tseg2 của CAN.init().

  • Thông tin thời gian CAN FD. None đối với các bộ điều khiển không hỗ trợ CAN FD, hoặc nếu CAN FD chưa được khởi tạo. Nếu không, là list lồng nhau gồm bốn phần tử tương ứng với các mục ở trên nhưng áp dụng cho tính năng CAN FD BRS.

  • Thông tin thời gian tùy chọn đặc thù cho bộ điều khiển. Tùy thuộc vào bộ điều khiển, giá trị này sẽ là None nếu bộ điều khiển không báo cáo bất kỳ thông tin nào, hoặc sẽ là list có độ dài cố định với các phần tử đặc thù cho một bộ điều khiển phần cứng cụ thể.

Ghi chú

Nếu CAN.init() chưa được gọi thì hàm này vẫn trả về kết quả, nhưng kết quả phụ thuộc vào nội bộ bộ điều khiển và có thể không chính xác.

restart() None

Khiến bộ điều khiển thoát khỏi STATE_BUS_OFF mà không xóa bất kỳ trạng thái nội bộ nào khác. Cũng xóa một số bộ đếm lỗi (luôn bao gồm số lần vào mỗi trạng thái lỗi, có thể cả TEC và REC tùy thuộc vào bộ điều khiển.)

Việc gọi hàm này cũng hủy các thông điệp đang chờ gửi. Không có ngắt IRQ_TX nào được gửi cho các thông điệp này.

Lưu ý rằng hàm này có thể hoặc không thể khiến bộ điều khiển thoát khỏi trạng thái "Error Passive", tùy thuộc vào việc phần cứng bộ điều khiển có đặt TEC và REC về 0 hay không.

deinit() None

Hủy khởi tạo một thể hiện CAN đang hoạt động. Tất cả các thông điệp đang chờ (truyền và nhận) bị loại bỏ và bộ điều khiển ngừng tương tác trên bus. Để sử dụng lại thể hiện này, hãy gọi CAN.init().

Không có ngắt IRQ_TX hoặc IRQ_RX nào được gọi để phản hồi việc gọi hàm này.

Xem thêm CAN.restart().

Hằng số

TX_QUEUE_LEN: int

Số lượng tối đa thông điệp CAN có thể được xếp hàng trong hàng đợi thông điệp phần cứng gửi đi của bộ điều khiển. Các "chỉ số bộ đệm truyền" được sử dụng bởi CAN.send(), CAN.cancel_send()Cờ IRQ sẽ nằm trong phạm vi này.

Các chế độ

Các giá trị này đại diện cho chế độ hoạt động của bộ điều khiển, được truyền vào CAN.init(). Không phải tất cả bộ điều khiển đều hỗ trợ tất cả các chế độ.

Việc thay đổi chế độ của bộ điều khiển đang chạy yêu cầu gọi CAN.deinit() và sau đó gọi CAN.init() lại với chế độ mới.

MODE_NORMAL: int

Bộ điều khiển hoạt động như một nút mạng CAN tiêu chuẩn (sẽ xác nhận các thông điệp hợp lệ và có thể truyền lỗi tùy thuộc vào Trạng thái hiện tại của nó).

MODE_SLEEP: int

Bộ điều khiển CAN đang ngủ ở chế độ tiết kiệm điện. Tùy thuộc vào bộ điều khiển, điều này có thể hỗ trợ đánh thức bộ điều khiển và chuyển sang CAN.MODE_NORMAL nếu nhận được lưu lượng CAN.

MODE_LOOPBACK: int

Một chế độ thử nghiệm. Bộ điều khiển CAN vẫn kết nối với bus ngoài, nhưng cũng sẽ nhận các thông điệp tự truyền và bỏ qua bất kỳ lỗi ACK nào.

MODE_SILENT: int

Bộ điều khiển CAN nhận thông điệp nhưng không tương tác với bus CAN (bao gồm gửi ACK, lỗi, v.v.)

MODE_SILENT_LOOPBACK: int

Một chế độ thử nghiệm không yêu cầu bộ thu phát CAN nào được kết nối. Bộ điều khiển CAN nhận các thông điệp tự truyền mà không tương tác với bus CAN. Các chân TX và RX CAN vẫn ở trạng thái không hoạt động.

Các trạng thái

Các giá trị này được trả về bởi CAN.state() và phản ánh trạng thái lỗi của bộ điều khiển CAN:

STATE_STOPPED: int

Bộ điều khiển chưa được khởi tạo.

STATE_ACTIVE: int

Bộ điều khiển đang hoạt động và cả hai bộ đếm lỗi TECREC đều dưới ngưỡng cảnh báo là 96. Xem CAN.get_counters().

STATE_WARNING: int

Bộ điều khiển đang hoạt động nhưng ít nhất một trong các bộ đếm lỗi TECREC nằm trong khoảng 96 và 127. Xem CAN.get_counters().

STATE_PASSIVE: int

Bộ điều khiển đang ở trạng thái "Error Passive" nghĩa là nó không còn truyền lỗi tích cực lên bus, nhưng nó vẫn hoạt động bình thường. Trạng thái này được vào khi ít nhất một trong các bộ đếm lỗi TECREC bằng 128 hoặc lớn hơn, nhưng TEC nhỏ hơn 255. Xem CAN.get_counters().

STATE_BUS_OFF: int

Bộ điều khiển đang ở trạng thái Bus-Off, nghĩa là bộ đếm lỗi TEC lớn hơn 255. Bộ điều khiển CAN sẽ không tương tác với bus ở trạng thái này và cần được khởi động lại qua CAN.restart() để tiếp tục.

Cờ thông điệp

Các giá trị này đại diện cho siêu dữ liệu về một thông điệp CAN. Các hàm CAN.send(), CAN.recv()CAN.set_filters() chấp nhận hoặc trả về giá trị số nguyên tạo thành từ không hoặc nhiều cờ này được bitwise OR với nhau.

FLAG_RTR: int

Chỉ ra một thông điệp là remote transmission request.

FLAG_EXT_ID: int

Nếu được đặt, chỉ ra định danh thông điệp là Extended (29-bit). Nếu không được đặt, chỉ ra định danh thông điệp là Standard (11-bit).

FLAG_UNORDERED: int

Nếu được đặt trong đối số flags của CAN.send(), chỉ ra rằng các thông điệp có cùng CAN ID có thể được gửi theo bất kỳ thứ tự nào lên bus.

Nếu không, việc cố xếp hàng nhiều thông điệp có cùng ID có thể dẫn đến CAN.send() thất bại nếu phần cứng bộ điều khiển không thể đảm bảo thứ tự.

Cờ này không bao giờ được đặt trên các thông điệp đã nhận và bị bỏ qua bởi CAN.set_filters().

Cờ lỗi nhận

Kết quả của CAN.recv() bao gồm giá trị số nguyên tạo thành từ không hoặc nhiều cờ này được bitwise OR với nhau. Nếu được đặt, các cờ này chỉ ra các vấn đề tiềm ẩn chung khi nhận thông điệp CAN.

RECV_ERR_FULL: int

FIFO phần cứng nơi thông điệp này được nhận đã đầy và các thông điệp đến bổ sung có thể bị mất.

RECV_ERR_OVERRUN: int

FIFO phần cứng nơi thông điệp này được nhận đã đầy và một hoặc nhiều thông điệp đến đã bị mất.

Giá trị IRQ

IRQ_RX: int

Truyền vào đối số trigger của irq() để kích hoạt handler mỗi khi bộ điều khiển CAN nhận được một thông điệp hoàn chỉnh vào RX FIFO. Bên trong handler, đọc thông điệp bằng recv().

IRQ_TX: int

Truyền vào đối số trigger của irq() để kích hoạt handler mỗi khi bộ điều khiển CAN hoàn thành một lần thử truyền (thành công hoặc thất bại). Bên trong handler, sử dụng các bit bổ sung bên dưới để khôi phục mailbox nào đã hoàn thành và liệu nó có thất bại không -- xem Cờ IRQ.

IRQ_STATE: int

Truyền vào đối số trigger của irq() để kích hoạt handler mỗi khi bộ điều khiển chuyển đổi giữa các giá trị STATE_* (active / warning / passive / bus-off). Sử dụng state() bên trong handler để đọc trạng thái mới.

IRQ_TX_FAILED: int

Cờ trạng thái có thể được đặt trong irq().flags() khi sự kiện IRQ_TX kích hoạt. Chỉ ra lần thử truyền đã thất bại (thường là do cancel_send() được gọi, hoặc bộ điều khiển vào trạng thái lỗi).

IRQ_TX_IDX_SHIFT: int

Vị trí bit của trường chỉ số transmit-mailbox trong giá trị irq().flags() trong một sự kiện IRQ_TX. Chỉ số mailbox được trích xuất là (flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK.

IRQ_TX_IDX_MASK: int

Mặt nạ bit của trường chỉ số transmit-mailbox trong giá trị irq().flags() trong một sự kiện IRQ_TX. Chỉ số được trích xuất khớp với số nguyên được trả về bởi lệnh gọi send() tương ứng (số nguyên trong khoảng 0 đến TX_QUEUE_LEN).

Cờ IRQ

Gọi CAN.irq() đăng ký một handler ngắt với một hoặc nhiều trigger CAN.IRQ_RX, CAN.IRQ_TXCAN.IRQ_STATE.

Hàm trả về một đối tượng IRQ, và gọi hàm flags() trên đối tượng này trả về số nguyên chỉ ra (các) sự kiện trigger nào đã kích hoạt ngắt. Một handler CAN IRQ nên gọi hàm flags() lặp lại cho đến khi nó trả về 0.

Khi hàm flags() trả về với bit CAN.IRQ_TX được đặt, handler cũng có thể kiểm tra các bit cờ sau trong kết quả để biết thêm thông tin về sự kiện TX:

  • Bit CAN.IRQ_TX_FAILED được đặt nếu việc truyền thất bại. Thông thường điều này chỉ xảy ra nếu CAN.cancel_send() được gọi, mặc dù nó cũng có thể xảy ra nếu bộ điều khiển vào trạng thái lỗi.

  • CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFT là vùng được che bởi bitmask của giá trị flags chứa chỉ số của bộ đệm truyền đã tạo ra sự kiện. Đây sẽ là số nguyên trong khoảng 0 đến CAN.TX_QUEUE_LEN (không bao gồm) và sẽ khớp với kết quả của lần gọi CAN.send() trước đó.

Ví dụ 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)

Quan trọng

Nếu trigger CAN.IRQ_TX được đặt thì handler phải gọi flags() lặp lại cho đến khi nó trả về 0, như được hiển thị trong ví dụ này. Nếu không, các ngắt CAN có thể không được kích hoạt lại đúng cách.