cancel
Showing results for 
Search instead for 
Did you mean: 

CAN setup and filters using HAL

endlessFancy
Associate II

Hi,

I have quite extencive experincu using CAN and J1939.

In this project I am working on now I will impliment CAN signaling in a STM32F446.

My questions:

1.

CAN_TxHeaderTypeDef.ExtId, shall be used with extended IDs. What will happen if .StdId is also filled in? Or is that only the 11 first bits in the ID and then ExtId shall be the rest of the 29 bit identifyer?

2.

I cant find any material describing the filter CAN_FilterTypeDef. Is there any kind of explination how to impliment this? I find nothing in the hall documentation and h. file is giving no real relation ship beteween identifyer and filter parameters.

I would love to be pointed to some kind of documentation.

Thank you in advance

5 REPLIES 5
turboscrew
Senior III

The extended id and stdid are mutually exclusive - learned that the hard way.

They COULD have made just id and use 11 or 29 bits of it depending on the EI-bit, but no. The EI bit selects whether the id is taken from standard id field or extended id field.

When it comes to the filters, it's all in the reference manual. Remember to check the register description too. Note that the HW allows you to decide how many filters you allocate to CAN A and CAN B, but HAL restricts that to 14 + 14.

The filters filter 32 bits, so using ID filtering is hard especially for 11-bit standard ID because some other bits are filtered too. It's better to use masks, and mark those "extra bits" as "not compared".

I also think that the .h file is quite informative:

/**
  * @brief  CAN filter configuration structure definition
  */
typedef struct
{
  uint32_t FilterIdHigh;          /*!< Specifies the filter identification number (MSBs for a 32-bit
                                       configuration, first one for a 16-bit configuration).
                                       This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
 
  uint32_t FilterIdLow;           /*!< Specifies the filter identification number (LSBs for a 32-bit
                                       configuration, second one for a 16-bit configuration).
                                       This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
 
  uint32_t FilterMaskIdHigh;      /*!< Specifies the filter mask number or identification number,
                                       according to the mode (MSBs for a 32-bit configuration,
                                       first one for a 16-bit configuration).
                                       This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
 
  uint32_t FilterMaskIdLow;       /*!< Specifies the filter mask number or identification number,
                                       according to the mode (LSBs for a 32-bit configuration,
                                       second one for a 16-bit configuration).
                                       This parameter must be a number between Min_Data = 0x0000 and Max_Data = 0xFFFF. */
 
  uint32_t FilterFIFOAssignment;  /*!< Specifies the FIFO (0 or 1U) which will be assigned to the filter.
                                       This parameter can be a value of @ref CAN_filter_FIFO */
 
  uint32_t FilterBank;            /*!< Specifies the filter bank which will be initialized.
                                       For single CAN instance(14 dedicated filter banks),
                                       this parameter must be a number between Min_Data = 0 and Max_Data = 13.
                                       For dual CAN instances(28 filter banks shared),
                                       this parameter must be a number between Min_Data = 0 and Max_Data = 27. */
 
  uint32_t FilterMode;            /*!< Specifies the filter mode to be initialized.
                                       This parameter can be a value of @ref CAN_filter_mode */
 
  uint32_t FilterScale;           /*!< Specifies the filter scale.
                                       This parameter can be a value of @ref CAN_filter_scale */
 
  uint32_t FilterActivation;      /*!< Enable or disable the filter.
                                       This parameter can be set to ENABLE or DISABLE. */
 
  uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.
                                       For single CAN instances, this parameter is meaningless.
                                       For dual CAN instances, all filter banks with lower index are assigned to master
                                       CAN instance, whereas all filter banks with greater index are assigned to slave
                                       CAN instance.
                                       This parameter must be a number between Min_Data = 0 and Max_Data = 27. */
 
} CAN_FilterTypeDef;

endlessFancy
Associate II

Thank you,

I will go to the reference manual to read up.

Ben K
Senior III

I wrote a method that configures the filter banks based on an actual filter list input as part of my STM32 library: CAN_eFilterConfig It's quite complex to do algorithmically, it would make more sense to have a code generator for this purpose, but at least this way the filtering can be changed in runtime. This function also outputs the Filter Match Index values, which are provided for the received frames, but are otherwise hard to match to your filters.

endlessFancy
Associate II

Thank you Ben, I will have a look at it

endlessFancy
Associate II

To answer my own question number 2 for fellow community members how find there way here:

If you want to configure the filterbank to recive only one CAN message of J1939 typ (extended ID) You should think like this;

/* Your ID with 0x 'prio':6 (or 18) , 'PGN': EEFF, ' SRC' : 92 */

EXT_ID_CAN = 0x18EEFF92;

The HAL lets your write this ID to ONE filter, but in two 16 bit shunks (dont be fooled by the uint32_t)

Also some but shifting must be done to match the layout of the filter matching according to the register organisation (figure 392 in the ref manual for stmf446xx)

So in the end my filter config looked like this:

canfilterDef.FilterIdHigh   = (EXT_ID_CAN >>13) & 0xFFFF; // THIS is the tricky part

canfilterDef.FilterIdLow   = ((EXT_ID_CAN <<3) & 0xFFF8) | 4; // THIS is the tricky part

canfilterDef.FilterMaskIdHigh = 0xFFFF;

canfilterDef.FilterMaskIdLow = 0xFFFC;

canfilterDef.FilterFIFOAssignment = CAN_RX_FIFO0;

canfilterDef.FilterBank = 0;

canfilterDef.FilterMode = CAN_FILTERMODE_IDMASK;

canfilterDef.FilterScale = CAN_FILTERSCALE_32BIT;

canfilterDef.FilterActivation = ENABLE;

canfilterDef.SlaveStartFilterBank = 0;

This is not a awesome tutorial, but I hope you can start using it fast.