Open Wh1terat opened 3 years ago
Hello.
0x681 << 21 = 0xd0200000
0x68103 << 13 = 0xd0206000
The extended format 29-bit length ID range is 0x0 to 0x1FFFFFFF 0xd0206000 is out of range.
Filter bank format is: https://www.st.com/resource/en/reference_manual/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf
Thanks for reply.
Yes I understand it's 29bit for extended or 11bit for standard. But unlike mcp2515, stm32 filter seems to read from MSB, not MSB+3.
11010000 00100000 00000000 00000000
Because this works to filter 0x681.
Infact, you can even see this in your own code from CANReceive function:
out = ((CAN_tx_msg->id & CAN_STD_ID_MASK) << 21U);
Edit:
To clarify what I'm asking, is it possible to filter the first 2 data bytes of a standard frame using the 32bit filters? As data bytes 1 & 2 would be in the same position as EXTID[12:0]+IDE+RTE
is it possible to filter the first 2 data bytes of a standard frame using the 32bit filters?
The Filter bank register has 28 FiR1 and 28 FiR2 respectively.
F0R1-F27R1 F0R2-F27R2
Standard frame filter:
Set the first filter to F0R1 Set a second filter on F0R2
F0R1=first filter data
F0R2=second filter data
CANSetFilter(0, 0, 1, 0, F0R1, F0R2)
That is simply using list mode rather than mask mode to match multiple IDs ?
To explain my problem more clearly, Can ID 0x681 sends constant keepalive messages every 500ms, first byte of data ID is 0xF0.
I am only interested in messages where first byte of data is 0x04 - because of the frequency of the keepalive messages it makes ISR unsuitable.
With MCP2515's filter I am able to filter the ID and first 2 bytes of a standard frame, trying to replicate this functionality using STM32.
Standard frame filter Identifier List mode:
F0R1=1st id & 2nd id
F0R2=3rd id & 4th id
CANSetFilter(0, 0, 1, 0, F0R1, F0R2)
Standard frame filter Identifier Mask mode:
F0R1=1st id & 2nd id
F0R2=1st mask & 2nd mask
CANSetFilter(0, 0, 0, 0, F0R1, F0R2)
Extended frame filter Identifier List mode:
F0R1=1st id
F0R2=2nd id
CANSetFilter(0, 1, 1, 0, F0R1, F0R2)
Extended frame filter Identifier Mask mode:
F0R1=1st id
F0R2=1st mask
CANSetFilter(0, 1, 0, 0, F0R1, F0R2)
Thank you for trying to help, but I think maybe I am being unclear about my issue or what I am trying to achieve - or maybe it is not even possible.
Same issue here, transitioning from MCP2515, it is completely unclear how to configure CANSetFilter to allow particular (or range) of ID`s, also it's unclear how to filter on 0,1,2..n bytes of data, for example filter only particular (or range) where data[0] or data[n] corresponds.
For example: I want to allow only packets with ID=0x101 and data[0]=0x6B. How to set the filter?
Tried this, no success:
CANSetFilter(0, 1, 0, 0, 0x101 << 21, 0x6B << 24);
From RM0008 Reference manual
24.4.1 Initialization mode
The software initialization can be done while the hardware is in Initialization mode. To enter this mode the software sets the INRQ bit in the CAN_MCR register and waits until the hardware has confirmed the request by setting the INAK bit in the CAN_MSR register. To leave Initialization mode, the software clears the INRQ bit. bxCAN has left Initialization mode once the INAK bit has been cleared by hardware. While in Initialization Mode, all message transfers to and from the CAN bus are stopped and the status of the CAN bus output CANTX is recessive (high). Entering Initialization Mode does not change any of the configuration registers. To initialize the CAN Controller, software has to set up the Bit Timing (CAN_BTR) and CAN options (CAN_MCR) registers.
To initialize the registers associated with the CAN filter banks (mode, scale, FIFO _assignment, activation and filter values), software has to set the FINIT bit (CAN_FMR). Filter__ initialization also can be done outside the initialization mode.___
Case of STM32F103:
// Configure Filters to default values
CAN1->FMR |= 0x1UL; // Set to filter initialization mode
CAN1->FMR &= 0xFFFFC0FF; // Clear CAN2 start bank
// bxCAN has 28 filters.
// These filters are used for both CAN1 and CAN2.
// STM32F103 has only CAN1, so all 28 are used for CAN1
CAN1->FMR |= 0x1C << 8; // Assign all filters to CAN1
// Set fileter 0
// Single 32-bit scale configuration
// Two 32-bit registers of filter bank x are in Identifier Mask mode
// Filter assigned to FIFO 0
// Filter bank register to all 0
CANSetFilter(0, 1, 0, 0, 0x0UL, 0x0UL);
CAN1->FMR &= ~(0x1UL); // Deactivate initialization mode
I don't understand this either. I want to filter only 7E8 diagnostic response messages from OBDII.
No go even when directly editing the code as highlighted in the previous response:
CANSetFilter(0, 1, 0, 0, 0x7E8, 0x7E8);
If you want to filter only ID=0x7E8
for STD ID Data Frame
uint32_t bank1, bank2;
bank1 = 0x7E8 << 21;
bank2 = 0xFFE00006; // Must be IDE=0 RTR=0
CANSetFilter(0, 1, 0, 0, bank1, bank2);
for STD ID Remote Frame
uint32_t bank1, bank2;
bank1 = 0x7E8 << 21;
bank1 = bank1 + 0x02; // Remote
bank2 = 0xFFE00006; // Must be IDE=0 RTR=1
CANSetFilter(0, 1, 0, 0, bank1, bank2);
for STD ID Any Frame
uint32_t bank1, bank2;
bank1 = 0x7E8 << 21;
bank2 = 0xFFE00004; // Must be IDE=0
CANSetFilter(0, 1, 0, 0, bank1, bank2);
for EXT ID Data Frame
uint32_t bank1, bank2;
bank1 = 0x7E8 << 3;
bank1 = bank1 + 0x04; // Ext
bank2 = 0xFFFFFFFE; // Must be IDE=1 RTR=0
CANSetFilter(0, 1, 0, 0, bank1, bank2);
for EXT ID Remote Frame
uint32_t bank1, bank2;
bank1 = 0x7E8 << 3;
bank1 = bank1 + 0x06; // Ext + Remote
bank2 = 0xFFFFFFFE; // Must be IDE=1 RTR=1
CANSetFilter(0, 1, 0, 0, bank1, bank2);
for EXT ID Any Frame
uint32_t bank1, bank2;
bank1 = 0x7E8 << 3;
bank1 = bank1 + 0x04; // Ext
bank2 = 0xFFFFFFFC; // Must be IDE=1
CANSetFilter(0, 1, 0, 0, bank1, bank2);
Mask bit0 indicates that you don't care.
Mask bit1 indicates that you care.
If anyone still struggles with setting up filters in list mode for 16bit IDs, here is how it should look:
uint32_t bank1 = (filterId1<<21) | (filterId2<<5);
uint32_t bank2 = (filterId3<<21) | (filterId4<<5);
Please, could i ask how can i filter a range of std ids? ie 0 to 7?, list mode from v-ivanyshyn works well, but im getting confused by bitshift places. for mask mode.
I cant get why bank 2 is 0xFFE00006 In the example above:
uint32_t bank1, bank2;
bank1 = 0x7E8 << 21;
bank2 = 0xFFE00006; // Must be IDE=0 RTR=0
CANSetFilter(0, 1, 0, 0, bank1, bank2);
I cant get why bank 2 is 0xFFE00006 In the example above:
About STM32 CAN Identifier Filtering
Thanks for the answer nopnop2002: first I have to thank you for the code you have made and shared, thank you very much! Have the link bookmarked for a long time and I wanted to follow the example of filtering from 0 to 7 but in std id. I was trying to understand how to include in your code to filter the mentioned range.
Answering my own question and for reference to future readers, 0xFFE00006 --> 0x7ff << 21 + 0x06 11111111111000000000000000000000+ 00000000000000000000000000000110= 11111111111000000000000000000110
why include 0x06 in the filter? 0x7ff<<21 is not enough?
why include 0x06 in the filter? 0x7ff<<21 is not enough?
This is because IDE and RTR are used to distinguish between frame types.
Bit 2 IDE: Identifier extension
This bit defines the identifier type of message in the mailbox.
0: Standard identifier.
1: Extended identifier.
Bit 1 RTR: Remote transmission request
0: Data frame
1: Remote frame
|<------->| Can ID for Standard
|<------------------------->| Can ID for Extended
11111111111000000000000000000110
||
|+-->RTR
+-->IDE
There are 4 frames type
If you don't include 0x06 in your filter, these will match
ID=0x467 and ID=0x119C000 pass the filter even though only ID=0x467 is needed.
ID=100-0110-0111=0x467
<----------->
1000 1100 1110 0000 0000 0000 0000 0000 // Standard data frame
ID=0x467
<----------->
1000 1100 1110 0000 0000 0000 0000 0010 // Standard remote frame
ID=1-0001-1001-1100-0000-0000-0000==0x119C000
<---------------------------------->
1000 1100 1110 0000 0000 0000 0000 0100 // Extended data frame
ID=0x119C000
<---------------------------------->
1000 1100 1110 0000 0000 0000 0000 0110 // Extended remote frame
Having issues with filter settings,
receiving id 0x101 and 0x206, how to setup a filter to just receive these messages.
Tried :
uint32_t bank1 = (0x101<<21) | (0x206<<5);
uint32_t bank2 = (0x0<<21) | (0x0<<5);
CANSetFilter(0, 0, 1, 0, bank1, bank2);
uint32_t bank1 = (0x101<<21) | (0x101<<5);
uint32_t bank2 = (0x206<<21) | (0x206<<5);
CANSetFilter(0, 0, 1, 0, bank1, bank2);
Case of STM32F103:
CAN1->FMR |= 0x1UL; // Set to filter initialization mode
fileter setting
CAN1->FMR &= ~(0x1UL); // Deactivate initialization mode
Otherwise: Look at the source.
/*
Bit IDE: Identifier extension
This bit defines the identifier type of message in the mailbox.
0: Standard identifier.
1: Extended identifier.
Bit RTR: Remote transmission request
0: Data frame
1: Remote frame
*/
int IDE1=0;
int IDE2=0;
int IDE3=0;
int IDE4=0;
int RTR1=0or1;
int RTR2=0or1;
int RTR3=0or1;
int RTR4=0or1;
uint32_t bank1 = (STID1<<21) | (RTR1<<20) | (IDE1<<19) | (STID2<<5) | (RTR2<<4) | (IDE2<<3);
uint32_t bank2 = (STID3<<21) | (RTR3<<20) | (IDE3<<19) | (STID4<<5) | (RTR4<<4) | (IDE4<<3);
Hi, Firstly - thank you for the project, very nicely documented.
Just wondering if you have some examples for CANSetFilter ? I'm trying to filter messages from ID 0x681 AND the first byte of the message 0x03
So this works fine for filtering all messages from 0x681
So I expected this would work for what I was trying to achieve:
But I'm still receiving all messages to 0x681 with this which is odd.