基于CubeMx的STM32的can通信代码

首先是关于CubeMx的使用,他只是帮助你完善一些初始化的问题,也可以的让你去避开对于底层的触碰。

我是基于F103的,其实F4等等,大同小异。

我默认你会使用CubeMx,如果你不会可以看看这个博主的教程: http://t.csdn.cn/eKcbZ

讲的很细致,估计聪明的你几个小时就学会了。

这里我们配置的是使用外部时钟,我的外部时钟是8M的:

这里主要是为了后期你可以使用stlink, 或者别的工具去Debug:

 下面我们可以配置一下时钟树:

我标记的位置都是很重要的,比如PCLK1是用于can通信的,所以计算波特率的时候可能会有影响。(倘若觉得后面的你在配置波特率的时候,觉得自己没问题,或许问题会出在时钟初始化,那么就要好好看看了。我碰到过,不赘述了)

 现在配置一下can的参数:

 我建议加上中断,因为我试了不加中断的can接收,没有成功。最后只能在中断里进行了。

我这里配置的是250K的波特率,倘若你要配置500K ,则是9,5,2;配置这个波特率首先要知道原理,这个自行百度,其次我的经验是就在这里实验,看看能不能用。软件中试触法完全可以。之后生成就可以了。我觉得我的步骤是不健全的,但是太全了你会不会没有思考的地方呢?我依旧认为你是个聪明的人。

初始化代码:

 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;
}

特别提醒,CubeMx是不帮你配置过滤器,邮箱的,这需要你自己亲历亲为:

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();
 }
 

}

发送的函数:

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;
	 }
}

接收函数(非中断版本),这个是我是失败的,如果你会你可以在评论中补充:

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;
}

中断版本的接收函数:

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

貌似就这些了。我主要碰到的问题是,配置波特率,接收不可以用在whlie中,只能用中断。

我已经将完整的代码上传,如果有需要可以下载,1个积分,不做伸手党。

猜你喜欢

转载自blog.csdn.net/qq_41059950/article/details/126596483