본문 바로가기
프로그래밍/Keil RTX

[C/Keil RTX] CAN 통신

by 채연2 2023. 1. 3.

 

 

 

 

요즘 하고 있는 프로젝트에서 제일 많이 사용하는 통신이 CAN 통신이다. CAN 통신은 이 프로젝트를 통해 처음 접해 보기도 했고, 그렇게 세세하게 알아보지 못한 채 개발을 해서 오늘에서야 세부적으로 파헤쳐보려고 한다.

 


CAN 통신

배경

Controller Arean Network의 약자로 차량 내에서 호스트 컴퓨터 없이 마이크로 컨트롤러나 장치들이 서로 통신하기 위해 설계된 표준 통신 규격이다.  메시지 기반 프로토콜이며 최근에는 차량 뿐만 아니라 산업용 자동화기기나 의료용 장비, 엘리베이터 등에서도 종종 사용되고 있다. 각 제어기들 간의 통신을 위해 주로 사용되는 non-host 버스 방식의 메시지 기반 네트워크 프로토콜이다.

 

CAN 통신이 개발되기 전까진 과거에는 모듈들이 통신하기 위해 UART 통신을 사용했다고 한다. 하지만 UART 통신은 모듈이 추가될 때마다 연결 선이 계속 추가적으로 필요하게 되고 (Point-To-Point 방식) 그로 인해 차량 공간을 많이 차지하게 되면서 차량 무게를 증가시키고 원가도 상승시켰다.

 

CAN 통신이 개발되면서 여러 개의 모듈을 제어할 수 있어 연결 선이 감소하게 되고 (Multi Master 방식), 차량 공간 및 차량 무게, 원가 또한 감소시킬 수 있게 되었다.

 


특징

  • Multi Master 통신 방식 : 통신 버스를 공유하고 있는 CAN 컨트롤러들은 모두가  Master 역할을 하여 언제든지 버스를 사용하고 싶을 때 사용 가능.
  • 노이즈에 매우 강함 : RS485 통신과 비슷하게 twist pair 2선을 사용하여 전기적 차동쌍방식(Differential) 통신을 하여 전기적인 노이즈에 매우 강함.
  • 표준 프로토콜 시장성 뛰어남 : 많은 업체들이 경쟁적으로 CAN 칩을 제작하고 있으며 비용 또한 저렴함. CAN 프로토콜은 호스트 CPU에 내장된 CAN 컨트롤러 칩이나 호스트 CPU에 장착된 CAN 주변장치에서 실행됨.
  • 통신 속도 빠름 : 최대 1Mbps 까지 사용 가능
  • 먼 거리 통신 가능 : 최대 1000m 까지도 40kbps 속도로 통신 가능함.
  • HW적으로 설정된 특정 ID 수신 가능 : CAN 에는 수신 필터가 있어 필터 설정 방법에 따라 정해진 ID, 특정 그룹 또는 전체 수신이 가능함.
  • 실시간 메시지 통신 가능 : 한 번에 8개의 데이터 전송하는 HW 패킷 제공함.
  • 우선순위 설정 가능
  • 사용 전선의 양 감소 가능

통신 방법

  1. 각 메시지는 자신의 고유 ID를 가짐. (CAN 2.0A = 11bit, CAN 2.0B = 29bit [확장형] )
  2. 모든 노드는 버스 IDLE 상태에서 데이터 전송이 가능함
  3. 메시지 충돌 중재는 ID를 통해 우선 순위 결정
  4. 수신 노드는 메시지 ID를 확인하여 무시 또는 저장함
  5. 수신 노드는 메시지 수신 후 ACK 신호를 발생시킴
  6. 메시지가 에러가 있다고 판단되면 ERR 신호를 발생시킴

CAN 메시지 구성

  • SOF (Start Of Frame) - 1bit: 주요 비트로, 메시지의 시작을 표시한다.
  • Identifier - 11bit or 29bit : 메시지를 식별할 수 있는 식별자이다. 메시지의 우선 순위를 지정한다. 프레임은 11bit 및 29bit를 가질 수 있다.
  • RTR (Remote Transmission Request) : 단일 원격 전송 요청. 리모트 프레임과 데이터 프레임을 구별하는 역할을 한다.
  • IDE (IDentifier Extension) : 표준과 확장 프레임을 구분한다.
  • r0 : 역 비트
  • DLC (Data Length Code) - 1bit: 데이터 필드 바이트의 길이를 나타낸다.
  • 0...8 Bytes Data - 64bit : 데이터 필드 영역
  • CRC (Cyclic Redundancy Check) - 15bit : 오류 검출에 사용된다. 
  • ACK - 1bit : 메시지를 정확하게 수신한 모든 CAN 컨트롤러는 메시지 끝에 ACK 비트를 전송한다. 전송 노드는 버스 상에 ACK 비트 유무를 확인하고, ACK 비트가 발견되지 않을 경우 전송 재시도 한다.
  • EOF (End of Frame) - 7bit : 프레임 종료 필드로 CAN 프레임의 종료를 나타낸다.
  • IFS (Inter-Frame Space) - 7bit : 컨트롤러가 요구하는 시간의 양을 포함하며, 메시지 버퍼 영역에서 적절한 위치로 정확하게 수신된 프레임을 이동시킨다.

Keil 에서의 CAN 통신 예제

CAN 모듈 설정

CLK_EnableModuleClock(CAN2_MODULE);

SYS->GPD_MFPH = SYS_GPD_MFPH_PD9MFP_CAN2_TXD | SYS_GPD_MFPH_PD8MFP_CAN2_RXD

NVIC_SetPriority(CAN2_IRQn, 1);
NVIC_EnableIRQ(CAN2_IRQn);

 

CAN 버스 확인

if (CAN2->ERR != 0) {
    printf("CAN2 bus error! : %X\n", CAN2->ERR);
}

 

CAN 메시지 받을 ID 설정

if (CAN_SetRxMsg(CAN2, MSG(0x01), CAN_EXT_ID, CAN_ID_00000001) == FALSE) {
	printf("[CAN_ID_00000001] set RX message object failed\n");
}

 

 

CAN 메시지 보내기

STR_CANMSG_T sMsg;

sMsg.FrameType        = CAN_DATA_FRAME;
sMsg.IdType           = CAN_EXT_ID;
sMsg.Id               = CAN_ID_00000002;
sMsg.DLC              = 1;
sMsg.Data[0]          = 0xC1;
	
if (CAN_Transmit(CAN2, MSG(0x02), &sMsg) == FALSE) {
	printf("[CAN_ID_00000002] send Tx message failed.\n");
}

 

 

CAN IRQ Handler 함수 정의하기

void CAN2_IRQHandler(void)
{
    uint32_t u8IIDRstatus;
    u8IIDRstatus = CAN2->IIDR;
    STR_CANMSG_T msg;

    /* check status and error interrupt flag */
    if (u8IIDRstatus != CAN_STATUS_INT && (u8IIDRstatus >= 0x01) && (u8IIDRstatus <= 0x10)) {
        if (CAN_Receive(CAN2, u8IIDRstatus - 1, &msg) == TRUE) {
            //insert your code
        }

        /* clear pending int */
        CAN_CLR_INT_PENDING_BIT(CAN2, u8IIDRstatus - 1);
    }
}

 

 

 

 

 

 

320x100

댓글