class CAN – Controller Area Network 프로토콜

CAN은 공통 버스에 연결된 하나 이상의 노드 간에 신뢰성 있는 실시간 메시지 전달에 사용되는 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 카메라(M4 / M7 / H7 / H7 Plus / Pure Thermal / N6 및 트랜시버를 연결한 Arduino 브랜드 변형)에서 사용할 수 있습니다. OpenMV Cam RT1062(mimxrt 포트)나 OpenMV Cam AE3(alif 포트)에서는 아직 지원되지 않습니다.

machine.CAN 인터페이스는 저수준 기본 CAN 메시징 인터페이스로, CAN 컨트롤러를 메시지 전송을 위한 발신 우선순위 큐, 메시지 수신을 위한 수신 큐, 그리고 오류 보고 메커니즘으로 추상화합니다.

참고

계획 중인 canaiocan micropython-lib 모듈이 MicroPython에서 CAN을 사용하는 권장 방법이 될 것입니다.

생성자

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

주어진 id의 CAN 컨트롤러 객체를 생성합니다:

  • id 는 특정 CAN 컨트롤러 객체를 식별합니다. 이는 보드 및 포트마다 다릅니다.

  • 그 외의 모든 인수는 CAN.init() 로 전달됩니다. 적어도 하나의 인수(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 는 공칭 비트에 대한 타임 퀀타 단위의 재동기화 점프 폭입니다. classic CAN에서는 1에서 4까지(포함)의 값일 수 있습니다.

  • tseg1 은 공칭 비트에 대한 타임 퀀타 단위로 샘플 포인트의 위치를 정의합니다. classic CAN에서는 1에서 16까지(포함)의 값일 수 있습니다. 이는 ISO-11898 표준에 정의된 Prop_SegPhase_Seg1 단계의 합입니다. 이 값이 설정되면 tseg2 도 반드시 설정되어야 하며 sample_point 는 무시됩니다.

  • tseg2 는 공칭 비트에 대한 타임 퀀타 단위로 전송 포인트의 위치를 정의합니다. classic CAN에서는 1에서 8까지(포함)의 값일 수 있습니다. 이는 ISO-11898 표준의 Phase_Seg2 에 해당합니다. 이 값이 설정되면 tseg1 도 반드시 설정되어야 합니다.

이 인수들이 지정되면 CAN 컨트롤러는 원하는 bitrate 와 지정된 비트당 총 타임 퀀타 수에 맞게 올바르게 구성됩니다. 이들이 모두 제공되면 tseg1tseg2 값이 sample_point 인수보다 우선합니다.

참고

개별 컨트롤러 하드웨어는 이 매개변수들의 유효한 값에 대해 추가 제약이 있을 수 있으며, 주어진 값이 지원되지 않으면 ValueError 를 발생시킵니다.

참고

특정 컨트롤러 하드웨어는 오버샘플링과 같은 하드웨어별 기능을 위해 추가 선택적 키워드 매개변수를 받을 수 있습니다.

set_filters(filters: list | tuple | None) None

CAN 컨트롤러에 수신 필터를 설정합니다. filters 는 다음 중 하나일 수 있습니다:

  • 모든 수신 메시지를 수락하는 None, 또는

  • 모든 메시지 수신을 비활성화하는 [] 또는 (), 또는

  • 필터 기준을 정의하는 하나 이상의 항목으로 이루어진 이터러블. 각 항목은 세 개의 요소를 가진 튜플 또는 리스트여야 합니다:

    • identifier 는 CAN 식별자(int)입니다.

    • bit_mask 는 CAN 식별자 필드의 비트에 대한 비트 마스크(int)입니다.

    • flags메시지 플래그 에 정의된 비트가 0개 이상 설정된 정수입니다. 이는 수신 메시지가 일치해야 하는 속성을 지정합니다. 모든 컨트롤러가 모든 플래그에 대한 필터링을 지원하는 것은 아니며, 지원되지 않는 플래그가 요청되면 ValueError 가 발생합니다.

수신 메시지는 bit_mask 로 마스킹된 비트가 메시지 식별자와 필터 identifier 값 사이에서 일치하고, 필터에 설정된 플래그가 수신 메시지와 일치할 경우 수락됩니다.

플래그에 CAN.FLAG_EXT_ID 비트가 설정되어 있으면 필터는 Extended CAN ID에만 일치합니다. CAN.FLAG_EXT_ID 비트가 설정되어 있지 않으면 필터는 Standard CAN ID에만 일치합니다.

모든 필터는 컨트롤러에서 OR 연산으로 결합됩니다. filters 인수로 빈 리스트나 튜플을 전달하면 어떤 메시지도 수신되지 않습니다.

일부 CAN 컨트롤러는 각 필터가 하나의 수신 FIFO에만 연결되도록 요구합니다. 이 경우 인수의 필터 항목들이 사용 가능한 FIFO에 라운드 로빈 방식으로 할당됩니다. 이 드라이버는 수신 IRQ에서 FIFO들을 구분하지 않습니다.

참고

호출자가 CAN.FILTERS_MAX 보다 많은 항목을 가진 이터러블을 전달하면 ValueError 가 발생합니다.

참고

identifier 또는 bit_mask 가 지정된 ID 유형에 대한 범위를 벗어나면 “invalid id” 사유와 함께 ValueError 가 발생합니다.

예제

모든 수신 메시지를 받습니다:

can.set_filters(None)

Standard ID 값 0x301과 0x700인 메시지만 받습니다:

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

Standard ID 값이 0x300-0x3FF 범위인 메시지와 Extended ID 값 0x50700인 메시지만 받습니다:

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

이 하드웨어 컨트롤러가 지원하는 최대 수신 필터 개수를 읽는 상수 값입니다.

일부 컨트롤러는 사용 중인 필터 개수에 대해 더 복잡한 하드웨어 제약이 있을 수 있다는 점에 유의하세요(예: Standard 및 Extended ID 필터를 독립적으로 계산). 이 경우 FILTERS_MAX 한도를 초과하지 않더라도 CAN.set_filtersValueError 를 발생시킬 수 있습니다.

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

새 CAN 메시지를 컨트롤러의 하드웨어 전송 큐로 복사하여 버스로 전송합니다. 전송 큐는 CAN 식별자 우선순위로 정렬된 우선순위 큐입니다(숫자가 낮은 식별자가 더 높은 우선순위를 갖습니다).

  • id 는 정수 CAN 식별자 값입니다.

  • data 는 CAN 메시지 데이터를 담고 있거나 Remote Transmission Request를 설명하는 bytes 객체(또는 유사한 것)입니다(아래 참조).

  • flags메시지 플래그 에 정의된 비트가 0개 이상 설정된 정수로, 발신 CAN 메시지의 속성(Extended ID, Remote Transmission Request 등)을 지정합니다.

메시지가 버스 전송을 위해 성공적으로 큐에 추가되면 이 함수는 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 개의 항목을 담을 수 있지만 동시에 큐에 추가될 수 있는 메시지에 대해 다른 하드웨어 제약이 있을 수 있습니다.

Remote Transmission Request

flags 인수에 CAN.FLAG_RTR 비트가 설정되면 컨트롤러는 메시지 대신 Remote Transmission Request를 전송합니다. 이 경우 data 인수의 내용은 무시됩니다. 컨트롤러는 DLC 길이 필드가 data 인수의 길이와 같은 요청을 전송합니다.

예제

3바이트 페이로드 0a0b0c 와 Standard ID 0x200으로 메시지 전송을 시도합니다:

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

빈 페이로드와 Extended ID 0x180008로 메시지 전송을 시도합니다. 동일한 ID를 가진 다른 메시지가 이미 전송 대기 중일 경우를 대비해, 컨트롤러가 이 ID를 가진 메시지를 임의의 순서로 전송할 수 있음을 나타냅니다:

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

길이 8바이트와 Standard ID 0x555로 Remote Transmission Request 전송을 시도합니다:

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

CAN.set_filters() 로 설정된 필터에 따라 컨트롤러가 수신한 CAN 메시지를 반환합니다.

이 함수는 하나의 선택적 인수를 받습니다. 제공되는 경우 이는 최소 4개의 요소를 가진 리스트여야 하며, 두 번째 요소는 수신된 모든 CAN 메시지(CAN Classic의 경우 8바이트, CAN FD의 경우 64바이트)를 담기에 충분한 용량을 가진 bytearray 또는 유사한 객체를 참조하는 memoryview 객체여야 합니다. 제공된 리스트가 성공 결과로 반환되며, 함수 내부에서의 메모리 할당을 피합니다.

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 메시지 수신 시 잠재적 문제를 나타냅니다. 이 플래그들은 이 함수가 반환될 때마다 컨트롤러 내부에서 재설정됩니다.

Remote Transmission Request

Remote Transmission Request가 수신되면 인덱스 2에 CAN.FLAG_RTR 비트가 설정되고, 인덱스 1의 memoryview는 수신된 요청의 DLC 필드와 같은 길이로 모두 0을 담게 됩니다.

예제
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 에 플래그로 지정된 이벤트 중 하나 이상이 발생했을 때 호출될 인터럽트 handler 함수를 설정합니다.

  • handler 는 인터럽트 이벤트가 트리거될 때 호출되는 함수입니다. 핸들러는 정확히 하나의 인수를 받아야 하며, 이는 CAN 인스턴스입니다.

  • trigger 는 인터럽트를 생성할 수 있는 이벤트를 구성합니다. 가능한 값은 다음 중 하나 이상의 마스크입니다:

    • CAN.IRQ_RX 이벤트는 CAN 컨트롤러가 RX FIFO로 최소 한 개의 메시지를 수신한 후 발생합니다(즉 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가 “hard”가 아닌 경우).

state() int

컨트롤러의 현재 상태를 나타내는 정수 값을 반환합니다. 값은 상태 에 정의된 값 중 하나가 됩니다.

덜 심각한 오류 상태는 버스가 복구되면 자동으로 해제될 수 있지만, CAN.STATE_BUS_OFF 상태는 CAN.restart() 를 호출해야만 복구할 수 있습니다.

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

컨트롤러의 오류 카운터 값을 반환합니다. 결과는 8개의 값으로 이루어진 리스트입니다. 선택적 list 매개변수가 지정되면 제공된 리스트 객체가 갱신되어 결과로 반환되며, 할당을 피할 수 있습니다.

리스트 항목은 다음과 같습니다:

  • TEC(Transmit Error Counter) 값

  • REC(Receive Error Counter) 값

  • 컨트롤러가 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를 0으로 만드는지 여부에 따라 컨트롤러가 “Error Passive” 상태에서 빠져나오게 할 수도 있고 그렇지 않을 수도 있다는 점에 유의하세요.

deinit() None

이전에 활성화된 CAN 인스턴스를 비활성화합니다. 대기 중인 모든 메시지(전송 및 수신)가 폐기되고 컨트롤러는 버스에서의 상호 작용을 멈춥니다. 이 인스턴스를 다시 사용하려면 CAN.init() 를 호출하세요.

이 함수를 호출해도 IRQ_TXIRQ_RX 인터럽트는 호출되지 않습니다.

CAN.restart() 도 참조하세요.

상수

TX_QUEUE_LEN: int

컨트롤러의 발신 하드웨어 메시지 큐에 대기시킬 수 있는 최대 CAN 메시지 개수. CAN.send(), CAN.cancel_send()IRQ 플래그 에서 사용하는 “전송 버퍼 인덱스”가 이 범위 안에 있게 됩니다.

모드

이 값들은 CAN.init() 에 전달되는 컨트롤러 동작 모드를 나타냅니다. 모든 컨트롤러가 모든 모드를 지원하는 것은 아닙니다.

실행 중인 컨트롤러의 모드를 변경하려면 CAN.deinit() 를 호출한 다음 새 모드로 CAN.init() 를 다시 호출해야 합니다.

MODE_NORMAL: int

컨트롤러가 표준 CAN 네트워크 노드로 활성화되어 있습니다(유효한 메시지를 확인 응답하며 현재 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 오류 카운터 중 최소 하나가 96에서 127 사이입니다. CAN.get_counters() 를 참조하세요.

STATE_PASSIVE: int

컨트롤러가 “Error Passive” 상태로, 더 이상 능동적 오류를 버스에 전송하지 않지만 그 외에는 정상 작동합니다. 이 상태는 TECREC 오류 카운터 중 최소 하나가 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

메시지가 remote transmission request임을 나타냅니다.

FLAG_EXT_ID: int

설정되면 메시지 식별자가 Extended(29비트)임을 나타냅니다. 설정되지 않으면 메시지 식별자가 Standard(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가 가득 차서 하나 이상의 수신 메시지가 손실되었습니다.

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_RX, CAN.IRQ_TX, CAN.IRQ_STATE 중 하나 이상으로 인터럽트 핸들러를 등록합니다.

이 함수는 IRQ 객체를 반환하며, 이 객체의 flags() 함수를 호출하면 어떤 트리거 이벤트가 인터럽트를 발생시켰는지 나타내는 정수가 반환됩니다. CAN IRQ 핸들러는 flags() 함수가 0 을 반환할 때까지 반복적으로 호출해야 합니다.

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 트리거가 설정되면 핸들러는 이 예제에서처럼 flags()0 을 반환할 때까지 반복적으로 호출 해야 합니다. 그렇지 않으면 CAN 인터럽트가 올바르게 다시 활성화되지 않을 수 있습니다.