cancel
Showing results for 
Search instead for 
Did you mean: 

Two STM32F4-discovery boards unable to communicate over CAN

Rde K.1
Associate III

Hi,

I am new to HAL libraries and currently working on a small CAN bus consisting of two STM32F4-discovery boards connected to a CAN transceiver connected to the bus. Both transceivers are externally powered with 5V.

So far, I tried the existing CAN examples from the STM32CubeF4 github. The loopback example works fine, the normal mode example does not.

After a few transmissions the mailboxes are filled and the transmit function returns an error. And I can't figure out why it does not transmit the requests. Below you can find the code I on both discovery boards. It is basically the Networking example but with some light adjustments for LED output pins.

Any ideas on why this might not be working as expected?

#include "main.h"
 
#define KEY_PRESSED     0x00
#define KEY_NOT_PRESSED 0x01
 
uint8_t ubKeyNumber = 0x0;
CAN_HandleTypeDef     CanHandle;
CAN_TxHeaderTypeDef   TxHeader;
CAN_RxHeaderTypeDef   RxHeader;
uint8_t               TxData[8];
uint8_t               RxData[8];
uint32_t              TxMailbox;
 
 
void SystemClock_Config(void);
void Error_Handler(void);
void CAN_Config(void);
void LED_Display(uint8_t LedStatus);
void Init_OnBoard_LEDs(void);
 
int main(void)
{
  HAL_Init();
 
  /* Configure the system clock to 168 MHz */
  SystemClock_Config();
 
  /* Configure LED1, LED2, LED3 and LED4 */
  Init_OnBoard_LEDs();
 
  LED_Display(ubKeyNumber);
 
  /* Configure the CAN peripheral */
  CAN_Config();
 
  /* Infinite loop */
  while (1)
  {
	  uint8_t state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
    if (state)
    {
      if (ubKeyNumber == 0x4)
      {
        ubKeyNumber = 0x00;
      }
      else
      {
        LED_Display(++ubKeyNumber);
 
        /* Set the data to be transmitted */
        TxData[0] = ubKeyNumber;
        TxData[1] = 0xAD;
 
        /* Start the Transmission process */
        if (HAL_CAN_AddTxMessage(&CanHandle, &TxHeader, TxData, &TxMailbox) != HAL_OK)
        {
          /* Transmission request Error */
          Error_Handler();
        }
        HAL_Delay(1000);
      }
    }
  }
}
 
void Init_OnBoard_LEDs(void){
	__HAL_RCC_GPIOD_CLK_ENABLE();
	GPIO_InitTypeDef BoardLEDs;
	BoardLEDs.Mode = GPIO_MODE_OUTPUT_PP;
	BoardLEDs.Pin = GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;
	HAL_GPIO_Init(GPIOD, &BoardLEDs);
 
 
	__HAL_RCC_GPIOA_CLK_ENABLE();
	GPIO_InitTypeDef BlueButton;
	BlueButton.Mode = GPIO_MODE_INPUT;
	BlueButton.Pin = GPIO_PIN_0;
	BlueButton.Pull = GPIO_NOPULL;
	HAL_GPIO_Init(GPIOA, &BlueButton);
}
 
void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;
 
  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();
 
  /* The voltage scaling allows optimizing the power consumption when the device is
     clocked below the maximum system frequency, to update the voltage scaling value
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
 
  /* Enable HSE Oscillator and activate PLL with HSE as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 25;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  HAL_RCC_OscConfig(&RCC_OscInitStruct);
 
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
  HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
 
  /* STM32F405x/407x/415x/417x Revision Z devices: prefetch is supported  */
  if (HAL_GetREVID() == 0x1001)
  {
    /* Enable the Flash prefetch */
    __HAL_FLASH_PREFETCH_BUFFER_ENABLE();
  }
}
 
 
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
void Error_Handler(void)
{
  while (1)
  {
  }
}
 
/**
  * @brief  Configures the CAN.
  * @param  None
  * @retval None
  */
void CAN_Config(void)
{
	//Tx: PB12
	//Rx: PB13
  CAN_FilterTypeDef  sFilterConfig;
 
  /*##-1- Configure the CAN peripheral #######################################*/
  CanHandle.Instance = CAN2;
 
  CanHandle.Init.TimeTriggeredMode = DISABLE;
  CanHandle.Init.AutoBusOff = DISABLE;
  CanHandle.Init.AutoWakeUp = DISABLE;
  CanHandle.Init.AutoRetransmission = ENABLE;
  CanHandle.Init.ReceiveFifoLocked = DISABLE;
  CanHandle.Init.TransmitFifoPriority = DISABLE;
  CanHandle.Init.Mode = CAN_MODE_NORMAL;
  CanHandle.Init.SyncJumpWidth = CAN_SJW_1TQ;
  CanHandle.Init.TimeSeg1 = CAN_BS1_4TQ;
  CanHandle.Init.TimeSeg2 = CAN_BS2_2TQ;
  CanHandle.Init.Prescaler = 6;
 
  if (HAL_CAN_Init(&CanHandle) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
 
  /*##-2- Configure the CAN Filter ###########################################*/
  sFilterConfig.FilterBank = 0;
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
  sFilterConfig.FilterActivation = ENABLE;
  sFilterConfig.SlaveStartFilterBank = 14;
 
  if (HAL_CAN_ConfigFilter(&CanHandle, &sFilterConfig) != HAL_OK)
  {
    /* Filter configuration Error */
    Error_Handler();
  }
 
  /*##-3- Start the CAN peripheral ###########################################*/
  if (HAL_CAN_Start(&CanHandle) != HAL_OK)
  {
    /* Start Error */
    Error_Handler();
  }
 
  /*##-4- Activate CAN RX notification #######################################*/
  if (HAL_CAN_ActivateNotification(&CanHandle, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
  {
    /* Notification Error */
    Error_Handler();
  }
 
  /*##-5- Configure Transmission process #####################################*/
  TxHeader.StdId = 0x321;
  TxHeader.ExtId = 0x01;
  TxHeader.RTR = CAN_RTR_DATA;
  TxHeader.IDE = CAN_ID_STD;
  TxHeader.DLC = 2;
  TxHeader.TransmitGlobalTime = DISABLE;
}
 
/**
  * @brief  Rx Fifo 0 message pending callback
  * @param  hcan: pointer to a CAN_HandleTypeDef structure that contains
  *         the configuration information for the specified CAN.
  * @retval None
  */
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
  /* Get RX message */
  if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
  {
    /* Reception Error */
    Error_Handler();
  }
 
  /* Display LEDx */
  if ((RxHeader.StdId == 0x321) && (RxHeader.IDE == CAN_ID_STD) && (RxHeader.DLC == 2))
  {
    LED_Display(RxData[0]);
    ubKeyNumber = RxData[0];
  }
}
 
/**
  * @brief  Turns ON/OFF the dedicated LED.
  * @param  LedStatus: LED number from 0 to 3
  * @retval None
  */
void LED_Display(uint8_t LedStatus)
{
  /* Turn OFF all LEDs */
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_RESET);
 
	switch(LedStatus){
	case(0x0):
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_12, GPIO_PIN_SET);
		break;
	case(0x1):
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
		break;
	case(0x2):
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, GPIO_PIN_SET);
		break;
	case(0x3):
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15, GPIO_PIN_SET);
		break;
	default:
		break;
	}
}

35 REPLIES 35

@Community member​ When you say "will never get any messages" is incorrect. Here is a video of me using a STM32F407-Discovery board using CAN2 and no CAN1. When I use my suggested sFilterConfig without the Filterbank parameters, it works.

https://youtu.be/S-Jb2y6rdW8

@Rde K.1​ I'm not sure if you used STM32CubeIDE or CubeMX to set up the dev board, but did you enable CAN2 RX0 Interrupts?

0693W00000Y6qHCQAZ.png

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

@Community member​ 

I don't know what you did from your side. The screenshot you provided don't show the filter config. From my side I've just did a test with CAN2 and I confirm what I've already said.

If the filter bank is not well configured as I mentioned i.e. .FilterBank should be always >= .SlaveStartFilterBank for CAN2 you never get any message into the FIFO even the filter is configured to receive all IDs.

What I did: I used two boards STM32F743_EVAL and STM32F429_EVAL with the examples "Examples\CAN\CAN_Networking" provided under the respective CubeHAL driver packages, modified the example STM32F429 to receive CAN messages over CAN2, connected CAN2 to the available transceiver on the board (PA12 connected to PB13 / PA11 connected to PB12).

Filer config 1:

 sFilterConfig.FilterBank = 0;

 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;

 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;

 sFilterConfig.FilterIdHigh = 0x0000;

 sFilterConfig.FilterIdLow = 0x0000;

 sFilterConfig.FilterMaskIdHigh = 0x0000;

 sFilterConfig.FilterMaskIdLow = 0x0000;

 sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;

 sFilterConfig.FilterActivation = ENABLE;

 sFilterConfig.SlaveStartFilterBank = 14;

-> Here .FilterBank < .SlaveStartFilterBank and I never get any message because this doesn't allows you to receive any message even the CAN peripheral acknowledge the CAN frame on the bus but the frame will never get into the FIFO.

Filer config 2:

 sFilterConfig.FilterBank = 15;

 sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;

 sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;

 sFilterConfig.FilterIdHigh = 0x0000;

 sFilterConfig.FilterIdLow = 0x0000;

 sFilterConfig.FilterMaskIdHigh = 0x0000;

 sFilterConfig.FilterMaskIdLow = 0x0000;

 sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;

 sFilterConfig.FilterActivation = ENABLE;

 sFilterConfig.SlaveStartFilterBank = 14;

-> Here .FilterBank > .SlaveStartFilterBank and I receive well the messages sent by STM32F743_EVAL board and the LEDs are turning on according to the received message.

So please re-check from your side.

If you want I can attach the examples (F7/F4) to check.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

@Community member​  if i did use the FilterBank/SlaveStartFilterBank and it wasn't set up correctly, then I agree it doesn't work which i showed it in the video. But I also showed in the video that i didn't use FilterBank/SlaveStartFilterBank and I am able to still receive messages. That was using a STM32F407 Discovery.

I have a consumer product that uses a STM32F105 and even though I am using both CAN controllers, I am using the exact sFilterConfig for both of them. It's been probably almost 4 years since the product has been shipping and I've yet to have customer support tell me that they get calls from customers about the interface not working.

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

@Community member​ I've uploaded the project to github so you can test with the same code that I used in the video..

https://github.com/karlyamashita/STM32F407_NoFilter

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.
Sco
ST Employee

Firstly, please confirm the connection of the two boards, it seems ok regarding your diagram.

Secondly, it's necessary to combine these two boards' GND(seems ok).

Then the direct way is to capture the signal through a oscilloscope: TX(1st tranciever) = > CAN H/L = > RX(2nd tranciever).

Best Regards,

Sco

@Community member​ 

By commenting out the lines .FilterBank and .SlaveStartFilterBank don't allow you to receive any messages because the default value in CAN_FMR register of CAN2SB = 0xE =14. I've already tested it with STM32F407-Disco board in loopback mode and didn't get any message with the two lines commented out. So now, I have a doubt about the authenticity of your STM32 chip.

So please use the CAN filters as described above. 

Have a nice day.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.