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 can và aiocan đ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:
idxá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 tseg1 và tseg2 đượ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_SegvàPhase_Seg1như đượ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_Seg2trong 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ị tseg1 và tseg2 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
ValueErrornế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ặcMộ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ử:
identifierlà định danh CAN (int).bit_masklà mặt nạ bit cho các bit trong trường định danh CAN (int).flagslà 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ờ,ValueErrorsẽ đượ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_maskkhớp giữa định danh thông điệp và giá trịidentifiercủ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 bitCAN.FLAG_EXT_IDkhô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,ValueErrorsẽ được phát sinh.Ghi chú
Nếu
identifierhoặcbit_masknằm ngoài phạm vi cho loại ID được chỉ định,ValueErrorvớ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_filterscó thể phát sinhValueErrorngay cả khi giới hạnFILTERS_MAXchư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đếnCAN.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àmCAN.cancel_sendvà trong các sự kiệnCAN.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ề
Nonenế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_UNORDEREDtrong đố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_LENphầ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àiDLCbằ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
0a0b0cvà 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
memoryviewtham chiếu đếnbytearrayhoặ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_filtersphả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ọiset_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à
memoryviewgiữ các byte đã nhận.memoryviewnày được hỗ trợ bởi mộtbytearraymớ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ợmemoryviewcó 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_RTRsẽ được đặt ở Index 2 và memoryview ở Index 1 sẽ chứa toàn số không, với độ dài bằng trườngDLCcủ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_RXxả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_TXxả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_STATExả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ọiCAN.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đếnCAN.TX_QUEUE_LEN(không bao gồm). Thông thường đây sẽ là giá trị trước đó được trả về bởiCAN.send().Kết quả là
Truenế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à
Falsetrong 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_TXnê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_OFFchỉ có thể phục hồi bằng cách gọiCAN.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ề
Nonecho 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à
Nonenế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_OFFmà 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_TXnà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_TXhoặcIRQ_RXnà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()và 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ọiCAN.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_NORMALnế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.
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_ACTIVE: int¶
Bộ điều khiển đang hoạt động và cả hai bộ đếm lỗi
TECvàRECđều dưới ngưỡng cảnh báo là 96. XemCAN.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
TECvàRECnằm trong khoảng 96 và 127. XemCAN.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
TECvàRECbằng 128 hoặc lớn hơn, nhưngTECnhỏ hơn 255. XemCAN.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
TEClớ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 quaCAN.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()và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_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ố
flagscủaCAN.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.Giá trị IRQ¶
- IRQ_RX: int¶
Truyền vào đối số
triggercủairq()để 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ằngrecv().
- IRQ_TX: int¶
Truyền vào đối số
triggercủairq()để 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ố
triggercủairq()để 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ụngstate()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ệnIRQ_TXkích hoạt. Chỉ ra lần thử truyền đã thất bại (thường là docancel_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ệnIRQ_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ệnIRQ_TX. Chỉ số được trích xuất khớp với số nguyên được trả về bởi lệnh gọisend()tương ứng (số nguyên trong khoảng0đếnTX_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_TX và CAN.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ếuCAN.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_SHIFTlà 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ảng0đếnCAN.TX_QUEUE_LEN(không bao gồm) và sẽ khớp với kết quả của lần gọiCAN.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.