class CAN -- Controller Area Network プロトコル

CAN は、共通バスに接続された 1 つ以上のノード間で、信頼性の高いリアルタイムなメッセージ配信を行うために使用される 2 線式のシリアルプロトコルです。CAN 2.0 は ISO-11898 で標準化され、現在では CAN Classic とも呼ばれています。

また、後方互換性のある新しいプロトコルとして CAN FD (CAN with Flexible Data-Rate) もあります。machine.CAN ドライバは現在 CAN FD 機能をサポートしていません。CAN FD が必要な場合は STM32 上で pyb.CAN を使用してください。

CAN のサポートには、コントローラ (多くの場合はマイクロコントローラ内蔵のペリフェラル) と、信号を CAN バスにレベルシフトするための外部トランシーバが必要です。

STM32 系の OpenMV Cam (M4 / M7 / H7 / H7 Plus / Pure Thermal / N6 と、トランシーバを配線した Arduino ブランドの派生機種) で利用できます。OpenMV Cam RT1062 (mimxrt ポート) および OpenMV Cam AE3 (alif ポート) ではまだサポートされていません。

machine.CAN インターフェースは 低レベルで基本的な CAN メッセージングインターフェースであり、CAN コントローラを、メッセージ送信用の優先度付き送信キュー、メッセージ受信用の受信キュー、エラー報告の仕組みとして抽象化します。

注釈

予定されている can および aiocan micropython-lib モジュールが、MicroPython で CAN を使用するための推奨される方法となります。

コンストラクタ

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

指定された id を持つ CAN コントローラオブジェクトを構築します:

  • id は特定の CAN コントローラオブジェクトを識別します。これはボードおよびポートに固有です。

  • その他のすべての引数は CAN.init() に渡されます。少なくとも 1 つの引数 (bitrate) を指定する必要があります。

このクラスの将来のバージョンでは、ハードウェアを構成するポート固有のキーワード引数をここで受け付けるようになる可能性があります。現在、そのようなキーワード引数は実装されていません。

ビットレート 500kbps で CAN コントローラ 1 を構築して初期化します:

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 ドライバはそれに応じてパラメータを計算します。このパラメータは、tseg1tseg2 が設定されている場合は無視されます。

  • sjw は、公称ビットに対するタイムクォンタ単位での再同期ジャンプ幅です。クラシック CAN では 1 から 4 (両端を含む) までの値を指定できます。

  • tseg1 は、公称ビットに対するタイムクォンタ単位でのサンプルポイントの位置を定義します。クラシック CAN では 1 から 16 (両端を含む) までの値を指定できます。これは ISO-11898 規格で定義されている Prop_SegPhase_Seg1 フェーズの合計です。この値を設定する場合は tseg2 も設定する必要があり、sample_point は無視されます。

  • tseg2 は、公称ビットに対するタイムクォンタ単位での送信ポイントの位置を定義します。クラシック CAN では 1 から 8 (両端を含む) までの値を指定できます。これは ISO-11898 規格の Phase_Seg2 に対応します。この値を設定する場合は tseg1 も設定する必要があります。

これらの引数が指定された場合、CAN コントローラは目的の bitrate と指定されたビットあたりのタイムクォンタの総数に対して正しく構成されます。これらがすべて指定されている場合、tseg1tseg2 の値は sample_point 引数より優先されます。

注釈

個々のコントローラハードウェアは、これらのパラメータの有効な値に対して追加の制約を持つ場合があり、指定された値がサポートされていない場合は ValueError を送出します。

注釈

特定のコントローラハードウェアは、オーバーサンプリングなどのハードウェア固有の機能のために追加のオプションのキーワードパラメータを受け付ける場合があります。

set_filters(filters: list | tuple | None) None

CAN コントローラに受信フィルタを設定します。filters には次のものを指定できます:

  • すべての受信メッセージを受け入れる場合は None、または

  • すべてのメッセージ受信を無効にする場合は [] または ()、または

  • フィルタ条件を定義する 1 つ以上の項目のイテラブル。各項目は、3 つの要素を持つタプルまたはリストである必要があります:

    • identifier は CAN 識別子 (int) です。

    • bit_mask は CAN 識別子フィールド内のビットのビットマスク (int) です。

    • flags は、メッセージフラグ で定義されているビットを 0 個以上設定した整数です。これは、受信メッセージが一致する必要があるプロパティを指定します。すべてのコントローラがすべてのフラグでのフィルタリングをサポートしているわけではなく、サポートされていないフラグが要求された場合は ValueError が送出されます。

bit_mask でマスクされたビットがメッセージ識別子とフィルタの identifier 値の間で一致し、かつフィルタに設定されたフラグが受信メッセージと一致する場合、受信メッセージは受け入れられます。

flags に CAN.FLAG_EXT_ID ビットが設定されている場合、フィルタは拡張 CAN ID のみに一致します。CAN.FLAG_EXT_ID ビットが設定されていない場合、フィルタは標準 CAN ID のみに一致します。

すべてのフィルタはコントローラ内で OR 結合されます。filters 引数に空のリストまたはタプルを渡すと、メッセージは受信されません。

一部の CAN コントローラでは、各フィルタを 1 つの受信 FIFO のみに関連付ける必要があります。これらの場合、引数内のフィルタ項目は利用可能な FIFO にラウンドロビン方式で割り当てられます。このドライバは受信 IRQ において FIFO を区別しません。

注釈

呼び出し元が CAN.FILTERS_MAX より多くの項目を持つイテラブルを渡した場合、ValueError が送出されます。

注釈

指定された ID 型に対して identifier または bit_mask のいずれかが範囲外の場合、理由 "invalid id" を伴う ValueError が送出されます。

すべての受信メッセージを受信します:

can.set_filters(None)

標準 ID 値 0x301 と 0x700 のメッセージのみを受信します:

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

標準 ID 値が 0x300-0x3FF の範囲にあるメッセージと、拡張 ID 値 0x50700 のメッセージのみを受信します:

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

このハードウェアコントローラがサポートする受信フィルタの最大数を読み取る定数値。

一部のコントローラは、使用するフィルタの数に関してより複雑なハードウェア制約を持つ場合があることに注意してください (たとえば、標準 ID フィルタと拡張 ID フィルタを別々に数えるなど)。これらの場合、FILTERS_MAX の上限を超えていなくても CAN.set_filtersValueError を送出することがあります。

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

新しい CAN メッセージをコントローラのハードウェア送信キューにコピーして、バスに送信します。送信キューは CAN 識別子の優先度でソートされた優先度付きキューです (数値の小さい識別子ほど優先度が高くなります)。

  • id は整数の CAN 識別子値です。

  • data は、CAN メッセージデータを含む bytes オブジェクト (または同様のもの)、あるいはリモート送信要求 (下記参照) を記述するものです。

  • flags は、メッセージフラグ で定義されているビットを 0 個以上設定した整数で、送信する CAN メッセージのプロパティ (拡張 ID、リモート送信要求など) を指定します。

メッセージがバスへの送信用に正常にキューイングされた場合、この関数は 0 から CAN.TX_QUEUE_LEN (排他的) の範囲の整数を返します。この値はメッセージが送信用にキューイングされた送信バッファのインデックスであり、CAN.cancel_send 関数や CAN.IRQ_TX イベントで使用できます。

キューが満杯の場合、送信は失敗し None が返されます。

指定された id 値が送信キュー内の既存のメッセージと同じ優先度を持ち、CAN コントローラハードウェアが同じ ID のメッセージをキューに追加された順序でバスに送信することを保証できない場合も、送信は失敗し None を返します。それでもメッセージをキューイングするには、flags 引数に CAN.FLAG_UNORDERED フラグを渡します。このフラグは、同じ CAN ID のメッセージを任意の順序でバスに送信してよいことを示します。

コントローラが "Bus Off" エラー状態にあるか、または無効になっている場合、この関数を呼び出すと OSError が送出されます。

注釈

この意図的に低レベルにした実装は、呼び出し元が送信メッセージのソフトウェアキューを確立できるように設計されています。

重要

CAN の "送信キュー" は FIFO キューではなく、優先度順に並べられています。最大 CAN.TX_QUEUE_LEN 個の項目を保持できますが、同時にキューイングできるメッセージには他のハードウェア制約がある場合があります。

リモート送信要求

flags 引数に CAN.FLAG_RTR ビットが設定されている場合、コントローラはメッセージの代わりにリモート送信要求を送信します。この場合、data 引数の内容は無視されます。コントローラは、DLC 長さフィールドが data 引数の長さと等しい要求を送信します。

3 バイトのペイロード 0a0b0c と標準 ID 0x200 を持つメッセージの送信を試みます:

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

空のペイロードと拡張 ID 0x180008 を持つメッセージの送信を試みます。同じ ID で送信される他のメッセージが既にキューイングされている場合に備えて、コントローラがこの ID のメッセージを任意の順序で送信できることを示します:

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

長さ 8 バイトと標準 ID 0x555 を持つリモート送信要求の送信を試みます:

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

CAN.set_filters() で設定されたフィルタに従ってコントローラが受信した CAN メッセージを返します。

この関数は 1 つのオプション引数を取ります。指定する場合は、少なくとも 4 個の要素を持つリストで、2 番目の要素は受信した任意の CAN メッセージを保持するのに十分な容量を持つ bytearray などのオブジェクトを参照する memoryview オブジェクトである必要があります (CAN Classic では 8 バイト、CAN FD では 64 バイト)。指定されたリストが成功結果として返され、関数内でのメモリ割り当てを回避します。

CAN コントローラがメッセージを受信していない場合、この関数は None を返します。

注釈

コントローラがメッセージを受信できるようになる前に CAN.set_filters を呼び出す必要があります。すべてのメッセージを受信するには、set_filters(None) を呼び出します。

CAN コントローラがメッセージを受信した場合、この関数は 4 個の要素を持つリストを返します:

  • インデックス 0 は受信したメッセージの CAN ID で、整数として返されます。

  • インデックス 1 は、受信したメッセージデータへのアクセスを提供する memoryview です。

    • arg が指定されていない場合、これは受信したバイト列を保持する memoryview です。この memoryview は、受信した任意の CAN メッセージを保持するのに十分な大きさで新たに割り当てられた bytearray によって裏付けられます。これにより、結果を将来の arg として安全に再利用でき、メモリ割り当てを節約できます。

    • arg が指定されている場合、指定された memoryview は受信したバイト列を正確に保持するようにサイズ変更されます。memoryview の裏付けとなるオブジェクトが任意の長さの CAN メッセージを保持できることを保証するのは呼び出し元の責任です。

  • インデックス 2 は、メッセージフラグ で定義されているビットを 0 個以上設定した整数です。これは受信したメッセージに関するメタデータを示します。

  • インデックス 3 は、受信エラーフラグ で定義されているビットを 0 個以上設定した整数です。0 以外の値は、CAN メッセージの受信時に潜在的な問題があることを示します。これらのフラグは、この関数が返るたびにコントローラ内でリセットされます。

リモート送信要求

リモート送信要求を受信した場合、インデックス 2 に CAN.FLAG_RTR ビットが設定され、インデックス 1 の memoryview はすべて 0 になり、その長さは受信した要求の 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

trigger でフラグが立てられたイベントの 1 つ以上が発生したときに呼び出される割り込み handler 関数を設定します。

  • handler は、割り込みイベントが発生したときに呼び出される関数です。ハンドラは、CAN インスタンスである引数を正確に 1 つだけ取る必要があります。

  • trigger は、割り込みを生成できるイベントを構成します。指定可能な値は、次のうち 1 つ以上のマスクです:

    • CAN.IRQ_RX イベントは、CAN コントローラがその RX FIFO に少なくとも 1 つのメッセージを受信した後に発生します (つまり CAN.recv() が正常に返ることを意味します)。

    • CAN.IRQ_TX イベントは、CAN コントローラが CAN バスへのメッセージの送信に成功するか、メッセージの送信に失敗した後に発生します。このトリガにはハンドラに対する追加要件があります。詳細は IRQ フラグ を参照してください。

    • CAN.IRQ_STATE イベントは、CAN コントローラがより深刻なエラー状態に遷移したときに発生します。更新された状態を取得するには CAN.state() を呼び出します。

  • hard が True の場合、ハード割り込みが使用されます。これにより、CAN コントローラのイベントとハンドラが呼び出されるまでの遅延が短縮されます。ハード割り込みハンドラはメモリを割り当てることができません。割り込みハンドラの記述 を参照してください。

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 が "ハード" でない場合) には、潜在的な競合状態があることに注意してください。

state() int

コントローラの現在の状態を示す整数値を返します。値は 状態 で定義されている値のいずれかになります。

深刻度の低いエラー状態は、バスが回復すると自動的にクリアされる場合がありますが、CAN.STATE_BUS_OFF 状態は CAN.restart() を呼び出すことによってのみ回復できます。

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

コントローラのエラーカウンタ値を返します。結果は 8 個の値のリストです。オプションの list パラメータが指定されている場合、割り当てを回避するために、指定されたリストオブジェクトが更新され結果として返されます。

リスト項目は次のとおりです:

  • TEC (送信エラーカウンタ) の値

  • REC (受信エラーカウンタ) の値

  • コントローラが Active 状態から Warning 状態に入った回数。

  • コントローラが Warning 状態から Error Passive 状態に入った回数。

  • コントローラが Error Passive 状態から Bus Off 状態に入った回数。

  • ハードウェアキュー内の保留中の TX メッセージの総数。

  • ハードウェアキュー内の保留中の RX メッセージの総数。

  • RX オーバーランが発生した回数。

注釈

コントローラによっては、これらの値は特定の値を超えると 0 に戻ってオーバーフローする場合があります。

注釈

コントローラが特定のカウンタをサポートしていない場合、そのリスト要素には None が返されます。

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

CAN コントローラに現在構成されているタイミングを示す要素のリストを返します。これはデバッグ目的でタイミングを検証するために使用できます。結果は 6 個の値のリストです。オプションの list パラメータが指定されている場合、割り当てを回避するために、指定されたリストオブジェクトが更新され結果として返されます。

リスト項目は次のとおりです:

  • コントローラが使用する正確なビットレート。ハードウェアの制約を満たすための量子化のため、CAN.init() に渡された bitrate 引数とは異なる場合があります。

  • 公称ビットに対するタイムクォンタ単位での再同期ジャンプ幅 (SJW)。CAN.init()sjw パラメータと同じ意味を持ちます。

  • 公称ビットに対するタイムクォンタ単位でのサンプルポイントの位置。CAN.init()tseg1 パラメータと同じ意味を持ちます。

  • 公称ビットに対するタイムクォンタ単位での送信ポイントの位置。CAN.init()tseg2 パラメータと同じ意味を持ちます。

  • CAN FD のタイミング情報。CAN FD をサポートしていないコントローラの場合、または CAN FD が初期化されていない場合は None になります。それ以外の場合は、上記の項目に対応するが CAN FD の BRS 機能に適用される 4 個の要素のネストされたリストになります。

  • オプションのコントローラ固有のタイミング情報。コントローラによっては、コントローラが何も報告しない場合は None になり、それ以外の場合は要素が特定のハードウェアコントローラに固有である一定長のリストになります。

注釈

CAN.init() が呼び出されていない場合でも、この関数は結果を返しますが、その結果はコントローラの内部状態に依存し、正確でない場合があります。

restart() None

他の内部状態をクリアすることなく、コントローラを STATE_BUS_OFF から脱出させます。一部のエラーカウンタもクリアされます (各エラー状態に入った回数は常にクリアされ、コントローラによっては TEC と REC もクリアされる場合があります)。

この関数を呼び出すと、送信待ちのメッセージもキャンセルされます。これらのメッセージに対して IRQ_TX 割り込みは配信されません。

この関数は、コントローラハードウェアが TEC と REC をゼロにするかどうかに応じて、コントローラを "Error Passive" 状態から脱出させる場合と脱出させない場合があることに注意してください。

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 ネットワークノードとしてアクティブです (有効なメッセージを ACK で応答し、現在の State に応じてエラーを送信する場合があります)。

MODE_SLEEP: int

CAN コントローラは低電力モードでスリープ状態にあります。コントローラによっては、CAN トラフィックを受信した場合にコントローラを起動して CAN.MODE_NORMAL に遷移させることをサポートする場合があります。

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

コントローラはアクティブで、TECREC のエラーカウンタはどちらも警告しきい値である 96 を下回っています。CAN.get_counters() を参照してください。

STATE_WARNING: int

コントローラはアクティブですが、TECREC のエラーカウンタの少なくとも 1 つが 96 から 127 の間にあります。CAN.get_counters() を参照してください。

STATE_PASSIVE: int

コントローラは "Error Passive" 状態にあり、アクティブエラーをバスに送信しなくなりますが、それ以外は機能します。この状態は、TECREC のエラーカウンタの少なくとも 1 つが 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() の各関数は、これらのフラグを 0 個以上ビット単位で OR 結合した整数値を受け付けるか、または返します。

FLAG_RTR: int

メッセージがリモート送信要求であることを示します。

FLAG_EXT_ID: int

設定されている場合、メッセージ識別子が拡張 (29 ビット) であることを示します。設定されていない場合、メッセージ識別子が標準 (11 ビット) であることを示します。

FLAG_UNORDERED: int

CAN.send()flags 引数に設定されている場合、同じ CAN ID のメッセージを任意の順序でバスに送信してよいことを示します。

それ以外の場合、同じ ID の複数のメッセージをキューイングしようとすると、コントローラハードウェアが順序を強制できない場合に CAN.send() が失敗することがあります。

このフラグは受信メッセージには決して設定されず、CAN.set_filters() では無視されます。

受信エラーフラグ

CAN.recv() の結果には、これらのフラグを 0 個以上ビット単位で OR 結合した整数値が含まれます。設定されている場合、これらのフラグは CAN メッセージの受信に関する潜在的な一般的問題を示します。

RECV_ERR_FULL: int

このメッセージが受信されたハードウェア FIFO が満杯であり、追加の受信メッセージが失われる可能性があります。

RECV_ERR_OVERRUN: int

このメッセージが受信されたハードウェア FIFO が満杯であり、1 つ以上の受信メッセージが失われています。

IRQ 値

IRQ_RX: int

CAN コントローラが RX FIFO に完全なメッセージを受信するたびにハンドラを起動させるには、irq()trigger 引数に渡します。ハンドラ内では recv() でメッセージを読み取ります。

IRQ_TX: int

CAN コントローラが送信試行を終了する (成功または失敗する) たびにハンドラを起動させるには、irq()trigger 引数に渡します。ハンドラ内では、以下の追加ビットを使用して、どのメールボックスが完了したか、および失敗したかどうかを取得します。IRQ フラグ を参照してください。

IRQ_STATE: int

コントローラが STATE_* の値 (active / warning / passive / bus-off) の間で遷移するたびにハンドラを起動させるには、irq()trigger 引数に渡します。ハンドラ内では state() を使用して新しい状態を読み取ります。

IRQ_TX_FAILED: int

IRQ_TX イベントが発生したときに irq().flags() に設定される場合があるステータスフラグ。送信試行が失敗したことを示します (通常は cancel_send() が呼び出されたか、コントローラがエラー状態に入ったため)。

IRQ_TX_IDX_SHIFT: int

IRQ_TX イベント中の irq().flags() 値内における送信メールボックスインデックスフィールドのビット位置。メールボックスインデックスは (flags >> IRQ_TX_IDX_SHIFT) & IRQ_TX_IDX_MASK として抽出されます。

IRQ_TX_IDX_MASK: int

IRQ_TX イベント中の irq().flags() 値内における送信メールボックスインデックスフィールドのビットマスク。抽出されたインデックスは、対応する send() 呼び出しによって返される整数 (0 から TX_QUEUE_LEN の範囲の int) と一致します。

IRQ フラグ

CAN.irq() を呼び出すと、CAN.IRQ_RXCAN.IRQ_TXCAN.IRQ_STATE の 1 つ以上のトリガで割り込みハンドラが登録されます。

この関数は IRQ オブジェクトを返し、このオブジェクトに対して flags() 関数を呼び出すと、どのトリガイベントが割り込みを発生させたかを示す整数が返されます。CAN IRQ ハンドラは、0 が返されるまで flags() 関数を繰り返し呼び出す必要があります。

flags() 関数が CAN.IRQ_TX ビットを設定して返した場合、ハンドラは TX イベントに関する追加情報のために結果内の次のフラグビットを確認することもできます:

  • 送信が失敗した場合、CAN.IRQ_TX_FAILED ビットが設定されます。通常これは CAN.cancel_send() が呼び出された場合にのみ発生しますが、コントローラがエラー状態に入った場合にも発生する可能性があります。

  • CAN.IRQ_TX_IDX_MASK << CAN.IRQ_TX_IDX_SHIFT は、イベントを生成した送信バッファのインデックスを保持する 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)

重要

CAN.IRQ_TX トリガが設定されている場合、この例に示すように、ハンドラは 0 が返されるまで flags() を繰り返し呼び出す 必要があります。そうしないと、CAN 割り込みが正しく再有効化されない場合があります。