I won't go into the basics of CAN here, you can buy a book to learn about it yourself. Now let's look at the CAN driver under STM32. STM32 itself includes the CAN data link layer, and the physical layer is the CAN transceiver using TJA1050, which is a non-fault-tolerant CAN. The terminal resistor is 120 ohms.
The most important thing about CAN is the initialization of CAN, which includes two main parts, one is the declaration of basic properties, and the other is the setting of filters. See the following code:
/*******************************************************************************
* Function Name : bxCAN_Port_Configuration
* Description : CAN端口设置
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void bxCAN_Port_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure_bxCAN;
GPIO_PinRemapConfig(GPIO_Remap1_CAN1 , ENABLE); //端口复用为CAN1
GPIO_InitStructure_bxCAN.GPIO_Pin = GPIO_Pin_8; //PB8:CAN-RX
GPIO_InitStructure_bxCAN.GPIO_Mode = GPIO_Mode_IPU; //输入上拉
GPIO_InitStructure_bxCAN.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure_bxCAN);
GPIO_InitStructure_bxCAN.GPIO_Pin = GPIO_Pin_9; //PB9:CAN-TX
GPIO_InitStructure_bxCAN.GPIO_Mode = GPIO_Mode_AF_PP; //复用模式
GPIO_InitStructure_bxCAN.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure_bxCAN);
}
/*******************************************************************************
* Function Name : bxCAN_Property_Configuration
* Description : CAN配置具体属性
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void bxCAN_Property_Configuration(void)
{
CAN_InitTypeDef CAN_InitStructure;
CAN_FilterInitTypeDef CAN_FilterInitStructure;
/* CAN register init */
CAN_DeInit(CAN1);
CAN_StructInit(&CAN_InitStructure);
/* CAN cell init */
CAN_InitStructure.CAN_TTCM=DISABLE; //MCR-TTCM disable time triggered communication modeCAN_InitStructure.CAN_ABOM
=DISABLE; //MCR-ABOM disable automatic offline managementCAN_InitStructure.CAN_AWUM
=DISABLE; //MCR-AWUM enter automatic wake-up mode by clearing the CAN_MCR_SLEEP
bitCAN_InitStructure.CAN_NART=DISABLE; //MCR-NART disable automatic message retransmission 0-Automatic retransmission 1-Message is transmitted only onceCAN_InitStructure.CAN_RFLM
=DISABLE; //MCR-RFLM receive FIFO lock mode 0-New message will overwrite the original message when overflowing 1-New message is discarded when overflowingCAN_InitStructure.CAN_TXFP
=DISABLE; //MCR-TXFP Send FIFO priority 0-priority depends on the message identifier 1-priority depends on the order of send requests
CAN_InitStructure.CAN_Mode=CAN_Mode_LoopBack; //BTR-SILM/LBKM CAN loopback mode
// CAN_InitStructure.CAN_Mode=CAN_Mode_Normal; // CAN normal mode
CAN_InitStructure.CAN_SJW=CAN_SJW_1tq; //BTR-SJW resynchronization jump width 1 time unit
CAN_InitStructure.CAN_BS1=CAN_BS1_2tq; //BTR-TS1 time period 1 occupies 2 time units
CAN_InitStructure.CAN_BS2=CAN_BS2_3tq; //BTR-TS1 time period 2 occupies 3 time units
#if CAN_BAUDRATE == 1000 /* 1MBps */ //BTR-BRP baud rate divider defines the time unit length 36/(1+2+3)/6=1Mbps
CAN_InitStructure.CAN_Prescaler = 6;
#elif CAN_BAUDRATE == 500 /* 500KBps */
CAN_InitStructure.CAN_Prescaler = 12;
#elif CAN_BAUDRATE == 250 /* 250KBps */
CAN_InitStructure.CAN_Prescaler = 24; #elif CAN_BAUDRATE == 125 /* 125KBps */ CAN_InitStructure.CAN_Prescaler =
48; #elif CAN_BAUDRATE == 100 /*
100KBps
*/
CAN_InitStructure.CAN_Prescaler = 60;
#elif CAN_BAUDRATE == 50 /* 50KBps */
CAN_InitStructure.CAN_Prescaler = 120;
#elif CAN_BAUDRATE == 20 /* 20KBps */
CAN_InitStructure.CAN_Prescaler = 300;
#elif CAN_BAUDRATE == 10 /* 10KBps */
CAN_InitStru cture.CAN_Prescaler = 600;
#endif
CAN_Init(CAN1, &CAN_InitStructure); //Initialize CAN register
/* CAN filter init */
CAN_FilterInitStructure.CAN_FilterNumber=1; // Select filter numberCAN_FilterInitStructure.CAN_FilterMode
=CAN_FilterMode_IdMask; // Select filter type as mask bit modeCAN_FilterInitStructure.CAN_FilterScale
=CAN_FilterScale_32bit; // Select filter width as a 32-bit filterCAN_FilterInitStructure.CAN_FilterIdHigh
=0x0000; // Identifier matchCAN_FilterInitStructure.CAN_FilterIdLow
=0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh=0x0000; // Identifier mask bit, 1: must match, 0: don't careCAN_FilterInitStructure.CAN_FilterMaskIdLow=
0x0000;
CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_FIFO0; // Select the associated FIFO to be stored as FIFO0
CAN_FilterInitStructure.CAN_FilterActivation=ENABLE; // Activate the filter
CAN_FilterInit(&CAN_FilterInitStructure); // Initialize the filter
/* CAN FIFO0 message pending interrupt enable */
CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE); // Set CAN1, FIFO0 receive interrupt enable
// CAN_ITConfig(CAN1, CAN_IT_FMP0, DISABLE);
}
/*******************************************************************************
* Function Name : bxCAN_Configuration
* Description : CAN初始化
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void bxCAN_Configuration(void)
{
bxCAN_Port_Configuration();
bxCAN_Property_Configuration();
}
/*******************************************************************************
* Function Name : Interrupt_Handle_bxCAN
* Description : 中断服务函数
* Input : None
* Output : None
* Return : None
*******************************************************************************/
void Interrupt_Handle_bxCAN(void)
{
CanRxMsg RxMessage;
RxMessage.StdId=0x00;
RxMessage.ExtId=0x00;
RxMessage.IDE=0;
RxMessage.DLC=0;
RxMessage.FMI=0;
RxMessage.Data[0]=0x00;
RxMessage.Data[1]=0x00;
CAN_Receive(CAN1, CAN_FIFO0, &RxMessage);
}
Initialize the first part of the basic property settings. You need to look at the datasheet, the CAN sending process and receiving process, and then look at its related status register to understand its meaning. In the filter setting part, you need to understand the difference between its two modes. The mask bit mode is to give a reference value and then use the mask attribute to match, and the list mode is to directly match all according to the reference value of the register. I did not make any special settings for the mask bit here, just set it to accept all.
This process only implements sending standard frames, extended frames, and receiving frame data.
The receiving program uses the interrupt method, see the code function Interrupt_Handle_bxCAN() above, and the sending code is as follows:
void Send_Std_KLS_KL15(unsigned char value)
{
CanTxMsg TxMessage;
TxMessage.StdId=0x570;
TxMessage.IDE=CAN_ID_STD;
TxMessage.RTR=CAN_RTR_DATA;
TxMessage.DLC=8;
TxMessage.Data[0]=value;
TxMessage.Data[1]=0x00;
TxMessage.Data[2]=0x00;
TxMessage.Data[3]=0x00;
TxMessage.Data[4]=0x00;
TxMessage.Data[5]=0x00;
TxMessage.Data[6]=0x00;
TxMessage.Data[7]=0x00;
CAN_Transmit(CAN1, &TxMessage);
}
This is sending a standard frame. If an extended frame is sent, it is as follows:
void Send_Exd_message(void)
{
CanTxMsg TxMessage;
TxMessage.StdId=0x0000;
TxMessage.ExtId=0x1234;
TxMessage.IDE=CAN_ID_EXT;
TxMessage.RTR=CAN_RTR_DATA;
TxMessage.DLC=2;
TxMessage.Data[0]=0xDE;
TxMessage.Data[1]=0xCA;
CAN_Transmit(CAN1, &TxMessage);
}
Since CAN makes the data link layer transparent, in practical applications, the CAN network can be used efficiently as long as the shield bit is used properly.
Previous article:About the global reference of STM32 Systick delay function variables
Next article:STM32 uCOS_II practice of external interrupt events and system operation process
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Wi-Fi 8 specification is on the way: 2.4/5/6GHz triple-band operation
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Vietnam's chip packaging and testing business is growing, and supply-side fragmentation is splitting the market
- Three steps to govern hybrid multicloud environments
- Three steps to govern hybrid multicloud environments
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Microchip Accelerates Real-Time Edge AI Deployment with NVIDIA Holoscan Platform
- Melexis launches ultra-low power automotive contactless micro-power switch chip
- Melexis launches ultra-low power automotive contactless micro-power switch chip
- 【Free Trial】DFRobot micro:bit Programming Car-McQueen
- How is the storage period of components calculated?
- The Definitive Guide to FPGA Rapid System Prototyping (Chinese)
- Temperature problems solved for you (IV) Ambient temperature monitoring
- LGA-12 package soldering issues
- [NXP Rapid IoT Review] +3.rapid-iot-studio example bin summary
- GD32E231 Learning 4: External Interrupt EXTI
- The smallest Bluetooth module in the industry? Now available
- Questions about I2C communication
- Bullshit, playing with a 4.2-inch e-ink screen price tag