cancel
Showing results for 
Search instead for 
Did you mean: 

CAN programming question

KMiko.1
Associate III

Hi !

I'm new in the STM32 world ! So, sorry if my questions are stupid. I work on CAN with the example : FDCAN Classic Frame Networking.

I want to know if in this example that I modified slightly,

  • HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) is use to send a message ?
  • HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs) is use to receive ? or it is HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData) ?
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <stdbool.h>
 
 
/* Private includes ----------------------------------------------------------*/
 
 
/* Private typedef -----------------------------------------------------------*/
 
 
/* Private define ------------------------------------------------------------*/
 
#define KEY_PRESSED     GPIO_PIN_RESET
#define KEY_NOT_PRESSED GPIO_PIN_SET
 
 
 
/* Private macro -------------------------------------------------------------*/
 
 
 
/* Private variables ---------------------------------------------------------*/
 
	FDCAN_HandleTypeDef hfdcan1;
	FDCAN_RxHeaderTypeDef RxHeader;
	FDCAN_TxHeaderTypeDef TxHeader;
	
	uint8_t ubKeyNumber = 0x0;
	uint8_t RxData[8];
	uint8_t TxData[8];
 
 
/* Private function prototypes -----------------------------------------------*/
	
	void SystemClock_Config(void);
	static void MX_GPIO_Init(void);
	static void MX_FDCAN1_Init(void);
	static void FDCAN_Config(void);
	static void LED_Display(uint8_t LedStatus);
 
 
 
/* Private user code ---------------------------------------------------------*/
 
	
 
/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
 
  HAL_Init();/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  SystemClock_Config();/* Configure the system clock */
 
  /* Configure User push-button in interrupt mode */
  BSP_PB_Init(BUTTON_USER, BUTTON_MODE_GPIO);
  BSP_LED_Init(LED1); /* Configure LED1, LED2, LED3 and LED4 */
  BSP_LED_Init(LED2);
  BSP_LED_Init(LED3);
  BSP_LED_Init(LED4);
 
  
  /* Initialize all configured peripherals */
  MX_GPIO_Init();																						// GPIO Init
  MX_FDCAN1_Init();																						// FDCAN1 Init
  FDCAN_Config();																						// Configure the FDCAN peripheral
 
 
  
  /* Infinite loop */
  while (1)
  {
	  
	  // Check Power supply CAN DATA
	  _Bool checkPSS = PowerSupply_Security();				// Check CAN security message
 
        // Set the data to be transmitted
        TxHeader.Identifier = 0x321;																	// ID
        TxHeader.IdType = FDCAN_STANDARD_ID;															// ID type
        TxHeader.TxFrameType = FDCAN_DATA_FRAME;														// Frame type
        TxHeader.DataLength = FDCAN_DLC_BYTES_8;														// Data length
        TxData[0] = 0xAA;
        TxData[1] = 0xAD;
        TxData[2] = 0xAD;
        TxData[3] = 0xAD;
        TxData[4] = 0xAD;
        TxData[5] = 0xAD;
        TxData[6] = 0xAD;
        TxData[7] = 0xAD;
 
        // Start the Transmission process
        if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK) {
          Error_Handler();																				// Transmission request Error
        }
        
        HAL_Delay(10);
 
        while (BSP_PB_GetState(BUTTON_USER) != KEY_NOT_PRESSED)
        {
        }
  }
}
 
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 
  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV2;
  RCC_OscInitStruct.PLL.PLLN = 20;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
  RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
  /** Initializes the peripherals clocks
  */
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
  PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1;
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
  {
    Error_Handler();
  }
}
 
/**
  * @brief FDCAN1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_FDCAN1_Init(void)
{
 
  /* USER CODE BEGIN FDCAN1_Init 0 */
 
  /* USER CODE END FDCAN1_Init 0 */
 
  /* USER CODE BEGIN FDCAN1_Init 1 */
 
  /* USER CODE END FDCAN1_Init 1 */
  hfdcan1.Instance = FDCAN1;
  hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
  hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
  hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
  hfdcan1.Init.AutoRetransmission = ENABLE;
  hfdcan1.Init.TransmitPause = ENABLE;
  hfdcan1.Init.ProtocolException = DISABLE;
  hfdcan1.Init.NominalPrescaler = 1;
  hfdcan1.Init.NominalSyncJumpWidth = 16;
  hfdcan1.Init.NominalTimeSeg1 = 63;
  hfdcan1.Init.NominalTimeSeg2 = 16;
  hfdcan1.Init.DataPrescaler = 1;
  hfdcan1.Init.DataSyncJumpWidth = 4;
  hfdcan1.Init.DataTimeSeg1 = 5;
  hfdcan1.Init.DataTimeSeg2 = 4;
  hfdcan1.Init.StdFiltersNbr = 1;
  hfdcan1.Init.ExtFiltersNbr = 0;
  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN FDCAN1_Init 2 */
 
  /* USER CODE END FDCAN1_Init 2 */
 
}
 
/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
 
  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();
 
}
 
/* USER CODE BEGIN 4 */
 
/**
  * @brief  Configures the FDCAN.
  * @param  None
  * @retval None
  */
static void FDCAN_Config(void)
{
	
  FDCAN_FilterTypeDef sFilterConfig;
 
  /* Configure Rx filter */
  sFilterConfig.IdType = FDCAN_STANDARD_ID;
  sFilterConfig.FilterIndex = 0;
  sFilterConfig.FilterType = FDCAN_FILTER_MASK;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x321;
  sFilterConfig.FilterID2 = 0x7FF;
  
  if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK) {
    Error_Handler();
  }
 
  /* Configure global filter: Filter all remote frames with STD and EXT ID Reject non matching frames with STD ID and EXT ID */
  if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK) {
    Error_Handler();
  }
 
  /* Start the FDCAN module */
  if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK) {
    Error_Handler();
  }
 
  if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK) {
    Error_Handler();
  }
 
  /* Prepare Tx Header */
  TxHeader.Identifier = 0x321;
  TxHeader.IdType = FDCAN_STANDARD_ID;
  TxHeader.TxFrameType = FDCAN_DATA_FRAME;
  TxHeader.DataLength = FDCAN_DLC_BYTES_2;
  TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
  TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
  TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
  TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
  TxHeader.MessageMarker = 0;
}
 
/**
  * @brief  Rx FIFO 0 callback.
  * @param  hfdcan: pointer to an FDCAN_HandleTypeDef structure that contains
  *         the configuration information for the specified FDCAN.
  * @param  RxFifo0ITs: indicates which Rx FIFO 0 interrupts are signalled.
  *         This parameter can be any combination of @arg FDCAN_Rx_Fifo0_Interrupts.
  * @retval None
  */
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
  if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
  {
    /* Retrieve Rx messages from RX FIFO0 */
    if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
    {
    Error_Handler();
    }
 
    /* Display LEDx */
    if ((RxHeader.Identifier == 0x321) && (RxHeader.IdType == FDCAN_STANDARD_ID) && (RxHeader.DataLength == FDCAN_DLC_BYTES_2))
    {
      ubKeyNumber = RxData[0];
    }
  }
}
 
 
 
/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  /* Turn LED1, LED2, LED3 and LED4 on */
  BSP_LED_On(LED1);
  BSP_LED_On(LED2);
  BSP_LED_On(LED3);
  BSP_LED_On(LED4);
 
  while(1){}
}

Thank you !

3 REPLIES 3
Ozone
Lead

To be honest, I did not work with the CAN interface of STM32 MCUs, and definitely not with HAL/Cube.

But almost all vendors have the same Bosch IP licensed, only the register interface differs.

You cannot "crack down" on the bus directly, because CAN is message/ID arbitrated, and has no master/slave organisation.

Instead, you have FIFOs for Tx and FIFOs or "mailboxes" for Rx.

HAL_FDCAN_AddMessageToTxFifoQ() is supposedly a function to add a message to the send queue.

HAL_FDCAN_RxFifo0Callback() would be a callback function for a CAN Rx event, and HAL_FDCAN_GetRxMessage() a function to retrieve one message.

Be careful with callback functions, they are called within interrupt context and can easily mess up the application timing.

SKacp.1
Senior II

ok so if i understand correctly the best thing to do is to remove the callback function.

I have a device which sends continuous functions and another which waits for a frame to send its response. To avoid problems I would like not to store the received messages, that is to say that I ignore the messages then by entering a function I will read the data (id) that I need then exit, is it possible? does the HAL_FDCAN_GetRxMessage () function look good?

ah and why don't you work with HAL CUBE?