class CAN -- 控制器區域網路通訊匯流排¶
CAN 同時支援傳統 CAN(bxCAN,用於 OpenMV Cam M4 與 M7)以及 CAN FD(FDCAN,用於 OpenMV Cam H7、H7 Plus 與 Pure Thermal)控制器。在實體層上,CAN 匯流排由兩條線路 RX 與 TX 組成。若要將 OpenMV Cam 連接至 CAN 匯流排,您必須使用 CAN 收發器,將來自 MCU 的 CAN 邏輯訊號轉換為匯流排上正確的電壓位準。
迴路測試(無收發器)模式下的傳統 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 影格、位元率切換、延伸影格 ID;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 CAN 控制器。
建構子¶
- class pyb.CAN(bus: int | str, *args, **kwargs)¶
在指定的
bus(一個整數周邊索引,例如CAN1為1、CAN2為2)上建構一個 CAN 物件。若未提供其他參數,則僅建立物件但不進行初始化(它會保留先前的匯流排設定,若有的話);若提供額外引數,則會初始化匯流排。可用參數請參閱CAN.init()。在每一款公開
pyb.CAN的 OpenMV Cam(M4 / M7 / H7 / H7 Plus / Pure Thermal)上,CAN(2)都接到相同的排針接腳:訊號
排針接腳
備註
RXP3TXP2CAN 周邊裝置僅提供邏輯位準訊號;要驅動實際的 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 輸入時脈分頻以產生標稱位元時間量子的數值。對傳統 CAN,prescaler 可介於 1 至 1024(含)之間;對 CAN FD,可介於 1 至 512(含)之間。
sjw 是標稱位元的重新同步跳躍寬度,以時間量子為單位;對傳統 CAN,可介於 1 至 4(含)之間;對 CAN FD,可介於 1 至 128(含)之間。
bs1 以標稱位元的時間量子為單位,定義取樣點的位置;對傳統 CAN,可介於 1 至 16(含)之間;對 CAN FD,可介於 2 至 256(含)之間。
bs2 以標稱位元的時間量子為單位,定義傳送點的位置;對傳統 CAN,可介於 1 至 8(含)之間;對 CAN FD,可介於 2 至 128(含)之間。
auto_restart 設定控制器在進入匯流排關閉(bus-off)狀態後是否會自動嘗試重新啟動通訊;若停用此功能,則可使用
restart()來離開匯流排關閉狀態baudrate 若提供非 0 的 baudrate,此函式將嘗試自動計算 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 輸入時脈分頻以產生資料位元時間量子的數值。prescaler 可介於 1 至 32(含)之間。
brs_sjw 是資料位元的重新同步跳躍寬度,以時間量子為單位;可介於 1 至 16(含)之間
brs_bs1 以資料位元的時間量子為單位,定義取樣點的位置;可介於 1 至 32(含)之間
brs_bs2 以資料位元的時間量子為單位,定義傳送點的位置;可介於 1 至 16(含)之間
brs_baudrate 若提供非 0 的 baudrate,此函式將嘗試自動計算 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 prescaler 值除以 PCLK1(內部周邊匯流排 1 的頻率);請參閱
pyb.freq()來判定 PCLK1。單一位元由同步區段(永遠為 1 tq)組成。接著是位元區段 1,然後是位元區段 2。取樣點位於位元區段 1 結束之後。傳送點位於位元區段 2 結束之後。鮑率為 1/bittime,其中 bittime 為 1 + BS1 + BS2 乘以時間量子 tq。
舉例來說,在 OpenMV Cam H7(PCLK1 = 100 MHz)上,取樣點為 75% 的 250 kbps CAN 可設定為
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。更多細節請參閱 OpenMV Cam 之 MCU 對應的 STM32 參考手冊中的 bxCAN / FDCAN 章節。
- restart() None¶
強制以軟體方式重新啟動 CAN 控制器,且不重設其組態。
若控制器進入匯流排關閉狀態,則它將不再參與匯流排活動。若控制器未設定為自動重新啟動(請參閱
init()),則可使用此方法觸發重新啟動,控制器將依循 CAN 通訊協定離開匯流排關閉狀態並進入錯誤主動(error active)狀態。
- state() int¶
回傳控制器的狀態。回傳值可為下列之一:
CAN.STOPPED—— 控制器完全關閉並已重設;CAN.ERROR_ACTIVE—— 控制器開啟且處於錯誤主動(Error Active)狀態(TEC 與 REC 均小於 96);CAN.ERROR_WARNING—— 控制器開啟且處於錯誤警告(Error Warning)狀態(TEC 或 REC 至少一者為 96 或以上);CAN.ERROR_PASSIVE—— 控制器開啟且處於錯誤被動(Error Passive)狀態(TEC 或 REC 至少一者為 128 或以上);CAN.BUS_OFF—— 控制器開啟但不參與匯流排活動(TEC 溢位超過 255)。
- info(list: list | None = None) list¶
取得控制器錯誤狀態以及 TX 與 RX 緩衝區的相關資訊。若提供 list,則它應為一個至少有 8 個項目的 list 物件,這些資訊將被填入其中。否則,將建立一個新的 list 並填入資訊。在兩種情況下,方法的回傳值都是已填入的 list。
list 中的值為:
TEC 值
REC 值
控制器進入錯誤警告(Error Warning)狀態的次數(超過 65535 後回繞至 0)
控制器進入錯誤被動(Error Passive)狀態的次數(超過 65535 後回繞至 0)
控制器進入匯流排關閉(Bus Off)狀態的次數(超過 65535 後回繞至 0)
待傳送的 TX 訊息數量
fifo 0 上待接收的 RX 訊息數量
fifo 1 上待接收的 RX 訊息數量
- 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 引數。
傳統 CAN 控制器(OpenMV Cam M4 / M7)的 params 陣列內容:
mode
params 內容
CAN.LIST16四個將被接受的 16 位元 ID。
CAN.LIST32兩個將被接受的 32 位元 ID。
CAN.MASK16兩組 16 位元 id/遮罩配對,例如
(1, 3, 4, 4)。第一組(1, 3)接受所有 bit 0 = 1 且 bit 1 = 0 的 ID;第二組(4, 4)接受所有 bit 2 = 1 的 ID。CAN.MASK32一組 32 位元 id/遮罩配對(其餘與
CAN.MASK16相同)。CAN FD 控制器(OpenMV Cam H7 / H7 Plus / Pure Thermal)的 params 陣列內容:
mode
params 內容
CAN.RANGE兩個構成所接受 ID 範圍的 ID。
CAN.DUAL兩個將被接受的 ID(例如
(1, 2))。CAN.MASK一組
(id, mask)配對(例如(0x111, 0x7FF))。rtr 對傳統 CAN 控制器而言,這是一個布林值陣列,用於指定濾波器是否應接受遠端傳輸要求(remote transmission request)訊息。若未提供此引數,則所有項目預設為
False。其長度取決於 mode:mode
len(rtr)備註
CAN.LIST164
CAN.LIST322
CAN.MASK162
CAN.MASK321
對 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 設定者)。
- recv(fifo: int, list: list | None = None, *, timeout: int = 5000) list¶
在匯流排上接收資料:
fifo 是一個整數,表示要接收的 FIFO
list 是一個選用的 list 物件,用作回傳值
timeout 是等待接收的逾時時間,以毫秒為單位。
回傳值:包含五個值的 list。
訊息的 id。
一個布林值,指示訊息 ID 為標準或延伸。
一個布林值,指示訊息是否為 RTR 訊息。
FMI(Filter Match Index,濾波器比對索引)值。
包含資料的陣列。
若 list 為
None,則會配置一個新的 list,並配置一個新的 bytes 物件來容納資料(作為 list 中的第五個元素)。若 list 不為
None,則它應為一個至少有五個元素的 list 物件。第五個元素應為一個 memoryview 物件,由 bytearray 或型別為 'B' 或 'b' 的 array 所建立,且此陣列必須有足夠空間容納至少 8 個位元組。接著,list 物件將被填入上述前四個回傳值,而 memoryview 物件會就地調整大小至資料大小並填入該資料。同一個 list 與 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 是要傳送的資料(要傳送的整數,或一個 buffer 物件)。
id 是要傳送之訊息的 id。
timeout 是等待傳送的逾時時間,以毫秒為單位。
rtr 是一個布林值,指定是否應將訊息作為遠端傳輸要求傳送。若 rtr 為 True,則僅使用 data 的長度來填入影格的 DLC 欄位;data 中的實際位元組則不會被使用。
extframe 若為 True,影格將使用延伸識別碼(29 位元),否則使用標準識別碼(11 位元)。
fdf 對 CAN FD 控制器而言,若設為 True,影格將採用 FD 影格格式,可支援最多 64 位元組的資料負載。
brs 對 CAN FD 控制器而言,若設為 True,則啟用位元率切換模式,在此模式下資料階段會以不同的位元率傳輸。資料位元時序的設定參數請參閱
CAN.init()。
若 timeout 為 0,訊息會被放入三個硬體緩衝區之一,方法隨即立刻回傳。若三個緩衝區都正在使用中,則會擲出例外。若 timeout 不為 0,則方法會等待直到訊息傳送完成。若訊息無法在指定時間內傳送,則會擲出例外。
回傳值:
None。
- rxcallback(fifo: int, fun: Callable[[CAN, int], None] | None) None¶
註冊一個函式,當訊息被接受並進入一個空的 FIFO 時呼叫該函式:
fifo 是接收的 FIFO。
fun 是當 FIFO 變為非空時要呼叫的函式。
此回呼函式接受兩個引數:第一個是 CAN 物件本身;第二個是一個整數,指示觸發回呼的原因:
原因
意義
0一則訊息已被接受並進入一個空的 FIFO。
1FIFO 已滿。
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)
常數¶
匯流排模式常數(
init()的mode引數):控制器狀態常數(由
state()回傳):傳統 CAN 濾波器模式(OpenMV Cam M4 / M7 上
setfilter()的mode引數):CAN FD 濾波器模式(OpenMV Cam H7 / H7 Plus / Pure Thermal 上
setfilter()的mode引數):