STM32CubeMX configuration CAN bus communication learning record (can't learn to find me)

STM32CubeMX configuration

First, open STM32CubeMX and select the chip model to build the project. Here I choose STM32F03ZET6 (Punctual Atomic Warship V3). The specific process of building a new project will not be repeated, it is too basic.
First configure the SYS and RCC tabs under the System Core directory as shown below:
(1) Configure Debug under SYS as Serial Wire

Configuration
(2) Configure the HSE (high-speed clock) under RCC as an external crystal Crystal/Ceramic Resonator, which is set according to the hardware configuration of the board

Insert picture description here
(3) Enable CAN bus and configure related parameters

Insert picture description here
The configuration method of CAN bus related parameters is explained here. In F103ZET6, CAN is a low-speed peripheral mounted under APB1, and the clock is 36MHz. The special rate is related, I set the frequency division to 36 here, so that the clock is 1MHz, and each cycle is 1us (that is, 1 Time in the following parameter is 1us) for easy calculation, Time Quanta in Bit Segment 1 and Time Quanta in Bit Segment 2 are also two parameters that affect the baud rate, the specific calculation is as follows:

Bound=1/(1*Tq+Tqbs1+Tqbs2)

Among them, Tqbs1 represents the time corresponding to Time Quanta in Bit Segment 1, Tqbs2 represents the time corresponding to Time Quanta in Bit Segment 2, and Tq represents the time of 1 Time.

So take my configuration example: 1/(1us+4us+5us)=100K, this is my baud rate.

In addition, by the way, because I only have one battleship V3, the CAN on the MIni board is not led out, so I set the Operating Mode under Advenced Parameter to Loopback, that is, the loopback mode (spontaneous sending and receiving).

(4) Serial port configuration (used to display the data sent and received by the host computer to facilitate the effect)

Insert picture description here
Configure the serial port mode to Asynchronous, hardware flow control Disable, and the default parameters such as baud rate word width. In addition, open the USART1 global interruput under NVIC Setting to facilitate the reception of data from the host computer:
Insert picture description here
Since the serial port is mentioned, let me mention DMA by the way Well, turning on DMA can greatly save CPU resources and reduce the burden on the CPU. Add two DMA channels (USART1_RX and USART1_TX) under the DMA Setting tab, and Mode is temporarily set to Normal mode, of course, it can also be set to Circle mode, so that DMA will continue to send out crazy continuously. In this test, it is Not required. The default Data Width is Byte. As shown in the figure below: So
Insert picture description here
far, the settings of the serial port and CAN bus have been completed.

(5) Clock tree configuration

The picture above will do

Insert picture description here
(6) Set the project name and file path and IDE

IDE chooses according to the development tool you use. I use Keil V5 here and check Copy only the necessry library files, so that the generated project only contains the relevant library files used for configuration and there is no redundancy. Check Generate peripheral initialization as a pair of'.c/.h' file per peripheral. The function of this option is to generate different source files and header files for the relevant configuration code of each peripheral, making the project cleaner.
Insert picture description here
Insert picture description here
(7) Generate code
Insert picture description here
directly GENERATE CODE
Insert picture description here
is enough. After the generation is completed, you can open the folder to see the generated file directory, or open the project directly.

Code addition and modification

(1) Add some CAN bus transceiver functions and filter functions

Open the can.c file under Application/User in the project directory, and at the end
/* USER CODE BEGIN 1 */

/*
Add your own code between USER CODE END 1 */ , otherwise if the STM32CubeMX configuration error needs to modify the configuration and regenerate the code, this part of the code will be overwritten, which is equivalent to white writing, so be sure to write in these two Remember in the middle of the comment!!

Here I post my code for everyone to use, if you find a bug, please tell me thank you!

void CAN_FilterInit(CAN_HandleTypeDef *hcan)
{
	CAN_FilterTypeDef CAN_FilterInitStructure;
	CAN_FilterInitStructure.FilterMode = CAN_FILTERMODE_IDMASK;
	CAN_FilterInitStructure.FilterScale = CAN_FILTERSCALE_32BIT;
	CAN_FilterInitStructure.FilterIdHigh = 0x2460;
	CAN_FilterInitStructure.FilterIdLow = 0x0000;
	CAN_FilterInitStructure.FilterMaskIdHigh = 0xF0E0;
	CAN_FilterInitStructure.FilterMaskIdLow = 0x0000;
	CAN_FilterInitStructure.FilterBank = 0;
	CAN_FilterInitStructure.FilterFIFOAssignment = CAN_RX_FIFO0;
	CAN_FilterInitStructure.FilterActivation = ENABLE;
	CAN_FilterInitStructure.SlaveStartFilterBank = 14;
	if(HAL_CAN_ConfigFilter(hcan,&CAN_FilterInitStructure) != HAL_OK)
	{
		Error_Handler();
	}
	if(HAL_CAN_ActivateNotification(hcan,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
	{
		Error_Handler();
	}
	if(HAL_CAN_Start(hcan) != HAL_OK)
	{
		Error_Handler();
	}
}

And remember to declare it in can.h.

(2) CAN bus transceiver function. I put the callback function of the serial port's receiving and sending completion directly in main.c, and I posted it here for your reference (also remember to declare it in the first part of main.c):

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)//CAN Receive
{
	CAN_RxHeaderTypeDef RX_Header;
	HAL_CAN_GetRxMessage(hcan,CAN_RX_FIFO0,&RX_Header,RX_Data);
	HAL_CAN_ActivateNotification(hcan,CAN_IT_RX_FIFO0_MSG_PENDING);
}

void CAN_Send_Msg(CAN_HandleTypeDef *hcan,uint8_t *msg,uint8_t len,uint32_t id)//CAN Transmit
{
	CAN_TxHeaderTypeDef Tx_Header;
	uint32_t TxMailBox;
	
	Tx_Header.StdId = id;
	Tx_Header.IDE = CAN_ID_STD;
	Tx_Header.RTR = CAN_RTR_DATA;
	Tx_Header.DLC = len;
	
	HAL_CAN_AddTxMessage(hcan,&Tx_Header,msg,&TxMailBox);
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart == &huart1)
	{
		HAL_UART_Receive_DMA(&huart1,(uint8_t*)TX_Data,sizeof(TX_Data));
	}	
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart == &huart1)
	{
		CAN_Send_Msg(&hcan,TX_Data,sizeof(TX_Data),0x123);
		HAL_UART_Transmit_DMA(&huart1,(uint8_t*)RX_Data,sizeof(RX_Data));
	}
}

(3) In addition, remember to turn on the serial port DMA reception and transmission at the beginning of the Main function, and define the relevant variables

uint8_t RX_Data[8];
uint8_t TX_Data[8];
CAN_TxHeaderTypeDef TxHeader;

CAN_FilterInit(&hcan);
HAL_UART_Transmit_DMA(&huart1,(uint8_t*)RX_Data,sizeof(RX_Data));
HAL_UART_Receive_DMA(&huart1,(uint8_t*)TX_Data,sizeof(TX_Data));

Note: In addition, functions such as sprintf used in the program should include stdio header files.

The function of this test is to receive data from the serial port, and then send it out through the CAN bus. Because the loopback mode is configured, the same CAN data input will be received. After the data is received, it will be sent to the host computer through the serial port DMA method for display. Similar to the echo experiment of the serial port, except that there is another CAN line in the middle, hahaha it's enough for me...

After compiling and downloading, the effect is as shown in the figure

Insert picture description here
The article is over here, thank you all

Guess you like

Origin blog.csdn.net/Haders_0610/article/details/109312713