Skip to main content
Explorer
July 9, 2024
Solved

CAN1 loopback does not work on STM32F427

  • July 9, 2024
  • 3 replies
  • 1616 views

Hello everyone,

I have recently been trying to get the CAN1 bus working on the STM32F427. So far, however, it has not worked in either loopback or normal mode. For the normal mode I had a CANCaseXL Analyzer available. The problem, however, is that not even the loopback works. I have attached the main.c file and the ioc project file.

When I call HAL_CAN_AddTxMessage(), I get HAL_OK back, so that seems to work. However, I have set a breakpoint in the CAN interrupt handler (HAL_CAN_IRQHandler() in file stm32f4xx_hal_can.c) and there I see that the TERR0 bit gets set. Accordingly, the transmission process has failed. I have already tried many other possibilities, which unfortunately did not work either.

Maybe someone has an idea. Many thanks in advance!

Louis

    This topic has been closed for replies.
    Best answer by mƎALLEm

    Hello,

    At first check at your ioc file, I don't recommend these values for CAN bit timing:

     

    hcan1.Init.Prescaler = 16;
    hcan1.Init.TimeSeg1 = CAN_BS1_1TQ;
    hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;

     

    BS1_1TQ and BS2_2TQ are very low. You need to increase them as much as possible by decreasing the prescaler as much as possible.

    I recommend these values for 500kb/s:

    SofLit_0-1720537708434.png

    Also, we don't recommend HSI as clock source when using CAN in Normal mode. You need to use HSE with an external crystal otherwise you may face communication issues.

    SofLit_0-1720537957478.png

     

     

     

    3 replies

    mƎALLEmAnswer
    Technical Moderator
    July 9, 2024

    Hello,

    At first check at your ioc file, I don't recommend these values for CAN bit timing:

     

    hcan1.Init.Prescaler = 16;
    hcan1.Init.TimeSeg1 = CAN_BS1_1TQ;
    hcan1.Init.TimeSeg2 = CAN_BS2_2TQ;

     

    BS1_1TQ and BS2_2TQ are very low. You need to increase them as much as possible by decreasing the prescaler as much as possible.

    I recommend these values for 500kb/s:

    SofLit_0-1720537708434.png

    Also, we don't recommend HSI as clock source when using CAN in Normal mode. You need to use HSE with an external crystal otherwise you may face communication issues.

    SofLit_0-1720537957478.png

     

     

     

    Graduate II
    July 9, 2024

    Segment 1 should be larger than Segment 2. Use this online calculator http://www.bittiming.can-wiki.info/

     

    I did some test with your code and found an issue. If you're using polling method then don't use HAL_CAN_ActivateNotification else you'll get stuck in while(HAL_CAN_IsTxMessagePending(&hcan1, TxMailbox));

     

    Here is what I did to get either Interrupt or Polling method to work. Interrupt mode blinks the LED fast while polling blinks the LED slowly. I moved your code out of main.c and created separate functions.

     

    main.c

     /* Infinite loop */
     /* USER CODE BEGIN WHILE */
     PollingInit();
     while (1)
     {
    	 PollingRoutine();
     /* USER CODE END WHILE */
    
     /* USER CODE BEGIN 3 */
     }
     /* USER CODE END 3 */

     

    PollingRoutine.c

    /*
     * PollingRoutine.c
     *
     * Created on: Oct 24, 2023
     * Author: karl.yamashita
     *
     *
     * Template for projects.
     *
     */
    
    
    #include "main.h"
    
    
    //#define USE_CAN_INTERRUPT
    
    
    extern CAN_HandleTypeDef hcan1;
    
    
    CAN_TxHeaderTypeDef TxHeader;
    CAN_RxHeaderTypeDef RxHeader;
    uint8_t TxData[8];
    uint8_t RxData[8];
    uint32_t TxMailbox;
    bool CAN_MsgRdy = false;
    
    
    void PollingInit(void)
    {
    	CAN_FilterInit();
    }
    
    void PollingRoutine(void)
    {
    	CAN_SendTxMessage();
    #ifdef USE_CAN_INTERRUPT
    	CAN_CheckMsg();
    #else
    	CAN_ReceiveMessage();
    #endif
    	HAL_Delay(100);
    }
    
    void led1_on(void)
    {
    	HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
    }
    
    void led1_off(void)
    {
    	HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET);
    }
    
    
    void CAN_FilterInit(void)
    {
    	CAN_FilterTypeDef CAN1_Filter;
    
    	CAN1_Filter.FilterBank = 0;
    	CAN1_Filter.FilterMode = CAN_FILTERMODE_IDMASK;
    	CAN1_Filter.FilterScale = CAN_FILTERSCALE_32BIT;
    	CAN1_Filter.FilterIdHigh = 0x0000;
    	CAN1_Filter.FilterIdLow = 0x0000;
    	CAN1_Filter.FilterMaskIdHigh = 0x0000;
    	CAN1_Filter.FilterMaskIdLow = 0x0000;
    	CAN1_Filter.FilterFIFOAssignment = CAN_RX_FIFO0;
    	CAN1_Filter.FilterActivation = ENABLE;
    	CAN1_Filter.SlaveStartFilterBank = 14;
    
    	if (HAL_CAN_ConfigFilter(&hcan1, &CAN1_Filter) != HAL_OK)
    	{
    	 Error_Handler();
    	}
    
    	if (HAL_CAN_Start(&hcan1) != HAL_OK)
    	{
    	 Error_Handler();
    	}
    #ifdef USE_CAN_INTERRUPT
    	if (HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_TX_MAILBOX_EMPTY | CAN_IT_ERROR) != HAL_OK)
    	{
    	 Error_Handler();
    	}
    #endif
    }
    
    void CAN_SendTxMessage(void)
    {
    	TxHeader.StdId = 0x11;
    	TxHeader.RTR = CAN_RTR_DATA;
    	TxHeader.IDE = CAN_ID_STD;
    	TxHeader.DLC = 2;
    	TxHeader.TransmitGlobalTime = DISABLE;
    	TxData[0] = 0xCA;
    	TxData[1] = 0xFE;
    
    	if (HAL_CAN_AddTxMessage(&hcan1, &TxHeader, TxData, &TxMailbox) != HAL_OK)
    	{
    	 Error_Handler();
    	}
    }
    
    #ifdef USE_CAN_INTERRUPT
    void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
    {
    	// currently not used as we use polling for test purposes
    	if(hcan == &hcan1)
    	{
    		if (HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
    		{
    		 Error_Handler();
    		}
    		CAN_MsgRdy = true;
    	}
    }
    
    void CAN_CheckMsg(void)
    {
    	if(CAN_MsgRdy)
    	{
    		CAN_MsgRdy = false;
    		if(RxHeader.StdId == 0x11)
    		{
    			if((RxData[0]<<8 | RxData[1]) == 0xCAFE)
    			{
    				led1_on();
    				HAL_Delay(100);
    				led1_off();
    				HAL_Delay(100);
    			}
    		}
    	}
    }
    
    #else // Polling
    void CAN_ReceiveMessage(void)
    {
    	while(HAL_CAN_IsTxMessagePending(&hcan1, TxMailbox));
    	while(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1) != 3);
    
    	HAL_Delay(20);
    
    	if (HAL_CAN_GetRxFifoFillLevel(&hcan1, CAN_RX_FIFO0) != 1)
    	{
    	 Error_Handler();
    	}
    
    	if (HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
    	{
    	 Error_Handler();
    	}
    
    	if(RxHeader.StdId == 0x11)
    	{
    		if((RxData[0]<<8 | RxData[1]) == 0xCAFE)
    		{
    			led1_on();
    			HAL_Delay(500);
    			led1_off();
    			HAL_Delay(500);
    		}
    	}
    }
    #endif
    
    

     

     

     

    Louis00Author
    Explorer
    July 10, 2024

    Thanks to both of you, both answers were very helpful!

    With the bit timing provided by @mƎALLEm, the TX no longer failed. With the code from @Karl Yamashita , the reception also worked.