kelas CAN -- bus komunikasi jaringan area pengontrol

CAN mengimplementasikan dukungan untuk CAN klasik (bxCAN, digunakan pada OpenMV Cam M4 dan M7) maupun CAN FD (FDCAN, digunakan pada OpenMV Cam H7, H7 Plus dan Pure Thermal). Pada level fisik, bus CAN terdiri dari dua jalur, RX dan TX. Untuk menghubungkan OpenMV Cam ke bus CAN, Anda harus menggunakan transceiver CAN guna mengonversi sinyal logika CAN dari MCU ke level tegangan yang benar pada bus.

CAN klasik dalam mode loopback (tanpa transceiver):

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 dengan semua fitur opsional diaktifkan (bingkai FD, pengalihan laju bit, ID bingkai diperluas; fase arbitrasi 500 kbit/s, fase data 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)

Fungsi-fungsi modul CAN berikut dan argumennya tersedia untuk pengontrol CAN klasik maupun FD, kecuali dinyatakan lain.

Konstruktor

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

Buat objek CAN pada bus yang diberikan (indeks periferal integer, misalnya 1 untuk CAN1, 2 untuk CAN2). Tanpa parameter tambahan, objek dibuat tetapi tidak diinisialisasi (pengaturan bus sebelumnya dipertahankan, jika ada); jika argumen tambahan diberikan, bus akan diinisialisasi. Lihat CAN.init() untuk parameter yang tersedia.

CAN(2) terhubung ke pin header yang sama pada setiap OpenMV Cam yang mengekspos pyb.CAN (M4 / M7 / H7 / H7 Plus / Pure Thermal):

Sinyal

Pin header

Catatan

RX

P3

TX

P2

Periferal CAN hanya menyediakan sinyal level logika; transceiver CAN eksternal diperlukan untuk mengendalikan bus CAN yang sesungguhnya.

pyb.CAN tidak tersedia pada OpenMV Cam N6.

Metode

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

Inisialisasi bus CAN dengan parameter yang diberikan:

  • mode adalah salah satu dari: NORMAL, LOOPBACK, SILENT, SILENT_LOOPBACK

  • prescaler adalah nilai yang digunakan untuk membagi clock input CAN guna menghasilkan kuanta waktu bit nominal. Prescaler dapat berupa nilai antara 1 hingga 1024 inklusif untuk CAN klasik, dan antara 1 hingga 512 inklusif untuk CAN FD.

  • sjw adalah lebar lompatan resinkronisasi dalam satuan kuanta waktu untuk bit nominal; dapat berupa nilai antara 1 hingga 4 inklusif untuk CAN klasik, dan antara 1 hingga 128 inklusif untuk CAN FD.

  • bs1 menentukan lokasi titik sampel dalam satuan kuanta waktu untuk bit nominal; dapat berupa nilai antara 1 hingga 16 inklusif untuk CAN klasik, dan antara 2 hingga 256 inklusif untuk CAN FD.

  • bs2 menentukan lokasi titik transmisi dalam satuan kuanta waktu untuk bit nominal; dapat berupa nilai antara 1 hingga 8 inklusif untuk CAN klasik, dan antara 2 hingga 128 inklusif untuk CAN FD.

  • auto_restart mengatur apakah pengontrol akan secara otomatis mencoba memulai ulang komunikasi setelah memasuki status bus-off; jika ini dinonaktifkan maka restart() dapat digunakan untuk keluar dari status bus-off

  • baudrate jika baudrate selain 0 diberikan, fungsi ini akan mencoba menghitung secara otomatis waktu bit nominal CAN (menggantikan prescaler, bs1 dan bs2) yang memenuhi baik baudrate (dalam .1%) maupun sample_point yang diinginkan (ke 1% terdekat). Untuk kontrol lebih presisi atas timing CAN, atur parameter prescaler, bs1 dan bs2 secara langsung.

  • sample_point menentukan posisi sampel bit relatif terhadap keseluruhan waktu bit nominal, dinyatakan sebagai persentase integer dari waktu bit nominal. Nilai default sample_point adalah 75%. Parameter ini diabaikan kecuali baudrate diatur.

  • num_filter_banks untuk CAN klasik, ini adalah jumlah bank yang akan ditetapkan ke CAN(1), sisanya dari 28 ditetapkan ke CAN(2).

Parameter-parameter yang tersisa hanya ada pada papan dengan dukungan CAN FD, dan mengonfigurasi fitur opsional CAN FD Bit Rate Switch (BRS):

  • brs_prescaler adalah nilai yang digunakan untuk membagi clock input CAN FD guna menghasilkan kuanta waktu bit data. Prescaler dapat berupa nilai antara 1 hingga 32 inklusif.

  • brs_sjw adalah lebar lompatan resinkronisasi dalam satuan kuanta waktu untuk bit data; dapat berupa nilai antara 1 hingga 16 inklusif

  • brs_bs1 menentukan lokasi titik sampel dalam satuan kuanta waktu untuk bit data; dapat berupa nilai antara 1 hingga 32 inklusif

  • brs_bs2 menentukan lokasi titik transmisi dalam satuan kuanta waktu untuk bit data; dapat berupa nilai antara 1 hingga 16 inklusif

  • brs_baudrate jika baudrate selain 0 diberikan, fungsi ini akan mencoba menghitung secara otomatis waktu bit data CAN (menggantikan brs_prescaler, brs_bs1 dan brs_bs2) yang memenuhi baik brs_baudrate (dalam .1%) maupun brs_sample_point yang diinginkan (ke 1% terdekat). Untuk kontrol lebih presisi atas timing BRS, atur parameter brs_prescaler, brs_bs1 dan brs_bs2 secara langsung.

  • brs_sample_point menentukan posisi sampel bit relatif terhadap keseluruhan waktu bit nominal, dinyatakan sebagai persentase integer dari waktu bit nominal. Nilai default brs_sample_point adalah 75%. Parameter ini diabaikan kecuali brs_baudrate diatur.

Kuanta waktu tq adalah satuan waktu dasar untuk bus CAN. tq adalah nilai prescaler CAN dibagi PCLK1 (frekuensi bus periferal internal 1); lihat pyb.freq() untuk menentukan PCLK1.

Satu bit terdiri dari segmen sinkronisasi, yang selalu 1 tq. Kemudian diikuti oleh segmen bit 1, lalu segmen bit 2. Titik sampel berada setelah segmen bit 1 selesai. Titik transmisi berada setelah segmen bit 2 selesai. Laju baud adalah 1/bittime, di mana bittime adalah 1 + BS1 + BS2 dikalikan kuanta waktu tq.

Sebagai contoh, pada OpenMV Cam H7 (PCLK1 = 100 MHz), CAN 250 kbps dengan titik sampel 75% dapat dikonfigurasi sebagai prescaler=25, sjw=1, bs1=11, bs2=4: tq = 25 / 100 MHz = 250 ns, bittime = (1 + 11 + 4) × 250 ns = 4 µs, titik sampel = (1 + 11) / 16 = 75%, dan laju baud adalah 1 / 4 µs = 250 kHz.

Lihat bagian bxCAN / FDCAN pada manual referensi STM32 untuk MCU OpenMV Cam untuk detail lebih lanjut.

deinit() None

Matikan bus CAN.

restart() None

Paksa restart perangkat lunak pada pengontrol CAN tanpa mengatur ulang konfigurasinya.

Jika pengontrol memasuki status bus-off maka pengontrol tidak akan lagi berpartisipasi dalam aktivitas bus. Jika pengontrol tidak dikonfigurasi untuk restart secara otomatis (lihat init()) maka metode ini dapat digunakan untuk memicu restart, dan pengontrol akan mengikuti protokol CAN untuk keluar dari status bus-off dan masuk ke status error aktif.

state() int

Kembalikan status pengontrol. Nilai yang dikembalikan dapat berupa salah satu dari:

  • CAN.STOPPED -- pengontrol sepenuhnya mati dan direset;

  • CAN.ERROR_ACTIVE -- pengontrol aktif dan berada dalam status Error Active (baik TEC maupun REC kurang dari 96);

  • CAN.ERROR_WARNING -- pengontrol aktif dan berada dalam status Error Warning (setidaknya salah satu dari TEC atau REC adalah 96 atau lebih besar);

  • CAN.ERROR_PASSIVE -- pengontrol aktif dan berada dalam status Error Passive (setidaknya salah satu dari TEC atau REC adalah 128 atau lebih besar);

  • CAN.BUS_OFF -- pengontrol aktif tetapi tidak berpartisipasi dalam aktivitas bus (TEC melampaui batas 255).

info(list: list | None = None) list

Dapatkan informasi tentang status error pengontrol dan buffer TX dan RX. Jika list disediakan maka harus berupa objek daftar dengan setidaknya 8 entri, yang akan diisi dengan informasi tersebut. Jika tidak, daftar baru akan dibuat dan diisi. Dalam kedua kasus, nilai kembalian metode adalah daftar yang telah diisi.

Nilai-nilai dalam daftar adalah:

  • Nilai TEC

  • Nilai REC

  • jumlah kali pengontrol memasuki status Error Warning (diputar kembali ke 0 setelah 65535)

  • jumlah kali pengontrol memasuki status Error Passive (diputar kembali ke 0 setelah 65535)

  • jumlah kali pengontrol memasuki status Bus Off (diputar kembali ke 0 setelah 65535)

  • jumlah pesan TX yang tertunda

  • jumlah pesan RX yang tertunda pada fifo 0

  • jumlah pesan RX yang tertunda pada fifo 1

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

Konfigurasikan bank filter:

  • bank adalah bank filter pengontrol CAN klasik, atau indeks filter CAN FD, yang akan dikonfigurasi.

  • mode adalah mode operasi filter, lihat tabel di bawah.

  • fifo adalah fifo mana (0 atau 1) tempat pesan harus disimpan, jika diterima oleh filter ini.

  • params adalah array nilai yang mendefinisikan filter. Isi array bergantung pada argumen mode.

Isi array params untuk pengontrol CAN klasik (OpenMV Cam M4 / M7):

mode

Isi params

CAN.LIST16

Empat ID 16-bit yang akan diterima.

CAN.LIST32

Dua ID 32-bit yang akan diterima.

CAN.MASK16

Dua pasang id/mask 16-bit, misalnya (1, 3, 4, 4). Pasangan pertama (1, 3) menerima semua ID dengan bit 0 = 1 dan bit 1 = 0; pasangan kedua (4, 4) menerima semua ID dengan bit 2 = 1.

CAN.MASK32

Satu pasang id/mask 32-bit (selainnya sama dengan CAN.MASK16).

Isi array params untuk pengontrol CAN FD (OpenMV Cam H7 / H7 Plus / Pure Thermal):

mode

Isi params

CAN.RANGE

Dua ID yang membentuk rentang ID yang diterima.

CAN.DUAL

Dua ID yang akan diterima (misalnya (1, 2)).

CAN.MASK

Satu pasang (id, mask) (misalnya (0x111, 0x7FF)).

  • rtr Untuk pengontrol CAN klasik, ini adalah array boolean yang menyatakan apakah filter harus menerima pesan permintaan transmisi jarak jauh. Jika argumen ini tidak diberikan, defaultnya adalah False untuk semua entri. Panjangnya bergantung pada mode:

    mode

    len(rtr)

    Catatan

    CAN.LIST16

    4

    CAN.LIST32

    2

    CAN.MASK16

    2

    CAN.MASK32

    1

    Untuk CAN FD argumen ini diabaikan.

  • extframe Jika True bingkai akan memiliki pengidentifikasi diperluas (29 bit), jika tidak maka pengidentifikasi standar (11 bit) yang digunakan.

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

Hapus dan nonaktifkan bank filter:

  • bank adalah bank filter pengontrol CAN klasik, atau indeks filter CAN FD, yang akan dihapus.

  • extframe Untuk pengontrol CAN FD, jika True, hapus filter diperluas (dikonfigurasi dengan extframe=True), jika tidak maka hapus pengidentifikasi standar (dikonfigurasi dengan extframe=False).

any(fifo: int) bool

Kembalikan True jika ada pesan yang menunggu pada FIFO, jika tidak False.

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

Terima data pada bus:

  • fifo adalah integer, yang merupakan FIFO untuk menerima

  • list adalah objek daftar opsional yang digunakan sebagai nilai kembalian

  • timeout adalah batas waktu dalam milidetik untuk menunggu penerimaan.

Nilai kembalian: Sebuah daftar berisi lima nilai.

  • ID pesan.

  • Boolean yang menunjukkan apakah ID pesan adalah standar atau diperluas.

  • Boolean yang menunjukkan apakah pesan adalah pesan RTR.

  • Nilai FMI (Filter Match Index).

  • Array yang berisi data.

Jika list adalah None maka daftar baru akan dialokasikan, beserta objek bytes baru untuk menampung data (sebagai elemen kelima dalam daftar).

Jika list bukan None maka harus berupa objek daftar dengan setidaknya lima elemen. Elemen kelima harus berupa objek memoryview yang dibuat dari bytearray atau array bertipe 'B' atau 'b', dan array ini harus memiliki cukup ruang untuk setidaknya 8 byte. Objek daftar kemudian akan diisi dengan empat nilai kembalian pertama di atas, dan objek memoryview akan diubah ukurannya di tempat sesuai ukuran data dan diisi dengan data tersebut. Objek daftar dan memoryview yang sama dapat digunakan kembali dalam panggilan berikutnya ke metode ini, sehingga memberikan cara menerima data tanpa menggunakan heap. Contohnya:

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

Kirim pesan pada bus:

  • data adalah data yang akan dikirim (integer untuk dikirim, atau objek buffer).

  • id adalah id pesan yang akan dikirim.

  • timeout adalah batas waktu dalam milidetik untuk menunggu pengiriman.

  • rtr adalah boolean yang menentukan apakah pesan akan dikirim sebagai permintaan transmisi jarak jauh. Jika rtr adalah True maka hanya panjang data yang digunakan untuk mengisi slot DLC pada bingkai; byte aktual dalam data tidak digunakan.

  • extframe jika True bingkai akan memiliki pengidentifikasi diperluas (29 bit), jika tidak maka pengidentifikasi standar (11 bit) yang digunakan.

  • fdf untuk pengontrol CAN FD, jika diatur ke True, bingkai akan memiliki format bingkai FD, yang mendukung payload data hingga 64 byte.

  • brs untuk pengontrol CAN FD, jika diatur ke True, mode pengalihan laju bit diaktifkan, di mana fase data ditransmisikan pada laju bit yang berbeda. Lihat CAN.init() untuk parameter konfigurasi timing bit data.

Jika timeout adalah 0, pesan ditempatkan dalam buffer di salah satu dari tiga buffer hardware dan metode segera kembali. Jika ketiga buffer sedang digunakan, pengecualian akan dilemparkan. Jika timeout bukan 0, metode menunggu hingga pesan terkirim. Jika pesan tidak dapat dikirim dalam waktu yang ditentukan, pengecualian akan dilemparkan.

Nilai kembalian: None.

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

Daftarkan fungsi yang akan dipanggil ketika pesan diterima ke dalam FIFO yang kosong:

  • fifo adalah FIFO penerima.

  • fun adalah fungsi yang akan dipanggil ketika FIFO menjadi tidak kosong.

Fungsi callback menerima dua argumen: yang pertama adalah objek CAN itu sendiri; yang kedua adalah integer yang menunjukkan alasan callback:

Alasan

Arti

0

Pesan telah diterima ke dalam FIFO yang kosong.

1

FIFO penuh.

2

Pesan hilang karena FIFO penuh.

Contoh penggunaan 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)

Konstanta

Konstanta mode bus (argumen mode dari init()):

NORMAL: int

Pengontrol berpartisipasi secara normal pada bus -- mengirimkan bingkainya sendiri dan mengakui bingkai yang diterima dengan valid.

LOOPBACK: int

Mode loopback internal: pengontrol terputus dari pin dan mengarahkan bingkai yang dikirim langsung kembali ke jalur penerima. Berguna untuk pengujian mandiri tanpa transceiver.

SILENT: int

Mode hanya dengar: pengontrol menerima bingkai tetapi tidak pernah mengendalikan bus (tidak ada ACK, tidak ada transmisi). Berguna untuk pemantauan bus.

SILENT_LOOPBACK: int

Menggabungkan SILENT dan LOOPBACK: tidak ada aktivitas pin dan tidak ada pengakuan, dengan loopback internal TX ke RX.

Konstanta status pengontrol (dikembalikan oleh state()):

STOPPED: int

Pengontrol sepenuhnya mati dan direset.

ERROR_ACTIVE: int

Pengontrol aktif dan berada dalam status Error Active (baik TEC maupun REC kurang dari 96).

ERROR_WARNING: int

Pengontrol aktif dan berada dalam status Error Warning (setidaknya salah satu dari TEC atau REC adalah 96 atau lebih besar).

ERROR_PASSIVE: int

Pengontrol aktif dan berada dalam status Error Passive (setidaknya salah satu dari TEC atau REC adalah 128 atau lebih besar).

BUS_OFF: int

Pengontrol aktif tetapi tidak berpartisipasi dalam aktivitas bus (TEC melampaui batas 255).

Mode filter CAN klasik (argumen mode dari setfilter() pada OpenMV Cam M4 / M7):

LIST16: int

Array params filter berisi empat ID 16-bit yang akan diterima.

LIST32: int

Array params filter berisi dua ID 32-bit yang akan diterima.

MASK16: int

Array params filter berisi dua pasang (id, mask) 16-bit.

MASK32: int

Array params filter berisi satu pasang (id, mask) 32-bit.

Mode filter CAN FD (argumen mode dari setfilter() pada OpenMV Cam H7 / H7 Plus / Pure Thermal):

RANGE: int

Array params filter berisi dua ID yang membentuk rentang ID yang diterima.

DUAL: int

Array params filter berisi dua ID spesifik yang diterima.

MASK: int

Array params filter berisi satu pasang (id, mask).