본문 바로가기
임베디드 개발/STM32 (ARM Cortex-M)

STM32 ] CAN 통신 설정 (bxCAN peripheral)

by eteo 2023. 1. 27.

 

bxCAN main features

STM32F4xx 시리즈에는 bxCAN이라고 불리는 CAN 모듈(컨트롤러)이 2개 있으며 특징은 다음과 같다.

 

  • 2 CAN Controllers are avialable. CAN1 and CAN2
  • CAN1 is called Master bxCAN and CAN2 is called Slave
  • Both supports CAN protocol version 2.0A and B
  • Bit rates up to 1 Mbit/s
  • Three transmit mailboxes
  • Two receive FIFOs with three stages
  • 28 filter banks shared between CAN1 and CAN2

 

 

 

Tx mailboxes

유저가 CAN 메시지를 구성해 담을 수 있는 3개의 메일박스가 존재하며, 셋 중 어떤 메일박스를 사용할지는 Transmission Scheduler가 identifier priority를 확인하여 결정한다.

 

 

Acceptance filters

사용자 정의로 수신 메시지를 필터링할 수 있는 28개의 Acceptance Filter banks가 존재한다. 필요한 메시지만 수신하고 나머지는 무시한다.

 

 

Receive FIFO

하드웨어단에서 수신 메시지를 저장하는 목적의 2개의 FIFO가 있고, 각 FIFO는 3개의 CAN 메시지를 저장할 수 있다. 유저가 할일은 인터럽트가 걸리면 CAN ISR로 가서 FIFO를 읽는것 뿐이다. 만약 읽지 않아서 FIFO에 4번째 메시지가 들어온다면 overrun될 것이다.

 

 

 

 

 

Dual CAN block diagram

 

 

 

CAN2가 Slave로 지칭되는 이유는 CAN1과 달리 SRAM memory에 직접 접근이 안되기 때문이다, 따라서 설정을 할 때 CAN1의 도움을 받아야하고 CAN2 이전에 CAN1이 먼저 활성화되어야한다.

 

CAN1과 CAN2 둘 다 3개의 mailbox와 2개의 FIFO(3 stages)를 가지고 있지만 Acceptance Filter는 둘 이 공유하고 있다.

 

 

 

 

 

 

 

CUBEMX 설정

 

 

Clock 설정

 

 

 

Activate CAN

 

 

 

CAN1_RX, CAN1_TX 핀

 

자세한 파라미터 설정은 아래에서 설명하겠다.

 

 

 

 

 

 

 

CAN bit Timings 설정

 

CAN 메시지 구조에서 one bit 는 다음의 4가지 time segments 로 구성되며, CAN bit rate 설정을 위해서는 각 segments 의 width 를 정해야 한다.

 

1. Synchronization Segment

2. Propagation Segment

3. Phase Segment 1

4. Phase Segment 2

 

이 때, 설정 가능한 최소 시간 단위인 Time Quanta라는 개념을 두고, 각 세그먼트에 몇 Time Quanta를 배치할지 설정하여 one bit 당 전송시간을 결정하면 최종 bit rate 가 정해진다.

 

 

Time Quanta는 CAN 모듈에 공급되는 Clock Prequency에 따라 정할 수 있는데 CAN1, CAN2는 APB1에서 클락을 공급받고 현재 APB1 clock은 45MHz로 설정되어있다.

 

Reference Manual p. 67

 

 

그리고 CAN 초기화 설정값인 Prescaler를 1로 하여 CAN 모듈에 45MHz를 그대로  공급할 수 있고, 더 높은 값을 설정하여 공급 클락을 slow down 할 수도 있다.

 

 

만약 Prescaler 값을 5로 설정한다면, 45MHz / 5 = 9MHz 이고 Time Quanta 는 1.1111...^10-7

대략 111.111ns가 된다.

 

이 값이 bit rate 설정에 쓰이는 최소 단위가 되고, 각 segment에 몇 Time Quanta를 배치할 지 결정하여 one bit 당 전송시간을 결정하는 것이다.

 

segments에 더 많은 Time Quanta를 배치하게 되면 bit rate 는 줄어들 것이다. 낮은 bit rate 에선 전송 에러가 줄고 더 먼거리에서 통신이 가능할 수 있지만 bus 전체의 throughput은 줄어든다.

반면 segments에 더 적은 Time Quanta를 배치했을 때 bit rate 는 올라가고 bus 의 throughput은 증가하지만 비교적 먼거리 통신에서 에러가 발생할 가능성이 있다.

 

 

 

 

 

 

CAN Bit Time Calculator

 

CAN 통신 bit rate 설정을 위해 Time Quanta 를 계산하고 Segment에 배치하는 일은 까다로우므로 대신 해주는 계산해주는 사이트가 있다.

 

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

 

 

 

위 사이트에서 STM bxCAN을 선택하고 Clock Rate는 APB1 클락인 45MHz를 입력한 뒤 Request Table 을 클릭한다.

 

 

 

 

아래와 같이 가능한 Bit Rate 와 설정 값들을 보여준다.

 

 

 

 

이 중 노란색이 추천 값이므로 테이블을 참고하여 설정하면 된다.

 

 

 

예를 들어 500Kbps 추천값으로 설정한다면 아래와 같이 CUBEMX에서 설정하면 된다.

 

 

 

Sync_Seg  = 항상 1 tq

Seg 1(Prop_Seg+Phase_Seg1) = 15 tq

Seg 2(Phase_Seg2) = 2 tq

 

하면 합이 18 tq이고, Prescaler 값이 5이니 CAN peripheral에 공급되는 clock이 9MHz

 

9MHz / 18 tq = 500Kbps 를 얻어낼 수 있다.

 

 

 

 

그리고 샘플링 포인트는 Phase_Seg1과 Phase_seg2 사이인데 one Bit의 number of time quanta가 18이고 Sync_seg+Prop_seg+Phase_seg1 = 16이니 sample point는 88.9% 가 된다.

 

 

 

 

 

 

CAN_HandleTypeDef 와 CAN_InitTypeDef 구조체 및 초기화

 

typedef struct __CAN_HandleTypeDef
{
  CAN_TypeDef                 *Instance;                 /*!< Register base address */
  CAN_InitTypeDef             Init;                      /*!< CAN required parameters */
  __IO HAL_CAN_StateTypeDef   State;                     /*!< CAN communication state */
  __IO uint32_t               ErrorCode;                 /*!< CAN Error code.
} CAN_HandleTypeDef;

 

typedef struct
{
  uint32_t Prescaler;                  /*!< Specifies the length of a time quantum.
                                            This parameter must be a number between Min_Data = 1 and Max_Data = 1024. */

  uint32_t Mode;                       /*!< Specifies the CAN operating mode.
                                            This parameter can be a value of @ref CAN_operating_mode */

  uint32_t SyncJumpWidth;              /*!< Specifies the maximum number of time quanta the CAN hardware
                                            is allowed to lengthen or shorten a bit to perform resynchronization.
                                            This parameter can be a value of @ref CAN_synchronisation_jump_width */

  uint32_t TimeSeg1;                   /*!< Specifies the number of time quanta in Bit Segment 1.
                                            This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_1 */

  uint32_t TimeSeg2;                   /*!< Specifies the number of time quanta in Bit Segment 2.
                                            This parameter can be a value of @ref CAN_time_quantum_in_bit_segment_2 */

  FunctionalState TimeTriggeredMode;   /*!< Enable or disable the time triggered communication mode.
                                            This parameter can be set to ENABLE or DISABLE. */

  FunctionalState AutoBusOff;          /*!< Enable or disable the automatic bus-off management.
                                            This parameter can be set to ENABLE or DISABLE. */

  FunctionalState AutoWakeUp;          /*!< Enable or disable the automatic wake-up mode.
                                            This parameter can be set to ENABLE or DISABLE. */

  FunctionalState AutoRetransmission;  /*!< Enable or disable the non-automatic retransmission mode.
                                            This parameter can be set to ENABLE or DISABLE. */

  FunctionalState ReceiveFifoLocked;   /*!< Enable or disable the Receive FIFO Locked mode.
                                            This parameter can be set to ENABLE or DISABLE. */

  FunctionalState TransmitFifoPriority;/*!< Enable or disable the transmit FIFO priority.
                                            This parameter can be set to ENABLE or DISABLE. */

} CAN_InitTypeDef;

 

 

이 중 Prescaler, SyncJumpWidth, TimeSeg1, TimeSeg2 이 위에서 설명한 Bit Timing 설정을 위한 파라미터이다. 그리고  Mode는 Normal 모드로 사용할 지 혹은 테스트 모드로 사용할지 선택하는 파라미터이고, 나머지는 bxCAN 모듈 운용을 위한 기본 설정값들인데 레퍼런스 매뉴얼 CAN 컨트롤 레지스터(CAN_MCR) 파트에 설명이 나와있다.

 

TTCM: Time triggered communication mode. TTCAN 이라는게 있는데 그 지원기능인 것 같다. Disabled 해두면 된다.

참고자료 : http://www.eskorea.net/html/data/technique/warcan_06.pdf

 

ABOM: Automatic bus-off management. Bus-Off에서 Recovery 하는 기능을 자동으로 할지 소프트웨어에 맡길지 선택한다. Enable 하면 128 occurrences of 11 consecutive recessive bits 감지 이후 자동 복구. Enabled.

 

AWUM: Automatic wakeup mode. 저전력 모드와 관련있다. Disabled.

 

NART: No automatic retransmission. 송신에 실패하면 하드웨어단에서 재전송 시도하는 기능이다. 0(Disabled)인 경우 자동으로 재전송한다.

 

RFLM: Receive FIFO locked mode. FIFO가 꽉찼을 때의 overrun 처리. Enable 하면 새로 들어오는 메시지는 무시되고 Disabled 하면 새로 들어온 메시지로 overwrite한다. Disabled.

 

TXFP: Transmit FIFO priority. 여러 메일박스가 pending 상태인 경우 우선순위 결정. Disabled 인 경우 identifier 가 낮은 메시지를 우선 전송하고, Enabled 인 경우 요청 순서대로 전송한다.

 

 

 

 

여기서 당황스러웠던 건 NART 비트의 설명이 CubeMX랑 정반대라서, 생성 코드나 매뉴얼 안보고 STM32CubeMX 툴만 사용해서 설정하는 사람들은 큰 낭패볼 수 있을 것 같다.

 

NART는 비트 네임에서도 알 수 있듯이 No automatic retransmission인데 MX툴에선 앞에 No가 없이 그냥 Automatic Retransmission 이라고만 써있다. STM32 커뮤니티에도 지적하는 사람이 몇 있던데 아직까지 안고쳐진것 같다.

 

 

 

 

 

 

 

 

 

이렇게 CAN1, CAN2를 설정 나면 다음과 같은 초기화 코드가 자동 생성된다.

 

  /* Initialize all configured peripherals */
  // ...
  MX_CAN1_Init();
  MX_CAN2_Init();
  // ...
  /* USER CODE BEGIN 2 */

 

 

 

HAL_CAN_Init() 함수는 또 HAL_CAN_MspInit() 함수를 호출하는데 그 안에서는 CAN Clock Enable 하고 CAN RX, TX 핀으로 쓰이는 GPIO Port 의 Clock Enable 그리고 GPIO 핀 관련 설정을 하고 있다.

 

만약 인터럽트를 쓴다면 여기에 인터럽트 관련 내용도 들어간다.

 

void HAL_CAN_MspInit(CAN_HandleTypeDef* canHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(canHandle->Instance==CAN1)
  {
  /* USER CODE BEGIN CAN1_MspInit 0 */

  /* USER CODE END CAN1_MspInit 0 */
    /* CAN1 clock enable */
    HAL_RCC_CAN1_CLK_ENABLED++;
    if(HAL_RCC_CAN1_CLK_ENABLED==1){
      __HAL_RCC_CAN1_CLK_ENABLE();
    }

    __HAL_RCC_GPIOD_CLK_ENABLE();
    /**CAN1 GPIO Configuration
    PD0     ------> CAN1_RX
    PD1     ------> CAN1_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);

  /* USER CODE BEGIN CAN1_MspInit 1 */

  /* USER CODE END CAN1_MspInit 1 */
  }
  else if(canHandle->Instance==CAN2)
  {
  /* USER CODE BEGIN CAN2_MspInit 0 */

  /* USER CODE END CAN2_MspInit 0 */
    /* CAN2 clock enable */
    __HAL_RCC_CAN2_CLK_ENABLE();
    HAL_RCC_CAN1_CLK_ENABLED++;
    if(HAL_RCC_CAN1_CLK_ENABLED==1){
      __HAL_RCC_CAN1_CLK_ENABLE();
    }

    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**CAN2 GPIO Configuration
    PB12     ------> CAN2_RX
    PB6     ------> CAN2_TX
    */
    GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_CAN2;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN CAN2_MspInit 1 */

  /* USER CODE END CAN2_MspInit 1 */
  }
}

 

 

 

 

 

bxCAN 의 operating mode

 

bxCAN 의 operating mode 는 Sleep, initialization, Normal 모드가 있는데 하드웨어 Reset 시 sleep 모드 상태이고 초기화 함수를 호출하면 initialization 모드에 들어간다.

 

그리고 bxCAN 을 사용해 송수신을 하려면 먼저 normal 모드에 들어가야 하는데 그 역할을 하는게 HAL_CAN_Start() 함수이다. USER CODE 2 부분에 넣어주면 된다.

 

  /* USER CODE BEGIN 2 */
  HAL_CAN_Start(&hcan1);
  HAL_CAN_Start(&hcan2);
  /* USER CODE END 2 */

 

 

 

 

 

 

Reference : FastBit Embedded Brain Academy

 

 

CAN 송수신 다음글 :

2023.01.29 - [DSP, MCU/STM32 (ARM Cortex-M)] - STM32 ] CAN 송수신

 

STM32 ] CAN 송수신

CAN 통신 설정 이전글 : 2023.01.27 - [DSP, MCU/STM32 (ARM Cortex-M)] - STM32 ] CAN 통신 설정 (bxCAN peripheral) STM32 ] CAN 통신 설정 (bxCAN peripheral) HTML 삽입 미리보기할 수 없는 소스 STM32F4xx 시리즈에는 bxCAN이라고

eteo.tistory.com