STM32 can communication code based on CubeMx

The first is about the use of CubeMx. It only helps you improve some initialization issues, and also allows you to avoid touching the bottom layer.

I based it on F103. In fact, F4 and so on are pretty much the same.

I assume you will use CubeMx. If you don’t know how, you can check out this blogger’s tutorial:  http://t.csdn.cn/eKcbZ

The explanation is very detailed. If you are smart, you will probably learn it in a few hours.

What we configure here is to use an external clock. My external clock is 8M:

This is mainly so that you can use stlink or other tools to debug later:

 Next we can configure the clock tree:

The positions I marked are very important. For example, PCLK1 is used for CAN communication, so it may have an impact when calculating the baud rate. (If you think you have no problem later when configuring the baud rate, maybe the problem lies in the clock initialization, then you should take a closer look. I have encountered it, so I won’t go into details.)

 Now configure the parameters of can:

 I suggest adding interrupts, because I tried can reception without interrupts, but it didn't work. In the end, it can only be done in interruption.

What I configure here is a baud rate of 250K. If you want to configure 500K, it is 9, 5, 2. To configure this baud rate, you must first know the principle. You can do this on Baidu. Secondly, my experience is to experiment here. See See if it works. It is completely possible to try out the method in the software. Then just generate it. I think my steps are unsound, but if they are too complete, will you not have anything to think about? I still think you're a smart guy.

Initialization code:

 uint8_t CAN1_Mode_Init(u32 tsjw,u32 tbs2,u32 tbs1,u16 brp,u32 mode)
{
	CAN_InitTypeDef		CAN1_InitConf;
    
    hcan.Instance=CAN1;
	
	  hcan.Init = CAN1_InitConf;
	
    hcan.Init.Prescaler=brp;				//分频系数(Fdiv)为brp+1
    hcan.Init.Mode=mode;					//模式设置 
    hcan.Init.SyncJumpWidth=tsjw;			//重新同步跳跃宽度(Tsjw)为tsjw+1个时间单位 
                                            //CAN_SJW_1TQ~CAN_SJW_4TQ

    hcan.Init.TimeSeg1=tbs1;				//tbs1范围CAN_BS1_1TQ~CAN_BS1_16TQ
    hcan.Init.TimeSeg2=tbs2;				//tbs2范围CAN_BS2_1TQ~CAN_BS2_8TQ
    hcan.Init.TimeTriggeredMode=DISABLE;	//非时间触发通信模式 
    hcan.Init.AutoBusOff=DISABLE;			//软件自动离线管理
    hcan.Init.AutoWakeUp=DISABLE;			//睡眠模式通过软件唤醒(清除CAN->MCR的SLEEP位)
    hcan.Init.AutoRetransmission=ENABLE;	//禁止报文自动传送 
    hcan.Init.ReceiveFifoLocked=DISABLE;	//报文不锁定,新的覆盖旧的 
    hcan.Init.TransmitFifoPriority=DISABLE;	//优先级由报文标识符决定 
	
    if(HAL_CAN_Init(&hcan)!=HAL_OK)			//初始化
		return 1;
        return 0;
}

Special reminder, CubeMx does not help you configure filters and mailboxes. You need to do this yourself:

void CAN_Config(void)
{	

	CAN_FilterTypeDef  sFilterConfig;

  /*配置CAN过滤器*/
  sFilterConfig.FilterBank = 0;                     //过滤器0
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
  sFilterConfig.FilterIdHigh = 0x0000;              //32位ID
  sFilterConfig.FilterIdLow = 0x0000;
  sFilterConfig.FilterMaskIdHigh = 0x0000;          //32位MASK
  sFilterConfig.FilterMaskIdLow = 0x0000;
  sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;//过滤器0关联到FIFO0
  sFilterConfig.FilterActivation = ENABLE;          //激活滤波器0
  sFilterConfig.SlaveStartFilterBank = 14;
	
	
 if(HAL_CAN_ConfigFilter(&hcan,&sFilterConfig) != HAL_OK)//初始化过滤器
 {
  Error_Handler();
 }
 if(HAL_CAN_Start(&hcan) != HAL_OK)//打开can
 {
  Error_Handler();
 }
 if(HAL_CAN_ActivateNotification(&hcan,CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)//开启接受邮箱 
                                                                                //0挂起中断
 {
  Error_Handler();
 }
 

}

Send function:

void CAN_senddata(CAN_HandleTypeDef *hcan,uint32_t can_id)
{
     TXHeader.StdId=can_id ;
	 TXHeader.ExtId=0x12345000;//0x12345000
	 TXHeader.DLC=8;
	 TXHeader.IDE=CAN_ID_EXT;
	 TXHeader.RTR=CAN_RTR_DATA;
	 TXHeader.TransmitGlobalTime = DISABLE;
	 if(KEY == 0)
    	HAL_CAN_AddTxMessage(hcan,&TXHeader,TXmessage,&pTxMailbox);//发送
     else if(KEY == 1)
			
	 {
		 HAL_CAN_AddTxMessage(hcan,&TXHeader,RXmessage,&pTxMailbox);把接收的再次发送
		 KEY = 0;
	 }
}

Receive function (non-interrupt version), this is what I failed with, if you can you can add in the comments:

uint32_t CAN1_Receive_Msg(u8 *buf)
{
 	u32 i;
	u8	RxData[8];

	if(HAL_CAN_GetRxFifoFillLevel(&hcan, CAN_RX_FIFO0) != 1)//没有接收到数据,直接退出 
	{
		return 0xF1;
	}

	if(HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &RXHeader, RxData) != HAL_OK)
	{
		return 0xF2;
	}
	
    for(i=0;i<RXHeader.DLC;i++)
    buf[i]=RxData[i];
	  return RXHeader.DLC;
}

Interrupt version of the receive function:

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance==CAN1)
	{
		KEY = 1;
		HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&RXHeader,RXmessage);//获取数据
	}
 
}

Looks like that's all. The main problem I encountered is that when configuring the baud rate, reception cannot be used in whlie, only interrupts can be used.

I have uploaded the complete code, you can download it if necessary, 1 point, no need to reach out.

Guess you like

Origin blog.csdn.net/qq_41059950/article/details/126596483