CAN bus study notes | CAN box test CAN interrupt reception of STM32

CAN basic knowledge introduction This article introduces the basic knowledge of the CAN protocol and the CAN controller related knowledge of the STM32F4 chip. The following will use the STM32CubeMX graphical configuration tool and cooperate with the CAN box to realize the interrupt sending and receiving test of the CAN communication through an example.

1. STM32CubeMX configuration

  • CAN is mounted on the APB1 bus, set the PCLK1 clock frequency to a maximum of 45MHz

insert image description here

  • Activate CAN1, configure bit timing parameters, other basic parameters and working mode (here set toLoopback mode

insert image description here

Calculation formula of CAN baud rate: You only need to know the settings of BS1 and BS2, and the clock frequency of APB1, you can easily calculate the baud rate. For example, if you set TS1=8, TS2=6 and BRP=6, under the condition that APB1 frequency is 45Mhz, you can get the baud rate of CAN communication=45000/6/(8+6+1)=500Kbps
insert image description here

  • Activate USART1 as the debugging serial port, and configure the GPIO pin corresponding to the relevant LED as the indicator light

Two, MDK-ARM programming

2.1 Several important structures

  • CAN initialization structure: the content of this structure can be configured by the STM32CubeMX tool
typedef struct
{
    
    
  uint32_t Prescaler;  					/* 配置 CAN 外设的时钟分频,可设置为 1-1024*/
  uint32_t Mode;       					/* 配置 CAN 的工作模式,回环或正常模式 */
  uint32_t SyncJumpWidth;  				/* 配置 SJW 极限值 */
  uint32_t TimeSeg1;   					/* 配置 BS1 段长度 */
  uint32_t TimeSeg2;   					/* 配置 BS2 段长度 */
  FunctionalState TimeTriggeredMode;   	/* 是否使能 TTCM 时间触发功能 */
  FunctionalState AutoBusOff;     		/* 是否使能 ABOM 自动离线管理功能 */
  FunctionalState AutoWakeUp;   		/* 是否使能 AWUM 自动唤醒功能 */
  FunctionalState AutoRetransmission;  	/* 是否使能 NART 自动重传功能 */
  FunctionalState ReceiveFifoLocked;   	/* 是否使能 RFLM 锁定 FIFO 功能 */
  FunctionalState TransmitFifoPriority;	/* 配置 TXFP 报文优先级的判定方法 */
} CAN_InitTypeDef;
  • Sending and receiving header structure: mainly used to construct sending messages and receiving messages. When sending and receiving files, you need to customize the header structure variable
typedef struct
{
    
    
  uint32_t StdId;    			/* 存储报文的标准标识符 11 位,0-0x7FF. */
  uint32_t ExtId;    			/* 存储报文的扩展标识符 29 位,0-0x1FFFFFFF. */
  uint32_t IDE;     			/* 存储 IDE 扩展标志 */
  uint32_t RTR;    				/* 存储 RTR 远程帧标志 */
  uint32_t DLC;    				/* 存储报文数据段的长度,0-8 */
  FunctionalState TransmitGlobalTime; 
} CAN_TxHeaderTypeDef;

typedef struct
{
    
    
  uint32_t StdId;    			/* 存储报文的标准标识符 11 位,0-0x7FF. */
  uint32_t ExtId;    			/* 存储报文的扩展标识符 29 位,0-0x1FFFFFFF. */
  uint32_t IDE;     			/* 存储 IDE 扩展标志 */
  uint32_t RTR;      			/* 存储 RTR 远程帧标志 */
  uint32_t DLC;     			/* 存储报文数据段的长度,0-8 */
  uint32_t Timestamp; 
  uint32_t FilterMatchIndex; 
} CAN_RxHeaderTypeDef;
  • Filter structure: STM32CubeMX will not initialize the relevant content of the filter, you need to add it yourself
typedef struct
{
    
    
  uint32_t FilterIdHigh;         	/*CAN_FxR1 寄存器的高 16 位 */
  uint32_t FilterIdLow;         	/*CAN_FxR1 寄存器的低 16 位 */
  uint32_t FilterMaskIdHigh;   		/*CAN_FxR2 寄存器的高 16 位 */
  uint32_t FilterMaskIdLow;    		/*CAN_FxR2 寄存器的低 16 位 */
  uint32_t FilterFIFOAssignment;  	/* 设置经过筛选后数据存储到哪个接收 FIFO */
  uint32_t FilterBank;            	/* 筛选器编号,范围 0-27,数据手册上说0-27是CAN1/CAN2共享,但是实测发现并不是这样,CAN1是0-13,CAN2是14-27 */
  uint32_t FilterMode;            	/* 筛选器模式 */
  uint32_t FilterScale;           	/* 设置筛选器的尺度 */
  uint32_t FilterActivation;      	/* 是否使能本筛选器 */
  uint32_t SlaveStartFilterBank;  	/* CAN2起始过滤器组 */
} CAN_FilterTypeDef;

4.2 Programming

  • After generating the project, open the can.c file, it can be seen that STM32CubeMX has initialized the bit timing parameters, other basic parameters and working modes. However, there is no initialization filter related content, so we need to add it ourselves and call it when CAN is initialized
//下面的设置只使能了FIFO0,并不过滤任何消息
void CAN_Filter_Config(){
    
    
	CAN_FilterTypeDef sFilterConfig;
	
	sFilterConfig.FilterBank = 0;						//筛选器编号, CAN1是0-13, CAN2是14-27
	sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;	//采用掩码模式
	sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;	//设置筛选器的尺度, 采用32位
	sFilterConfig.FilterIdHigh = 0X0000;				//过滤器ID高16位,即CAN_FxR1寄存器的高16位
	sFilterConfig.FilterIdLow = 0X0000;					//过滤器ID低16位,即CAN_FxR1寄存器的低16位
	sFilterConfig.FilterMaskIdHigh = 0X0000;			//过滤器掩码高16位,即CAN_FxR2寄存器的高16位
	sFilterConfig.FilterMaskIdLow = 0X0000;				//过滤器掩码低16位,即CAN_FxR2寄存器的低16位
	sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;	//设置经过筛选后数据存储到哪个接收FIFO
	sFilterConfig.FilterActivation = ENABLE;			//是否使能本筛选器
	sFilterConfig.SlaveStartFilterBank = 14;			//指定为CAN1分配多少个滤波器组
	
	if(HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK)
	{
    
    
		Error_Handler();
	}
}
  • Write the function of sending and interrupt receiving data: here the sending format is fixed as a standard data frame, and the ID is 12
uint8_t CAN1_Send_Msg(uint8_t *msg, uint8_t len){
    
    
	uint16_t i = 0;
	uint32_t txMailBox;
	uint8_t send_buf[8];
	
	txHeader.StdId = 12;
	txHeader.ExtId = 12;
	txHeader.IDE = CAN_ID_STD;
	txHeader.RTR = CAN_RTR_DATA;
	txHeader.DLC = len;
	
	for(i = 0; i < len; i++)
		send_buf[i] = msg[i];
	
	if(HAL_CAN_AddTxMessage(&hcan1, &txHeader, send_buf, &txMailBox) != HAL_OK)
		return 1;	
	return 0;
}

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan){
    
    
	uint16_t i = 0;
	uint8_t buf[8] = {
    
    0};
	
	if(hcan->Instance == CAN1){
    
    
		printf("*******************************\r\n");
		printf("Recv via STM32F429 Interrupt\r\n");
	
		HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rxHeader, buf);
	
		if(rxHeader.IDE == CAN_ID_STD)
			printf("StdId ID: %d\n", rxHeader.StdId);
		else
			printf("ExtId ID: %d\n", rxHeader.ExtId);
		printf("\r\n");
		printf("CAN IDE: %d\n", rxHeader.IDE);printf("\r\n");
		printf("CAN RTR: %d\n", rxHeader.RTR);printf("\r\n");
		printf("CAN DLC: %d\n", rxHeader.DLC);printf("\r\n");
		printf("Recv Data: ");
	
		for(i = 0; i < rxHeader.DLC; i++)
			printf("%c ",buf[i]);
	
		printf("\r\n");
		printf("*******************************\r\n");
	}
}
  • By default, the code generated by Cubemx does not have can start, and HAL_CAN_Start(&hcan1) is not called to enable CAN, nor is interrupt reception activated, so the following code needs to be added to the CAN initialization function
void MX_CAN1_Init(void){
    
    
	......
	/* USER CODE BEGIN CAN1_Init 2 */
	CAN_Filter_Config();
	HAL_CAN_Start(&hcan1);	
	HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
  	/* USER CODE END CAN1_Init 2 */
}
  • In the main function main.c, the code is as follows
int main(void){
    
    
  	HAL_Init();
  	SystemClock_Config();
 	MX_GPIO_Init();
  	MX_CAN1_Init();
  	MX_USART1_UART_Init();
  	/* USER CODE BEGIN 2 */
	uint8_t ret;
	printf("CAN Testing....!\r\n");
	uint8_t txdata[8] = {
    
    78, 79, 82, 77, 65, 76, 33, 32};
  	/* USER CODE END 2 */
  	/* Infinite loop */
  	/* USER CODE BEGIN WHILE */
  	while (1)
  	{
    
    
		HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_1);
		printf("Start Send data...\r\n");
		
		ret = CAN1_Send_Msg(txdata, 8);
		if(ret == 0)
			printf("STM32F429 CAN Send success!\r\n");
		else 
			printf("STM32F429 CAN Send failed!\r\n");
		
		HAL_Delay(3000);
    	/* USER CODE END WHILE */
    	/* USER CODE BEGIN 3 */
  	}
  	/* USER CODE END 3 */
}

3. Download test

Connect the CAN box with the CAN interface of STM32, connect the CAN box to the computer, and use the CAN debugging software to receive and send data, as shown below

insert image description here

After the STM32 project is compiled correctly, download it to the development board. You can see that the D1 indicator light keeps flashing when the system is running, and the serial port keeps printing the information that STM32 has successfully sent CAN messages. Using the CAN debugging software, you can see that the CAN box has received the data sent by the STM32. Use the debugging software to send CAN data to STM32

insert image description here

As can be seen in the serial port debugging assistant, the STM32 has received the data from the CAN box through the interrupt

insert image description here

Guess you like

Origin blog.csdn.net/Chuangke_Andy/article/details/127817895