leecrossun 2025. 3. 1. 20:26

CAN Tx

CAN_Handle의 구조체 멤버

  • Instance: CAN 인스턴스 지정
  • Init: CAN 초기화 매개변수 설정
    • Mode: Normal Mode, Loopback Mode, Silent Mode 등
    • Bit Timing 관련 요소: Prescaler(Time Quantum의 길이), SyncJumpWidth, TimeSeg1, TimeSeg2
    • AutoBusOff : 에러를 일으키는 노드를 자동으로 제외
    • AutoRetransmission : 전송자가 ACK를 받지 못하면 자동으로 재전송
    • AutoWakeup
    • TransmitFifoPriority

  • ReceiveFifoLocked
    • 0 : 3개의 메시지가 모두 채워지면 다음 메시지가 이전 것을 덮어씀
    • 1 : 3개의 메시지가 모두 채워지면 다음 메시지가 무시됨

 

CAN 비트 타이밍

http://www.bittiming.can-wiki.info/

 

CAN Bit Time Calculation

The following calculation sheet is mostly useful for classic CAN as defined in ISO-11898 before 2015. For the new CAN FD as defined in ISO-11898:2015 work is in Progress. CiA provides the document CiA 601-3 CAN FD bit-timing recommendations. By providing t

www.bittiming.can-wiki.info

 

  • CAN 통신에서는 한 비트가 네 개의 세그먼트로 나뉘며, CAN bus의 원하는 bitrate를 얻으려면 세그먼트의 width를 적절히 조정해야 함
  • 각 세그먼트는 time quanta의 측면에서 설명 ( time quantum : 모든 configuration value의 가장 작은 time unit )

  • 동기화 세그먼트(Synchronization Segment)
  • 전파 세그먼트(Propagation Segment)
  • 페이즈 세그먼트 1(Phase Segment 1)
  • 페이즈 세그먼트 2(Phase Segment 2)
  • 비트 타이밍은 타임 퀀텀(Time Quantum, Tq) 단위로 설정
    • 타임 퀀텀의 길이는 CAN 페리페럴에 공급되는 클럭 주파수에 따라 결정
      • HSE(고속 외부 클럭)에서 50MHz의 PLL 출력 클럭을 생성하고, APB1 버스에 25MHz를 공급한 경우, CAN1이 APB1 버스에 연결되어 있으므로 CAN1의 입력 클럭도 25MHz가 됨
        • Prescaler = 1일 때, CAN은 25MHz를 직접 사용
        • Prescaler = 5일 때, 5로 나누어 5MHz를 사용

비트 타이밍의 각 요소는 타임 퀀텀 개수로 표현

  • 동기화 세그먼트 = 1Tq (고정)
  • 전파 세그먼트 + 페이즈 세그먼트 1 = 8Tq
  • 페이즈 세그먼트 2 = 1Tq=> 총 10Tq가 한 비트를 구성

비트 타이밍을 적절히 조정하면 원하는 비트 레이트를 설정할 수 있음

  • If you increase the bit duration by including more and more TQs for each segment, then you may minimize the transmission errors and signal can be carried over longer distances but bus throughput decreases

  • 예를 들어, 테이블의 가장 첫번째 설정(Prescaler=5)에서는 1Mbps의 비트 레이트를 달성할 수 있음
  • 비트 타이밍을 과도하게 줄이면 전송 속도는 증가하지만, 장거리 통신에서 문제가 발생
  • 따라서 CAN Bit Time 계산기를 사용하여 최적의 값을 설정하는 것이 중요
void CAN1_Init(void)
{
	// CAN Controller setting
	hcan1.Instance = CAN1;
	hcan1.Init.Mode = CAN_MODE_LOOPBACK;
	hcan1.Init.AutoBusOff = DISABLE;
	hcan1.Init.AutoRetransmission = ENABLE;
	hcan1.Init.AutoWakeUp = DISABLE;
	hcan1.Init.ReceiveFifoLocked = DISABLE;
	hcan1.Init.TimeTriggeredMode = DISABLE;
	hcan1.Init.TransmitFifoPriority = DISABLE;
	
	// CAN bit timings setting
	hcan1.Init.Prescaler = 5;
	hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
	hcan1.Init.TimeSeg1 = CAN_BS1_8TQ;
	hcan1.Init.TimeSeg2 = CAN_BS2_1TQ;
	
	if(HAL_CAN_Init(&hcan1) != HAL_OK) Error_handler();
	
}

 

CAN Transmit mailboxes

  • 빈 상태: Mailbox가 비어 있음.
    • 3개의 mailboxes 존재
  • Pending 상태: TXRQ 비트가 설정되어 전송 요청 후, 우선순위 확인을 위해 대기
  • Schedule 상태: 스케줄러에 의해 우선순위가 높은 Mailbox로 선정되어 전송 대기
    • 처음 전송해야 하는 mailbox 선택하고, identifier, the data length code (DLC), data 설정
    • Control register에서 TXRQ bit 설정하여 전송 요청
  • Transmit 상태: 버스가 Idle 상태가 되면, 실제 전송이 시작되고, 버스의 경합(Arbitration)에 참여
  • 전송 성공:
    • Mailbox는 빈 상태로 복귀하며, TXOK 비트 설정 (CAN_TSR register)
  • 전송 실패:
    • Arbitration Lost (ALST) 또는 Transmission Error (TERR) (CAN_TSR register)
    • 자동 재전송 (Auto Retransmission) 기능이 활성화되어 있다면, Mailbox는 다시 Schedule 상태로 돌아가 재시도
    • 만약 재전송 기능이 비활성화되어 있다면, 실패 시 Mailbox는 비워짐
  • 우선순위 변경:
    • 만약 다른 Mailbox가 Pending 상태에 진입하여 우선순위가 더 높다면, 현재 Schedule 상태에 있는 Mailbox는 다시 Pending 상태로 돌아갈 수 있음

 

CAN TX 데이터 구조체

  • CAN_TXHeaderTypeDef
    • 전송 프레임의 헤더 정보를 설정
    • Standard/Extended Identifier: 식별자
    • IDE: 메시지 식별자 타입 (표준 프레임 vs 확장 프레임)
    • RTR: 데이터 프레임인지 요청(Remote) 프레임인지를 결정
    • DLC: 데이터 길이 (payload의 바이트 수)
    • 데이터는 이 구조체에 포함되지 않고 별도의 외부 버퍼로 전달됨

CAN 송신 함수 HAL_CAN_AddTxMessage 구현 및 송신 완료 확인

**HAL_CAN_AddTxMessage**(**CAN_HandleTypeDef** *hcan, **const** **CAN_TxHeaderTypeDef** *pHeader, **const** **uint8_t** aData[], **uint32_t** *pTxMailbox)

  • 폴링 방식 사용:
    • 전송 요청이 대기 중인지 확인 : CAN_IsTxMessagePending API 사용
    • 이 API는 선택한 메일박스에 전송 요청이 pending 상태이면 1, 그렇지 않으면 0을 반환
    • while 루프로 대기하여, 반환 값이 0이 될 때까지 기다린 후 송신 완료 확인
  • 전송 완료 후:
    • 송신 성공 시 TXOK 비트가 설정되고, 메일박스가 비워지며, UART 를 통해 “전송 성공” 메시지를 출력
void CAN_Tx(void)
{
	CAN_TxHeaderTypeDef TxHeader;
	uint32_t TxMailbox;
	uint8_t message[5] = {'H', 'E', 'L', 'L', 'O'};

	TxHeader.DLC = 5;
	TxHeader.StdId = 0x65D;
	TxHeader.IDE = CAN_ID_STD;
	TxHeader.RTR = CAN_RTR_DATA;

	if(HAL_CAN_AddTxMessage(&hcan1, &TxHeader, message, &TxMailbox)!= HAL_OK) Error_handler();
	while(HAL_CAN_IsTxMessagePending(&hcan1, TxMailbox));

	sprintf(msg, "Message Transmitted\r\n");
	HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY);

}

 

bxCAN operating mode

  • Reset/Sleep Mode
    • 마이크로컨트롤러가 리셋되거나 CAN 컨트롤러가 리셋 상태
    • 송수신 불가
  • Initialization Mode
    • CAN 컨트롤러 초기화
    • 제어 레지스터의 Sleep 비트를 해제
    • CAN 초기화 함수(CAN Init)는 바로 이 작업부터 시작
    • 초기화 모드에서는 송수신 기능이 동작하지 않으므로, 초기화 작업이 안전하게 수행
  • Normal Mode
    • 초기화가 완료된 후, CAN 컨트롤러를 실제 송신(Tx) 및 수신(Rx) 기능 수행
    • HAL_CAN_Start 호출
      • INRQ 비트를 활성화하여 CAN 컨트롤러를 초기화 모드에서 일반 모드로 전환
    • CAN 컨트롤러가 정상적으로 버스에 참여하여 메시지를 송수신
// main함수에 CAN_Tx 이전에 Start 함수 호출해서 Normal Mode로 전환
HAL_CAN_Start(&hcan1);
CAN_Tx();

 

msp.c Initialization

void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan)
{
	GPIO_InitTypeDef gpio_can1;
	__HAL_RCC_CAN1_CLK_ENABLE();

	gpio_can1.Pin = GPIO_PIN_11 | GPIO_PIN_12;
	gpio_can1.Mode = GPIO_MODE_AF_PP;
	gpio_can1.Pull = GPIO_NOPULL;
	gpio_can1.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
	gpio_can1.Alternate = GPIO_AF9_CAN1;
	HAL_GPIO_Init(GPIOA, &gpio_can1);
}

 

CAN loopback connection details

 

  • 트랜시버 없이 테스트 (Loopback 모드 사용)
    • 트랜시버 모듈을 사용하지 않는다면, PA11 (CAN TX 핀)을 연결할 필요X
    • 루프백 모드는 내부적으로 동작하므로 RCS 라인도 연결 X
    • 해당 핀을 3.3V로 드라이브
    • 3.3V는 Nucleo 보드에서 제공되며, 3.3kΩ 저항을 통해 연결
    • 이렇게 연결하면 트랜시버 없이도 테스트 가능
  • 트랜시버를 사용하는 경우
    • 트랜시버를 사용할 경우, 3.3V DC, GND, CAN TX, CAN RX 연결
      • CAN_H, CAN_L 핀이 있으며, 이는 차동 신호를 사용
      • 역할 : 싱글 엔디드 신호를 차동 신호로 변환
  • 트랜시버 연결 방법
    • 트랜시버 모듈에 3.3V 전원을 공급(3.3V 이상 공급하지 않도록 주의)
    • GND를 정확히 연결
    • PA11 (CAN TX) → 트랜시버 CAN TX 핀 연결
    • PA12 (CAN RX) → 트랜시버 CAN RX 핀 연결
    • CAN_H, CAN_L 핀은 그대로 둠 (별도로 연결할 필요 없음)
    • 대부분의 트랜시버에는 120Ω 종단 저항이 포함되어 있음
      • 사용 중인 트랜시버 모듈의 회로도를 확인하여 120Ω 저항이 있는지 체크
  • Nucleo 보드에서 전원 및 GND 연결

  • 3.3V와 GND는 Nucleo 보드의 헤더에서 쉽게 얻을 수 있음
  • 3.3V → 트랜시버 3.3V 핀 연결
  • GND → 트랜시버 GND 핀 연결

 

Application Test

 

  • 모든 연결을 완료한 후, 테스트를 진행.
  • Logic Analyzer를 사용할 경우 CAN_TX 핀에 연결.
    • CAN_RX 핀은 연결하지 않음 (Loopback 모드에서는 내부에서 처리됨)
  • 로직 분석기가 아날로그 신호를 지원하면 CAN_H에 연결 가능
  • 아날로그 신호 지원이 없을 경우, CAN_TX 핀의 디지털 신호를 측정

로직 분석기로 CAN 메시지 디코딩

분석기 소프트웨어에서 CAN 분석기 추가

채널 선택: CAN 신호를 연결한 채널 지정

비트 레이트 설정: 500kbps (500000으로 입력)

메시지 디코딩 확인

  • Identifier (식별자): 65D (16진수).
  • 데이터: "hello" (ASCII 변환 가능).

 

Loopback 모드에서 ACK 문제

  • ACK 오류(NAK)가 발생하지만, 이는 정상적인 동작
    • 자체적으로 ACK 신호를 무시하고 재전송하지 않기 때문
  • 따라서 ACK 필드는 Recessive(1) 상태로 유지됨

 

비트 레이트 검증

  • SOF(Start of Frame, 시작 프레임) 확인: 첫 번째 지배적 비트(Dominant Bit).
  • 비트 지속 시간 측정:
    • SOF가 2마이크로초(2μs)라면 500kbps 설정이 올바름
반응형