AnsweredAssumed Answered

STM32 CAN Filter

Question asked by afzal.uzair on Dec 19, 2012
Latest reply on Jul 28, 2016 by Lukasz Przenioslo
I am using STM32F103 board. I am testing CAN module in loop back mode. My code is working fine (provided below). I have following issues and observation about CAN...

(Observation 1) When I use FIFO 0, FMI field (RxMessage.FMI) of received message is two times the CAN_FilterNumber e.g. for CAN_FilterNumber=3, FMI value is 6, for CAN_FilterNumber=4, FMI value is 8, for CAN_FilterNumber=5, FMI value is 10 and so on. Why FMI value is 2 times CAN_FilterNumber ?

(Observation 2) When I use FIFO 1, received FMI field value is always zero no matter which filter I use, although all other received message field values are correct and interrupt is generating fine. Why am I not getting FMI value for FIFO 1?

(Observation 3)According to manual, there are total 14 filter banks for FIFO 0 and FIFO 1. I didn't understand the filters and FIFO's assignment. Can I attach any filter number to either FIFO 0 or FIFO 1? or is there any restriction? 

(Observation 4) Just for clearing concept, If I attach all 14 filters to only FIFO 0 then does this means that I cannot attach any filter to FIFO 1? What happens if I attach a filter number to both FIFO's?

All others things are working fine. Please give answer to each observation separately. Thanks in advance!

/* Code ---------------------------------------------------------*/
CanTxMsg TxMessage;
CanRxMsg RxMessage;
uint32_t i = 0,k=0;
uint8_t temp;
char buffer [5];
uint8_t TransmitMailbox = 0;
/* Private function prototypes -----------------------------------------------*/
void CAN_Struct_Init(void);
/**
  * @brief  CAN Bus Configuration 
  * @param  None
  * @retval None
  */     
void CAN_Config(void)
{
     // Enable GPIOB clock                                                   
       RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO , ENABLE);
     // CAN Periph clock enable 
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 , ENABLE);
     
     // CAN pins are fully remapped to PB.08,PB.09 etc.
     GPIO_PinRemapConfig(GPIO_Remap1_CAN1  , ENABLE);
     
     // GPIO CAN_RX (PB.08) Configuration 
     GPIO_InitStructureCAN_RX.GPIO_Pin = GPIO_Pin_8;
     GPIO_InitStructureCAN_RX.GPIO_Mode = GPIO_Mode_IPU;
     GPIO_InitStructureCAN_RX.GPIO_Speed = GPIO_CLOCK_SPEED;
     GPIO_Init(GPIOB, &GPIO_InitStructureCAN_RX);




     // GPIO CAN_TX (PB.09) Configuration 
     GPIO_InitStructureCAN_TX.GPIO_Pin = GPIO_Pin_9;
     GPIO_InitStructureCAN_TX.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_InitStructureCAN_TX.GPIO_Speed = GPIO_CLOCK_SPEED;
     GPIO_Init(GPIOB, &GPIO_InitStructureCAN_TX);
     
     // CAN1 Filter,FIFO and Baudrate settings 
     CAN_Struct_Init();
     
     // CAN1 NVIC settings for FIFO 0 
       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
     
       NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn;     
       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x08;
       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
       NVIC_Init(&NVIC_InitStructure);
     
     // CAN1 NVIC settings for FIFO 1
       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
     NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX1_IRQn;
       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0;
       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x09;
       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
       NVIC_Init(&NVIC_InitStructure);
     
     // IT Configuration for CAN1 FIFO 0 message received interrupt
     CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
     // IT Configuration for CAN1 FIFO 1 message received interrupt
     CAN_ITConfig(CAN1, CAN_IT_FMP1, ENABLE);
     
     // Receive message initialized
     RxMessage.StdId = 0x00;
     RxMessage.ExtId = 0x00;
     RxMessage.IDE = CAN_ID_STD;
     RxMessage.DLC = 0;
       RxMessage.FMI = 0;
       for (i = 0; i < 8; i++)
       {
              RxMessage.Data[i] = 0;
       }
}
/**
  * @brief  Configures the CAN, transmit and receive by polling
  * @param  None
  * @retval None
  */
void CAN_Struct_Init(void)
{
       // CAN1 register init 
       CAN_DeInit(CAN1);
       // CAN1 cell init 
     CAN_InitStructure.CAN_TTCM = DISABLE; // time-triggered communication mode = DISABLED
     CAN_InitStructure.CAN_ABOM = DISABLE; // automatic bus-off management mode = DISABLED
     CAN_InitStructure.CAN_AWUM = DISABLE; // automatic wake-up mode = DISABLED
     CAN_InitStructure.CAN_NART = DISABLE; // non-automatic retransmission mode = DISABLED
     CAN_InitStructure.CAN_RFLM = DISABLE; // receive FIFO locked mode = DISABLED
     CAN_InitStructure.CAN_TXFP = DISABLE; // transmit FIFO priority = DISABLED
       CAN_InitStructure.CAN_Mode = CAN_Mode_LoopBack;// CAN_Mode_Normal;
     
       CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
     CAN_InitStructure.CAN_BS1 = CAN_BS1_2tq;
       CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;
       // CAN1 Baudrate = 250kbps (System clock and CAN clock is 36MHz)
     // CAN_Prescaler value= CAN_clock/(required_Baudrate*total_number_of_tq)
     // In present case, total_number_of_tq=CAN_SJW_1tq+CAN_BS1_2tq+CAN_BS2_3tq=6*tq
     // so CAN_Prescaler= 36MHz/(250kbps*6)=24
  
       CAN_InitStructure.CAN_Prescaler = 24;
       CAN_Init(CAN1, &CAN_InitStructure);




       // CAN filter init 
       CAN_FilterInitStructure.CAN_FilterNumber = 12;
       CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
       CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
       CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
       CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
       CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
       CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
     CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FilterFIFO0;
     /*
       CAN_FilterInitStructure.CAN_FilterFIFOAssignment = CAN_FilterFIFO1;
     */
       CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
       CAN_FilterInit(&CAN_FilterInitStructure);     




     // Transmit message initialized
       TxMessage.StdId=0x34;
     TxMessage.ExtId=0x56;
       TxMessage.RTR=CAN_RTR_DATA;
       TxMessage.IDE=CAN_ID_EXT;
       TxMessage.DLC=8;
       TxMessage.Data[0]=0xA1;
       TxMessage.Data[1]=0xB2;
     TxMessage.Data[2]=0xC3;
     TxMessage.Data[3]=0xD4;
     TxMessage.Data[4]=0xE5;
       TransmitMailbox=CAN_Transmit(CAN1, &TxMessage);
       i = 0;
       while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFFFF))
       {
         i++;
       }
     USART1_SendData_s("CAN 1 init:\n\r");
}




/**
  * @brief  This function handles CAN1 RX FIFO 0 Handler.
  * @param  None
  * @retval None
  */
void USB_LP_CAN1_RX0_IRQHandler(void)
{
     if(CAN_GetITStatus(CAN1, CAN_IT_FMP0) != RESET)
     {
          USART1_SendData_s("CAN FIFO 0 IRQ:\n\r");
          CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);




          USART1_SendData_s("message StdID=");
          temp=(uint8_t) ((RxMessage.StdId & 0xFF000000)>>24);
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.StdId & 0x00FF0000)>>16);     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.StdId & 0x0000FF00)>>8);     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.StdId & 0x000000FF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
     
          USART1_SendData_s("message ExtId=");
          temp=(uint8_t) ((RxMessage.ExtId & 0xFF000000)>>24);
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.ExtId & 0x00FF0000)>>16);     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.ExtId & 0x0000FF00)>>8);     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.ExtId & 0x000000FF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          




          USART1_SendData_s("CAN1 RTR=");
          temp=(uint8_t) ((RxMessage.RTR & 0xFF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          USART1_SendData_s("CAN1 IDE=");
          temp=(uint8_t) ((RxMessage.IDE & 0xFF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          USART1_SendData_s("CAN1 DLC=");
          temp=(uint8_t) ((RxMessage.DLC & 0xFF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          USART1_SendData_s("CAN1 FMI=");
          temp=(uint8_t) ((RxMessage.FMI & 0xFF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          
          USART1_SendData_s("CAN1 message=");
          for (k=RxMessage.DLC;k!=0 ;k--)
          {
               sprintf (buffer, "%X",((RxMessage.Data[k-1]& 0xF0)>>4) );
               USART1_SendData_s(buffer);
               sprintf (buffer, "%X",(RxMessage.Data[k-1]& 0x0F) );
               USART1_SendData_s(buffer);
          }
          
          USART1_SendData_s("\n\r");
     
  }
     
}




/**
  * @brief  This function handles CAN1 RX FIFO 1 Handler.
  * @param  None
  * @retval None
  */
void CAN1_RX1_IRQHandler(void)
{
     if(CAN_GetITStatus(CAN1, CAN_IT_FMP1) != RESET)
     {
          USART1_SendData_s("CAN FIFO 1 IRQ:\n\r");
          CAN_Receive(CAN1, CAN_FIFO1, &RxMessage);
     
          USART1_SendData_s("message StdID=");
          temp=(uint8_t) ((RxMessage.StdId & 0xFF000000)>>24);
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.StdId & 0x00FF0000)>>16);     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.StdId & 0x0000FF00)>>8);     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.StdId & 0x000000FF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
     
          USART1_SendData_s("message ExtId=");
          temp=(uint8_t) ((RxMessage.ExtId & 0xFF000000)>>24);
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.ExtId & 0x00FF0000)>>16);     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.ExtId & 0x0000FF00)>>8);     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          temp=(uint8_t) ((RxMessage.ExtId & 0x000000FF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          




          USART1_SendData_s("CAN1 RTR=");
          temp=(uint8_t) ((RxMessage.RTR & 0xFF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          USART1_SendData_s("CAN1 IDE=");
          temp=(uint8_t) ((RxMessage.IDE & 0xFF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          USART1_SendData_s("CAN1 DLC=");
          temp=(uint8_t) ((RxMessage.DLC & 0xFF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          USART1_SendData_s("CAN1 FMI=");
          temp=(uint8_t) ((RxMessage.FMI & 0xFF));     
          sprintf (buffer, "%X",temp );
          USART1_SendData_s(buffer);
          USART1_SendData_s("\n\r");
          
          USART1_SendData_s("CAN1 message=");
          for (k=RxMessage.DLC;k!=0 ;k--)
          {
               sprintf (buffer, "%X",((RxMessage.Data[k-1]& 0xF0)>>4) );
               USART1_SendData_s(buffer);
               sprintf (buffer, "%X",(RxMessage.Data[k-1]& 0x0F) );
               USART1_SendData_s(buffer);
          }
          
          USART1_SendData_s("\n\r");
     
  
     }
}

Outcomes