Recently I looked at STM32 CAN communication and found that the setting of identifier filter is very particular. Especially when you want to use ST library functions, when the filter works in shield mode and you set the shield bit to 1, that is, the corresponding bits of the identifier must all match in order to pass, you must be especially careful.
For example, the filter length is 32 bits, the mode is mask mode, and if the identifier I want to send is 0x1314; then the filter settings are as follows
1. The filter is completely invalid and all received identifiers are passed
0x1314 binary code: 0000 0000 0000 0000 0001 0011 0001 0100
CAN_Filter xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx
CAN_FilterMask 0000 0000 0000 0000 0000 0000 0000 0000
Because all bits of the CAN_FilterMask register are 0, the corresponding identifiers are all "don't care", that is, the ID (identifier) of the received data does not need to match any bit of the CAN_Filter register.
2. The filter is fully effective. The received identifier is compared with the bits that need to be matched according to the MASK register.
Partial Match
0x1314 binary code: 0000 0000 0000 0000 0001 0011 0001 0100
CAN_Filter xxxx xxxx xxxx xxxx xxxx xxx1 xxxx xxxx
CAN_FilterMask 0000 0000 0000 0000 0000 0001 0000 0000
The CAN_FilterMask register specifies that the received identifier must match the 8th bit, and the other bits are ignored. That is, the 8th bit of the received identifier must be 1, otherwise the message will be discarded.
Match all
0x1314 binary code: 0000 0000 0000 0000 0001 0011 0001 0100
CAN_Filter 0000 0000 0000 0000 0000 0011 0001 0100
CAN_FilterMask 1111 1111 1111 1111 1111 1111 1111 1111
This is the most stringent case. Every bit of the received identifier must match every bit of the identifier in the filter. If one bit is wrong, the message will be discarded. (This identifier matching work is automatically completed by the internal hardware of the CAN module)
3. Using ST library to configure CAN filter
Similarly, the data identifiers of both the sender and receiver are 0x1314
The first type: the filter is invalid, all pass
static void CAN_Filter_Config(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber=0; //Filter group 0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //Work in identifier mask bit mode
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; //The filter bit width is a single 32-bit.
CAN_FilterInitStructure.CAN_FilterIdHigh= 0x0000; //High bit of ID to be filteredCAN_FilterInitStructure.CAN_FilterIdLow
= 0x0000; //Low bit of ID to be filteredCAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0x0000; //No need to match each of the high 16 bits of the filterCAN_FilterInitStructure.CAN_FilterMaskIdLow= 0x0000
; //No need to match each of the low 16 bits of the filterCAN_FilterInitStructure.CAN_FilterFIFOAssignment
=CAN_Filter_FIFO0; //Filter is associated with FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //Enable filterCAN_FilterInit
(&CAN_FilterInitStructure);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}
Second: Every bit of the filter must match
static void CAN_Filter_Config(void)
{
CAN_FilterInitTypeDef CAN_FilterInitStructure;
CAN_FilterInitStructure.CAN_FilterNumber=0; //Filter group 0
CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask; //Work in identifier mask bit mode
CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit; // The filter bit width is a single 32-bit.
CAN_FilterInitStructure.CAN_FilterIdHigh= (((u32)0x1314<<3)&0xFFFF0000)>>16; //High bit of ID to be filteredCAN_FilterInitStructure.CAN_FilterIdLow
= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //Low bit of ID to be filteredCAN_FilterInitStructure.CAN_FilterMaskIdHigh
= 0xFFFF; //Every bit of the high 16 bits of the filter must matchCAN_FilterInitStructure.CAN_FilterMaskIdLow
= 0xFFFF; //Every bit of the low 16 bits of the filter must matchCAN_FilterInitStructure.CAN_FilterFIFOAssignment
=CAN_Filter_FIFO0; //The filter is associated with FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; //Enable filter
CAN_FilterInit(&CAN_FilterInitStructure);
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
}
Here comes the point
Why does 0x1314 in CAN_FilterIdHigh need to be shifted 3 bits to the left and then bitwise ANDed with 0xFFFF0000? Why does 0x1314 in CAN_FilterIdLow need to be shifted 3 bits to the left and then bitwise ORed with CAN_ID_EXT CAN_RTR_DATA? In practice, when I send data, I set the ID identifier to 0x1314, as shown in the following code:
void CAN_SetMsg(void)
{
//TxMessage.StdId=0x00;
TxMessage.ExtId=0x1314; //Extended ID identifier 0x1314 is used
TxMessage.IDE=CAN_ID_EXT; //Extended mode
TxMessage.RTR=CAN_RTR_DATA; //Data is sent
TxMessage.DLC=2; // Data length is 2 bytes
TxMessage.Data[0]=0xDC;
TxMessage.Data[1]=0xBA;
}
Then the identifier in your filter should also be 0x1314. According to the above code for configuring the identifier, the value in the filter identifier register is definitely not 0x1314. The reason is as follows: we used the ST library and processed it when sending the identifier.
uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)
{
uint8_t transmit_mailbox = 0;
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_IDTYPE(TxMessage->IDE));
assert_param(IS_CAN_RTR(TxMessage->RTR));
assert_param(IS_CAN_ DLC (TxMessage->DLC));
if ((CANx->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
{
transmit_mailbox = 0;
}
else if ((CANx->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
{
transmit_mailbox = 1;
}
else if ((CANx->TSR&CAN_TSR_TME2) == CAN_TSR_TME2)
{
transmit_mailbox = 2;
}
else
{
transmit_mailbox = CAN_TxStatus_NoMailBox;
}
if (transmit_mailbox != CAN_TxStatus_NoMailBox)
{
CANx->sTxMailBox[transmit_mailbox].TIR &= TMIDxR_TXRQ;
if (TxMessage->IDE == CAN_Id_Standard)
{
assert_param(IS_CAN_STDID(TxMessage->StdId));
CANx->sTxMailBox[transmit_mailbox] .TIR |= ((TxMessage->StdId << 21) | \
TxMessage->RTR);
}
else
{
assert_param(IS_CAN_EXTID(TxMessage->ExtId));
CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage ->ExtId << 3) | \
TxMessage->IDE | \
TxMessage->RTR);
}
This is the processing of the identifier when sending. When sending 16 bits, just shift it left by 21 bits, and then do a bitwise OR with TxMessage->RTR (data frame). When sending 32 bits, the processing is more. After shifting left by 3 bits, it is first bitwise ORed with TxMessage->IDE and then bitwise ORed with TxMessage->RTR (data frame). This is why we have such a statement when setting the receive filter :
CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF; //The low bit of the ID to be filtered
Since the identifier is processed when sending, it is also restored when receiving:
void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage)
{
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_FIFO(FIFONumber));
RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONumber].RIR ;
if (RxMessage->IDE == CAN_Id_Standard)
{
RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 21);
}
else
{
RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 3);
} // I don't understand why the received identifier is only shifted right by three digits when restored without any other processing. When it is sent, it looks like this:
CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->ExtId << 3) | \
TxMessage->IDE | \
TxMessage->RTR);
TxMessage->RTR is the data frame value bit 0, but TxMessage->IDE is the extended identifier value 0x00000004. After 0x1314 is shifted 3 bits to the left, the value will definitely change. However, I just figured out this problem. The binary code of 0x4 is 0100. After 0x1314 is shifted 3 bits to the left, it becomes 100. It must be attached to a value, but this value is directly processed by a right shift of three bits when receiving. It is really smart. RTR is a data frame with a value of 0. It has no effect on it when it is ANDed with another number.
It’s too long to write so much, but I still figured out some things. If you don’t figure these out when the mask mode is effective, your receiver filter will probably be configured incorrectly, and it will be a tragedy to debug... Of course, if your mask bit doesn’t work, it doesn’t matter. You can configure the filter identifier value at will, as long as the filter mask register value is 0, it’s OK...
Previous article:Analysis of STM32 big-endian mode, stack and its growth direction
Next article:Porting ucGUI touch screen on STM32
Recommended ReadingLatest update time:2024-11-16 12:50
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Nvidia is said to acquire Arm for 40 billion pounds. Will the situation of domestic chips get worse?
- Operational issues of XDS100V3.0 emulation motoware built-in project
- GD32E231 Learning 3: SPI driving OLED
- What documents does the patch welding factory need?
- [Show goods] + Water Group Wholesale Department
- Pnp transistor collector connected to power supply problem
- AI cooling requires a "core" under the scorching sun. Infineon tests your knowledge of AI chips
- [Review of Arteli Development Board AT32F421] 3. FreeRTOS porting [with source code]
- Sallen-Key low-pass filter reference ground
- STLM75 evaluation board STEVAL-MKI204V1K data