cancel
Showing results for 
Search instead for 
Did you mean: 

Receive CAN msg in interrupt mode with STM32F105 mcu

Sandro Sartoni
Associate II
Posted on July 07, 2017 at 19:40

Hi everyone,

I'm trying to receive a msg via CAN-bus in interrupt mode with STM32F105 mcu. I set the CAN filter so that only 0x0106 and 0x010A IDs are allowed. This is the first time I use this microcontroller so I'm not completely sure of the code. Can you help me?

/* Main Code*/

int main(void)

 {

     /* USER CODE BEGIN 1 */

     /* USER CODE END 1 */

     /* MCU Configuration----------------------------------------------------------*/

     /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

     HAL_Init();

     /* Configure the system clock */

     SystemClock_Config();

     /* Initialize all configured peripherals */

     MX_GPIO_Init();

     MX_ADC1_Init();

     MX_CAN1_Init();

     MX_IWDG_Init();

     MX_RTC_Init();

     MX_SPI1_Init();

     MX_TIM1_Init();

     MX_TIM2_Init();

     MX_UART4_Init();

     MX_UART5_Init();

     /* USER CODE BEGIN 2 */

     /* Initialize CAN Filter */

     CAN_FilterConfTypeDef sFilterConfig;

     sFilterConfig.FilterNumber=0;

     sFilterConfig.FilterMode=CAN_FILTERMODE_IDMASK;

     sFilterConfig.FilterScale=CAN_FILTERSCALE_16BIT;

     sFilterConfig.FilterIdHigh=0x010A;

     sFilterConfig.FilterIdLow=0x0106;

     sFilterConfig.FilterMaskIdHigh=0x0000;

     sFilterConfig.FilterMaskIdLow=0x0000;

     sFilterConfig.FilterFIFOAssignment=0;

     sFilterConfig.FilterActivation=ENABLE;

     sFilterConfig.BankNumber=0;

     HAL_CAN_ConfigFilter(&hcan1,&sFilterConfig);

     if (HAL_CAN_ConfigFilter(&hcan1,&sFilterConfig) != HAL_OK)

     {

       Error_Handler();

     }

     HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);

     HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_3);

     /* USER CODE END 2 */

     /* Infinite loop */

     /* USER CODE BEGIN WHILE */

     while (1)

     {

     /* USER CODE END WHILE */

     /* USER CODE BEGIN 3 */

      /* Counts time, if no msg arrives after a certain time, assume something

         is broken and set arbitrarily to 75% the duty cycle */

      HAL_CAN_Receive_IT(&hcan1,CAN_FIFO0);

      //other code..

      HAL_Delay(delay);

     }

     /* USER CODE END 3 */

   }

/* CAN1 init function */

static void MX_CAN1_Init(void)

{

  hcan1.Instance = CAN1;

  hcan1.Init.Prescaler = 11;

  hcan1.Init.Mode = CAN_MODE_NORMAL;

  hcan1.Init.SJW = CAN_SJW_1TQ;

  hcan1.Init.BS1 = CAN_BS1_1TQ;

  hcan1.Init.BS2 = CAN_BS2_1TQ;

  hcan1.Init.TTCM = DISABLE;

  hcan1.Init.ABOM = DISABLE;

  hcan1.Init.AWUM = DISABLE;

  hcan1.Init.NART = DISABLE;

  hcan1.Init.RFLM = DISABLE;

  hcan1.Init.TXFP = DISABLE;

  if (HAL_CAN_Init(&hcan1) != HAL_OK)

  {

    Error_Handler();

  }

}

And in the interrupt section

void CAN1_RX0_IRQHandler(void)

{

  /* USER CODE BEGIN CAN1_RX0_IRQn 0 */

  /* USER CODE END CAN1_RX0_IRQn 0 */

  HAL_CAN_IRQHandler(&hcan1);

  /* USER CODE BEGIN CAN1_RX0_IRQn 1 */

  //my own code

  HAL_Delay(delay);

  /* USER CODE END CAN1_RX0_IRQn 1 */

#stm32f105-can-bus
13 REPLIES 13
Posted on July 07, 2017 at 19:47

sFilterConfig.FilterMode=CAN_FILTERMODE_IDMASK;

sFilterConfig.FilterScale=CAN_FILTERSCALE_16BIT;

sFilterConfig.FilterIdHigh=0x10A << 5; // Standard ID top 11-bits

sFilterConfig.FilterIdLow=0x106 << 5;

sFilterConfig.FilterMaskIdHigh=0x7FF << 5; // It is a MASK, remember something AND'd with zero is ZERO

sFilterConfig.FilterMaskIdLow=0x7FF << 5;

>>

This is the first time I use this microcontroller so I'm not completely sure of the code.

Reading and understanding the relevant parts of the Reference Manual will help considerably.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on July 07, 2017 at 19:49

Thinking this is nonsense. What on earth is the baud rate here?

  

hcan1.Init.Prescaler = 11;

  hcan1.Init.SJW = CAN_SJW_1TQ;

  hcan1.Init.BS1 = CAN_BS1_1TQ;

  hcan1.Init.BS2 = CAN_BS2_1TQ;

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on July 07, 2017 at 19:53

This is code automatically generated with STM32CubeMX. The baudrate I wanted to set is 1Mbps and with the program I mentioned before I set the Prescaler so that the Time for One Bit is 1031ns

Posted on July 07, 2017 at 21:06

If the APB is clocking at 36 MHz you've achieved 1.091 Mbps

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on July 07, 2017 at 21:23

The APB frequence is 32Mhz, after checking some documentation online my choice is Prescaler=4, Time Quanta in Bit Segment 1=6 and Time Quanta in Bit Segment 2=1.

If I'm not mistaken, thanks to the HAL_Receive_IT function when a msg arrives the micro checks the can's routine which is CAN1_RX0_IRQHandler, isn't it? The way I used these functions is correct?

Thanks for your patience, I realize these questions may be stupid but as I mentioned before this is my very first time programming a microcontroller, so I still have to learn many things

T J
Lead
Posted on July 08, 2017 at 04:06

I have this for my receive interrupt:

void CEC_CAN_IRQHandler(void)

{

  /* USER CODE BEGIN CEC_CAN_IRQn 0 */

            CAN_IRQFlag = true;

            checkCanRxFifos();

  /* USER CODE END CEC_CAN_IRQn 0 */

  HAL_CAN_IRQHandler(&hcan);

  /* USER CODE BEGIN CEC_CAN_IRQn 1 */

  /* USER CODE END CEC_CAN_IRQn 1 */

}

checkCanRxFifos

is how I pull the data from the fifos, before HAL upsets my flags...

void checkCanRxFifos(void){

    

    int readCanBytecount;

    

    char canFifo1FullFlag = CAN->RF1R & CAN_RF1R_FMP1;

    if(canFifo1FullFlag){

        {

            readCanBytecount = (CAN->sFIFOMailBox[1].RDTR &0x0f);    

            canRxMsgBottomWord[canRxMsgIN]    = CAN->sFIFOMailBox[1].RDLR;

            canRxMsgTopWord   [canRxMsgIN]    = CAN->sFIFOMailBox[1].RDHR;

            canRxMsgID [canRxMsgIN] = CAN->sFIFOMailBox[1].RIR >> 21;

            CAN->RF1R |= CAN_RF1R_RFOM1;                         // release FIFO

            canRxMsgLength [canRxMsgIN] =    readCanBytecount;        //  was 0x10+   to signify FIFO1

            ++ canRxMsgIN &= 0x3F;    // 16 entries only

            canRxMsgTableEMPTY = false;

            if( canRxMsgIN == canRxMsgOUT) canRxMsgTableFULL = true;

        }

                CAN->IER |= CAN_IER_FMPIE1;                                                               // (11)        Set FIFO1 message pending IT enable

    }

    char canFifo0FullFlag = CAN->RF0R & CAN_RF0R_FMP0;

    if(canFifo0FullFlag){

        {

            readCanBytecount         = (CAN->sFIFOMailBox[0].RDTR &0x0f);    

            canRxMsgBottomWord[canRxMsgIN]    = CAN->sFIFOMailBox[0].RDLR;

            canRxMsgTopWord   [canRxMsgIN]    = CAN->sFIFOMailBox[0].RDHR;

            uint32_t canRxmsgID =  CAN->sFIFOMailBox[0].RIR >> 21;

            CAN->RF0R |= CAN_RF0R_RFOM0;                         // release FIFO

            if ( canRxMsgTableFULL){    

                canRxMsgTableOverflow = true;  // now dump new frame...

            }else{

                canRxMsgID [canRxMsgIN] = canRxmsgID;

                canRxMsgLength [canRxMsgIN] = readCanBytecount;        // to signify FIFO0

                ++ canRxMsgIN &= 0x3F;    // 16 entries only

                canRxMsgTableEMPTY = false;

                if( canRxMsgIN == canRxMsgOUT)

                    canRxMsgTableFULL = true;

            }

            

// show data

           //length = sprintf(string + length,'%08X, %08X :W',canFifoBuf.d32[0],canFifoBuf.d32[1]);

//            for( int i = 0; i < readCanBytecount; i++){

//                

//                canRxBuffer[canRxpointerIN++] =  canFifoBuf.d8[i];            

//                canRxpointerIN &= 0xFF;

//                if (canRxpointerIN == canRxpointerOUT )        CanRxbufferOverrun = true;

//                //length += sprintf(string + length,'%02X, ',canFifoBuf.d8[i]);

//            }

            //sprintf(string + length -2,'\n\r');        // remove 2 bytes, the last comma and space

        //canFifo0FullFlag = CAN->RF0R & CAN_RF0R_FMP0;

        }

                        CAN->IER |= CAN_IER_FMPIE0;                                                               // (11)        Set FIFO1 message pending IT enable

    }

//            if (length >0)  puts(string);

}

Posted on July 08, 2017 at 09:37

I think the code you posted is already implemented inside the functions called in HAL_CAN_IRQHandler(&hcan1) inside the interrupt section. When I tested my board it seems like it never executes the interrupt routine, and I think that's because of my lines of code. The problem is there are some examples but they refer to the STM32F103 and I don't know if they're valid for the STM32F105 too

Posted on July 08, 2017 at 10:09

I run this before the while(1)

//init interrupts;

  __HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP1);

  __HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP0);

        
Posted on July 08, 2017 at 10:52

These enable are already present in the HAL_CAN_Receive_IT function, so I don't think that's what doesn't allow me to receive any message