Introduction
Sometimes we only want to see certain messages on a network that can have a hundred or more unique message ID's. Masks and filters allow us to only receive messages with a specified message ID or portion of message ID. For example, if we only want to see J1939 messages from source address 0x03, we can set up a mask and filter to ignore any message ID's that do not end in 0x03. Messages that do not match the mask and filter are rejected as soon as they are received by the CAN controller and do not require later processing by the microcontroller. This could be helpful if your device has trouble keeping up with incoming messages and only needs to act on a single message ID. Rather than reading every message ID and data field into your program and then throwing it away if it does not match a specific message ID, the non-matching messages are rejected and only messages meeting the mask and filter critera are loaded into the buffers to be retreived by some CANread() function.
Masks
Masks are used to determine which bits of the message ID should be applied to the filter. You turn on a mask by setting its respective bit to '1' and you turn off a mask by setting its respective bit to '0'. Going back to our J1939 example, the source address is the last byte of a message ID. Our mask in that case would be 0xFF since we only want to compare the last byte of the message ID to 0x03. Any message ID ending in 0x03 would be accepted regardless of its preceeding bits.
The operation of applying a mask to a message ID is a simple AND operation. Using the J1939 source address example, we said we only cared about the last 8 bits of the 29-bit ID. By ANDing the received message ID and the mask, we are left with all zeros except for the last 8 bits. The last 8 bits will be transferred to the next step for filtering.
| Mask/Filter | Hex | B0 | B1 | B2 | B3 | ... | B22 | B23 | B24 | B25 | B26 | B27 | B28 | B29 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Mask | 0xFF | 0 | 0 | 0 | 0 | ... | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| Msg ID | 0x18FEF103 | 1 | 1 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
| Result | 0x03 | 0 | 0 | 0 | 0 | ... | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
Filters
Filters are used to determine if the bits of a message ID that remain after a mask is applied match the bits we want to accept. After the incoming message ID is ANDed, the result is compared to the value of the filter. If the result matches the filter value, then the entire message is accepted.
J1939 Examples
Since J1939 assigns different functions to parts of the 29-bit message ID, it is a good example for building message ID masks/filters. We may only need to receive a particular PGN or maybe we only care about incoming messages from a particular source address. If you are using CAN King software, you can specify these masks and filters so that only messages meeting the criteria are displayed.
PGN Mask And Filter
Suppose we only want to receive PGN 0xFEF1 (CCVS1) but from all source addresses transmitting this message. We need to create a filter so that only PGN 0xFEF1 is received. This would require a mask of two bytes of 1's in the PGN's position in the 29-bit message ID and a filter value of 0xFEF1. Since the PGN is in the middle of the message, we'll need to add enough trailing zeros to our hex values to make sure the mask bits are shifted to the correct positions and the filter bits will match the result of the mask.
| Priority | PGN | Source Address | |
| Message ID | 0x18 | FEF1 | 03 |
| Mask | 0x00 | FFFF | 00 |
| Filter | 0x00 | FEF1 | 00 |
If we were to apply this mask and filter to a vehicle network, we would likely see about 3 message ID's passing through the filter. That is because PGN 0xFEF1 is typically transmitted by the ECM, TCM, and BCM. Since we only maksed the PGN, the different priorities and source address are still passed through the filter as long as the bits in the PGN position of the message ID match our filter value.
Source Address Mask And Filter
Let's say we want to see all messages being transmitted by a particular source address, 0x03. We'll need to mask the last 8 bits of the message ID and set our filter value to 0x03.
| Priority | PGN | Source Address | |
| Message ID | 0x18 | FEF1 | 03 |
| Mask | 0x00 | 0000 | FF |
| Filter | 0x00 | 0000 | 03 |
PGN and Source Address
The above mask and filter would show us a list of all message ID's (or PGNs) being transmitted by source address 0x03. If we wanted to only see a single PGN transmitted by source address 0x03, we can combine the masks and filters from the two examples to further refine the messages passed though the filter.
| Priority | PGN | Source Address | |
| Message ID | 0x18 | FEF1 | 03 |
| Mask | 0x00 | FFFF | FF |
| Filter | 0x00 | FEF1 | 03 |
Entire Message ID
The preceeding mask and filter would only allow PGN 0xFEF1 from source address 0x03 through the filter. The only way we can get more specific is to include the priority, which means we'd be specifying a mask and filter for the entire message ID. In this case, all 29 of our mask bits are set to '1' or 0x7FFFFFF. Our filter will be the entire ID we want to see, 0x18FEF103.
| Priority | PGN | Source Address | |
| Message ID | 0x18 | FEF1 | 03 |
| Mask | 0x7F | FFFF | FF |
| Filter | 0x18 | FEF1 | 03 |