본문 바로가기

CAN

4. 필터설정 (6) CAN_FilterConfTypeDef 구조체와 HAL_CAN_ConfigFilter 함수

CAN_FilterConfTypeDef 구조체는 CAN에서 사용되는 자료형 중 유일하게 CAN_HandleTypeDef 구조체에 포함되지 않습니다. 즉, 핸들과 독립적으로 작동합니다. 구조체는 다음과 같고 주의해야할 점은 맨 위 4개의 CAN_FiRx 레지스터에 삽입될 값들과 BankNumber 변수입니다. CAN_FiRx 레지스터에 삽입될 값들은 필터 뱅크의 길이 설정에 따라 각 변수의 값이 복사되는 레지스터의 위치가 달라지므로 필터를 설정할 때 특별히 주의가 필요합니다. 그 내용은 HAL_CAN_ConfigFilter 함수 안에서 필터 뱅크의 길이를 설정하는 블록 안에 그림으로 설명해 놓았습니다. 그리고 BankNumber 변수는 설정할 필터 뱅크의 번호가 아님에 주의해야 합니다. 설정할 필터 뱅크의 번호는 FilterNumber 변수에 입력해야 합니다. BankNumber 변수는 CAN2가 사용할 뱅크의 시작 번호로서 CAN2가 없는 STM32F091RC는 이 변수에 어떤 값을 입력해도 CAN_FMR 레지스터의의 CAN2SB 필드는 초기값인 14에서 변하지 않습니다.

 

typedef struct

{

      uint32_t FilterIdHigh;

      uint32_t FilterIdLow;

      uint32_t FilterMaskIdHigh;

      uint32_t FilterMaskIdLow;

      /* ↑↑ CAN_FiRx 레지스터에 삽입될 값. 하지만 필터의 길이에 따라 위치가 달라진다. */

      /* ↓↓ 필터 설정 레지스터에 어떤 값을 쓸지 결정하기 위한 변수 */

      uint32_t FilterFIFOAssignment;

      uint32_t FilterNumber; /* 설정할 필터 뱅크의 번호이다. */

      uint32_t FilterMode;

      uint32_t FilterScale;

      uint32_t FilterActivation;

      uint32_t BankNumber; /* CAN2가 사용할 뱅크의 시작 번호이다. */

}CAN_FilterConfTypeDef;



HAL_StatusTypeDef HAL_CAN_ConfigFilter( CAN_HandleTypeDef *hcan, CAN_FilterConfTypeDef *sFilterConfig)

{

uint32_t filternbrbitpos = 0; /* 필터 번호와 동일한 비트 번호에 1이 쓰여진다 */

      filternbrbitpos = (1U) << sFilterConfig->FilterNumber;



      /* 필터 초기화 모드로 진입 */

      hcan->Instance->FMR |= (uint32_t)CAN_FMR_FINIT;



      /* CAN2가 사용할 필터 뱅크의 시작 번호 설정 */

      hcan->Instance->FMR &= ~((uint32_t)CAN_FMR_CAN2SB);

      hcan->Instance->FMR |= (uint32_t)(sFilterConfig->BankNumber << 8U);



      /* 설정할 필터 뱅크를 비활성화 한다. */

      hcan->Instance->FA1R &= ~(uint32_t)filternbrbitpos;



      /* 필터 뱅크의 필터 레지스터 길이를 16비트로 설정한 경우 */

      if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT)

      {

          /* CAN_FS1R 레지스터의 해당 비트를 클리어 */



          hcan->Instance->FS1R &= ~(uint32_t)filternbrbitpos;



          hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR1 =

          ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdLow) << 16U) |

          (0x0000FFFF & (uint32_t)sFilterConfig->FilterIdLow);



          hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR2 =

          ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |

          (0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh);

          /* 이 블록이 수행되면 필터 뱅크는 다음과 같이 설정된다. */   

filtermaskidlow filteridlow filtermaskidhigh filteridhigh can_fxr1 can_fxr2

 

   

  }

      /* 필터 뱅크의 필터 레지스터 길이를 32비트로 설정한 경우 */

      if (sFilterConfig->FilterScale == CAN_FILTERSCALE_32BIT)

      {

          /* CAN_FS1R 레지스터의 해당 비트를 1로 설정 */



          hcan->Instance->FS1R |= filternbrbitpos;



          hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR1 =

          ((0x0000FFFF & (uint32_t)sFilterConfig->FilterIdHigh) << 16U) |

          (0x0000FFFF & (uint32_t)sFilterConfig->FilterIdLow);



          hcan->Instance->sFilterRegister[sFilterConfig->FilterNumber].FR2 =

          ((0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdHigh) << 16U) |

          (0x0000FFFF & (uint32_t)sFilterConfig->FilterMaskIdLow);

 

          /* 이 블록이 수행되면 필터 뱅크는 다음과 같이 설정된다. */

filtermaskidlow filteridlow filtermaskidhigh filteridhigh can_fxr1 can_fxr2

 

     }



      /* CAN_FM1R에서 필터 뱅크의 모드를 설정한다. */

      if (sFilterConfig->FilterMode == CAN_FILTERMODE_IDMASK) /* 마스크 모드라면 */

      {

          /* CAN_FM1R의 해당 비트를 클리어 한다. */

          hcan->Instance->FM1R &= ~(uint32_t)filternbrbitpos;

      }

      else // 리스트 모드라면

      {

          /* CAN_FM1R의 해당 비트를 1로 설정한 한다. */

          hcan->Instance->FM1R |= (uint32_t)filternbrbitpos;

      }



      /* 필터 뱅크에 배정할 RX FIFO를 결정한다. */

      if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0) // RxX FIFO 0을 배정한다면

      {

          /* CAN_FFA1R의 해당 비트를 클리어한다. */

          hcan->Instance->FFA1R &= ~(uint32_t)filternbrbitpos;

      }



      if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO1) // RxX FIFO 1을 배정한다면

      {

        /* CAN_FFA1R의 해당 비트를 1로 셋한다. */

        hcan->Instance->FFA1R |= (uint32_t)filternbrbitpos;

}



      /* 필터를 설정해도 활성화하지 않을 수 있다. */

      if (sFilterConfig->FilterActivation == ENABLE) // 필터를 활성화 한다면

      {

          /* CAN_FA1R 레지스터의 해당 비트를 1로 셋한다.

          hcan->Instance->FA1R |= filternbrbitpos;

      }



      /* CAN_FMR 레지스터의 FINIT를 클리어하여 필터 초기화 모드를 탈출한다. */

      hcan->Instance->FMR &= ~((uint32_t)CAN_FMR_FINIT);

      return HAL_OK;

}