STM32H7 CAN1 and CAN2 simultaneous use configuration instructions

Keywords: Programming

STM32H7 is a relatively new MCU. Many routines only give an example of a can port. There is no clear explanation for using two can ports at the same time. This paper mainly aims at the simultaneous use of CAN1 CAN2 for a teaching.

1. The configuration of CAN port is divided into the following points:

1. Baud rate configuration, not to elaborate, according to the official routine configuration.

2.CANRAM configuration

The width of message RAM is 32 bits, the total size is 10k, one width is 1 word, the total is 32 words.

It is mainly divided into four parts,

1. Filter configuration

2. Input data buffer configuration

3. Output data buffer configuration

4.can configuration of the starting address.

Make a main explanation for 234.

2.3 it is similar. If the length len of each element and the number num of all elements in a buffer are configured, the length of the buffer is len * num

4. It is very important to configure the starting address of CANRAM. For example, the number of RAM bytes occupied by the above parameters is 800 bytes. This configuration is CAN1. The starting address of RAM is 0x0400AC00,

Then the end address will be added 800 bytes. If CAN2 is to be configured, the CAN2 parameter MessageRAMOffset must be calculated from at least 800. The MessageRAMOffset of CAN1 is 0. In this way, CAN1 and CAN2 CAN be used at the same time. Remember: the RAM configuration of CAN1 and CAN2 is not parallel configuration, but serial configuration. Each CAN configuration occupies an independent RAM.

Paste the code for your reference:


CAN_PARA_CFG can_cfg[ODO_CAN_END] = 
{
	{
		.Instance = FDCAN1,
		.Mode=FDCAN_MODE_NORMAL,
		.NominalPrescaler=10,
		.NominalSyncJumpWidth=8,
		.NominalTimeSeg1=31,
		.NominalTimeSeg2=8,
		.TxBuffersNbr = 0,
		.TxFifoQueueElmtsNbr = 32,
	  .MessageRAMOffset = 0,
		.filtertype = 1,
		.filterID1 = 0,
		.filterID2 = 0xFFFF
	},
	{
		.Instance = FDCAN2,
		.Mode=FDCAN_MODE_NORMAL,
		.NominalPrescaler=10,
		.NominalSyncJumpWidth=8,
		.NominalTimeSeg1=31,
		.NominalTimeSeg2=8,
		.TxBuffersNbr=0,
		.TxFifoQueueElmtsNbr = 32,
		.MessageRAMOffset = 500,
		.filtertype = 1,
		.filterID1 = 0,
		.filterID2 = 0xFFFF
	}
};

void HAL_FDCAN_MspInit(FDCAN_HandleTypeDef* hfdcan)
{
	if (hfdcan->Instance == FDCAN1)
	{
		HAL_FDCAN1_MspInit(hfdcan);
	}
	else if(hfdcan->Instance == FDCAN2)
	{
		HAL_FDCAN2_MspInit(hfdcan);
	}
}

void HAL_FDCAN_MspDeInit(FDCAN_HandleTypeDef* hfdcan)
{
	if (hfdcan->Instance == FDCAN1)
	{
		HAL_FDCAN1_MspDeInit(hfdcan);
	}
	else if (hfdcan->Instance == FDCAN2)
	{
		HAL_FDCAN2_MspDeInit(hfdcan);
	}
}


u4 board_can_init(CAN_NAME canname)
{
		FDCAN_FilterTypeDef FDCANRxFilterType;

    HAL_FDCAN_DeInit(&can_cfg[canname].FDCANHalHandler); 

    can_cfg[canname].FDCANHalHandler.Instance=can_cfg[canname].Instance;
    can_cfg[canname].FDCANHalHandler.Init.FrameFormat=FDCAN_FRAME_CLASSIC;            //Traditional mode
    can_cfg[canname].FDCANHalHandler.Init.Mode=can_cfg[canname].Mode;                
    can_cfg[canname].FDCANHalHandler.Init.AutoRetransmission=DISABLE;                 //Turn off automatic retransmission
    can_cfg[canname].FDCANHalHandler.Init.TransmitPause=DISABLE;                      //Turn off transmission pause
    can_cfg[canname].FDCANHalHandler.Init.ProtocolException=DISABLE;                  //Closing protocol exception handling
    can_cfg[canname].FDCANHalHandler.Init.NominalPrescaler=can_cfg[canname].NominalPrescaler;                    //division factor
    can_cfg[canname].FDCANHalHandler.Init.NominalSyncJumpWidth=can_cfg[canname].NominalSyncJumpWidth;            //Resynchronize jump width
    can_cfg[canname].FDCANHalHandler.Init.NominalTimeSeg1=can_cfg[canname].NominalTimeSeg1;                      //tsg1 range: 2 ~ 256
    can_cfg[canname].FDCANHalHandler.Init.NominalTimeSeg2=can_cfg[canname].NominalTimeSeg2;                      //tsg2 range: 2 ~ 128
		can_cfg[canname].FDCANHalHandler.Init.MessageRAMOffset=can_cfg[canname].MessageRAMOffset;      
    can_cfg[canname].FDCANHalHandler.Init.StdFiltersNbr=1;                            //Number of standard information filters
    can_cfg[canname].FDCANHalHandler.Init.ExtFiltersNbr=0;                            //Number of extended information filters
    can_cfg[canname].FDCANHalHandler.Init.RxFifo0ElmtsNbr=32;                          //Receive FIFO0 element number
    can_cfg[canname].FDCANHalHandler.Init.RxFifo0ElmtSize=FDCAN_DATA_BYTES_8;         //Receive FIFO0 element size: 8 bytes
	  can_cfg[canname].FDCANHalHandler.Init.RxFifo1ElmtsNbr=0;                          //Receive FIFO1 element number
    can_cfg[canname].FDCANHalHandler.Init.RxBuffersNbr=0;                             //Receive buffer number
		
    can_cfg[canname].FDCANHalHandler.Init.TxEventsNbr=0;                              //Send event number
		can_cfg[canname].FDCANHalHandler.Init.TxBuffersNbr=can_cfg[canname].TxBuffersNbr;                             //Send buffer number
		can_cfg[canname].FDCANHalHandler.Init.TxFifoQueueElmtsNbr=can_cfg[canname].TxFifoQueueElmtsNbr;               //Send FIFO sequence element number
    can_cfg[canname].FDCANHalHandler.Init.TxFifoQueueMode=FDCAN_TX_FIFO_OPERATION;    //Send FIFO sequence mode
    can_cfg[canname].FDCANHalHandler.Init.TxElmtSize=FDCAN_DATA_BYTES_8;              //Send size: 8 bytes
    if(HAL_FDCAN_Init(&can_cfg[canname].FDCANHalHandler)!=HAL_OK) return 1;           //Initialize FDCAN
		
		/*fifo 0 Set to overwrite write*/
		HAL_FDCAN_ConfigRxFifoOverwrite(&can_cfg[canname].FDCANHalHandler,FDCAN_RX_FIFO0,FDCAN_RX_FIFO_OVERWRITE);
  
		FDCANRxFilterType.IdType=FDCAN_STANDARD_ID;                       //Standard ID
		FDCANRxFilterType.FilterIndex=can_cfg[canname].filtertype;        //Filter index                   
		FDCANRxFilterType.FilterType=FDCAN_FILTER_MASK;                   //Filter type
		FDCANRxFilterType.FilterConfig=FDCAN_FILTER_TO_RXFIFO0;           //Filter 0 is associated with FIFO0  
		FDCANRxFilterType.FilterID1=can_cfg[canname].filterID1;                               //>ID1
		FDCANRxFilterType.FilterID2=can_cfg[canname].filterID2;                               //<ID2
		if(HAL_FDCAN_ConfigFilter(&can_cfg[canname].FDCANHalHandler,&FDCANRxFilterType)!=HAL_OK) 
		{	
			return 2;//Filter initialization
		}
		
		if (HAL_FDCAN_ConfigGlobalFilter(&can_cfg[canname].FDCANHalHandler, FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_ACCEPT_IN_RX_FIFO0, ENABLE, ENABLE) != HAL_OK)
		{
			return 2;
		}

		HAL_FDCAN_ActivateNotification(&can_cfg[canname].FDCANHalHandler,FDCAN_IT_RX_FIFO0_NEW_MESSAGE,0);
		HAL_FDCAN_ActivateNotification(&can_cfg[canname].FDCANHalHandler,FDCAN_IT_TX_FIFO_EMPTY,0);
		
		can_cfg[canname].FDCAN_TxHeader.IdType = FDCAN_STANDARD_ID;                  
    can_cfg[canname].FDCAN_TxHeader.TxFrameType = FDCAN_DATA_FRAME;              
    can_cfg[canname].FDCAN_TxHeader.DataLength = FDCAN_DLC_BYTES_8;              
    can_cfg[canname].FDCAN_TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;      
    can_cfg[canname].FDCAN_TxHeader.BitRateSwitch = FDCAN_BRS_OFF;               
    can_cfg[canname].FDCAN_TxHeader.FDFormat = FDCAN_CLASSIC_CAN;                
    can_cfg[canname].FDCAN_TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;     
    can_cfg[canname].FDCAN_TxHeader.MessageMarker = 0;    
		
		HAL_FDCAN_Start(&can_cfg[canname].FDCANHalHandler);                               //Open FDCAN
		
    return success;		
}

/*can1 Initialization*/
void can1_init(void)
{
	board_can_init(ODO_CAN1);        
}

/*can Initialization*/
void can2_init(void)
{
	board_can_init(ODO_CAN2);      
}



Here's a tip for troubleshooting hardware connections:

Enter debugging mode:

1. Check the CAN protocol status register. Just after initialization and can bus is not connected, the LEC bit is status 7, indicating that no can bus event is detected. When you connect the settings to the CAN bus, if there is nothing wrong with the program and hardware, the LEC status changes to 0. It means no error has occurred. If the CAN bus is not connected, and you send data to the outside, LEC will change to state 5, bit0ERR, indicating that during the message sending process, the device wants to send the dominant level, but the monitored cell idle is invisible.

Posted by lewisstevens1 on Thu, 09 Jan 2020 05:29:08 -0800