学习记录--CAN通信

目录

一,基本原理部分

二,cubeMX配置

1. 配置波特率

2. 打开接收中断(本实验开个邮箱0(FIFO0)即可)

 三. keil中代码

1. 配置过滤器

 2. 数据帧的发送:

 3. 数据帧的接收

4. 开启CAN


一,基本原理部分

参考:(12条消息) CAN通信知识梳理及在Stm32上的应用(HAL库)_冬瓜-CSDN博客

二,cubeMX配置

1. 配置波特率

由中文参考手册:

 位时序如下:

2. 打开接收中断(本实验开个邮箱0(FIFO0)即可)

 三. keil中代码

1. 配置过滤器

对于掩码模式的过程:

 寄存器 CAN_TIxR 各位描述:

 几种模式的过滤器配置:

//32位列表模式过滤器配置(这里配置R1用来过滤标准ID(StdId),R2用来过滤拓展ID(ExtId))
void CANFilterConfig_Scale32_IdList(CAN_HandleTypeDef * hcan,uint32_t StdId,uint32_t ExtId,uint8_t Filter_Number )  
{  
  CAN_FilterTypeDef  sFilterConfig;   	
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;  //设为列表模式  
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; //配置为32位宽  
  sFilterConfig.FilterIdHigh = StdId<<5;      			 //如图基本ID左移5位,放入到STID中  
  sFilterConfig.FilterIdLow = 0|CAN_ID_STD;     		 //设置IDE位为0  
  sFilterConfig.FilterMaskIdHigh = ((ExtId<<3)>>16)&0xffff;  //拓展ID前部分存入R2高位中
  sFilterConfig.FilterMaskIdLow = ((ExtId<<3)&0xffff)|CAN_ID_EXT;//拓展ID后部分存入R2低位并且设置IDE位为1  
  sFilterConfig.FilterFIFOAssignment = 0;    //接收到的报文放入到FIFO0中  
  sFilterConfig.FilterActivation = ENABLE;  
  sFilterConfig.FilterBank = Filter_Number;  //选择使用第n个过滤器(to definition可知和以前用的can库中的FilterNumber相同)
  HAL_CAN_ConfigFilter(hcan, &sFilterConfig) ;
}

//16位列表模式过滤器配置(可以写入四个标准ID)
void CANFilterConfig_Scale16_IdList(CAN_HandleTypeDef * hcan,uint32_t StdId1,uint32_t StdId2,uint32_t StdId3,uint32_t StdId4, uint8_t Filter_Number)  
{  
  CAN_FilterTypeDef  sFilterConfig;  
  sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;   //设为列表模式  
  sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;  //位宽设置为16位  
  sFilterConfig.FilterIdHigh = StdId1<<5;  						//4个标准CAN ID分别放入到4个存储中  
  sFilterConfig.FilterIdLow = StdId2<<5;  
  sFilterConfig.FilterMaskIdHigh = StdId3<<5;  
  sFilterConfig.FilterMaskIdLow = StdId4<<5;  	//因为只能过滤标准ID故不需要配IDE位
  sFilterConfig.FilterFIFOAssignment = 0;   //接收到的报文放入到FIFO0中  
  sFilterConfig.FilterActivation = ENABLE;  
  sFilterConfig.FilterBank = Filter_Number;  
  HAL_CAN_ConfigFilter(hcan, &sFilterConfig); 
}

//32位掩码模式过滤器配置(验证码(期望ID):ID,屏蔽码(哪些位必须一样):Mask)
void CANFilterConfig_Scale32_IdMask(CAN_HandleTypeDef * hcan,uint32_t ID,uint32_t Mask,uint8_t ID_Type, uint8_t Filter_Number)  
{
	if(ID_Type==0) //标准ID
  {
		CAN_FilterTypeDef  sFilterConfig;  
		sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;     //配置为掩码模式  
		sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;    //设置为32位宽  
		sFilterConfig.FilterIdHigh =ID<<5;     
		sFilterConfig.FilterIdLow =0;  								//设置IDE位为0
		sFilterConfig.FilterMaskIdHigh =(Mask<<5);  
		sFilterConfig.FilterMaskIdLow =0|0x02;        //置位RTR:只接收数据帧  
		sFilterConfig.FilterFIFOAssignment = 0;       //设置通过的数据帧进入到FIFO0中  
		sFilterConfig.FilterActivation = ENABLE;  
		sFilterConfig.FilterBank = Filter_Number;  							
		HAL_CAN_ConfigFilter(hcan, &sFilterConfig);
  }
  else //扩展ID
  {
		CAN_FilterTypeDef  sFilterConfig;   
		sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;         //配置为掩码模式  
		sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;        //设为32位宽  
		sFilterConfig.FilterIdHigh =((ID<<3) >>16) &0xffff;
		sFilterConfig.FilterIdLow =((ID<<3)&0xffff) | CAN_ID_EXT; //设置IDE位为1
		sFilterConfig.FilterMaskIdHigh = (Mask>>16)&0xffff;  
		sFilterConfig.FilterMaskIdLow = (Mask&0xffff)|0x02;       //只接收数据帧  
		sFilterConfig.FilterFIFOAssignment = 0;  
		sFilterConfig.FilterActivation = ENABLE;  
		sFilterConfig.FilterBank = Filter_Number;  
		HAL_CAN_ConfigFilter(hcan, &sFilterConfig);
  }
}

 2. 数据帧的发送:

//发送标准ID数据帧(数据数组指针:pData)
uint8_t CANx_SendStdData(CAN_HandleTypeDef* hcan,uint16_t ID,uint8_t *pData,uint16_t Len)
{
  static CAN_TxHeaderTypeDef   Tx_Header;
	
	Tx_Header.StdId=ID;						//标准数据帧ID
	Tx_Header.ExtId=0;
	Tx_Header.IDE=CAN_ID_STD;		 //标准帧,IDE设置为0
	Tx_Header.RTR=CAN_RTR_DATA;	 //发送数据帧,RTR设置为0:CAN_RTR_DATA = 0x00000000U
	Tx_Header.DLC=Len;					 //数据长度
  //找到空的发送邮箱发送数据
	if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX0) != HAL_OK) //
	{
		if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX1) != HAL_OK)
		{
			HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX2);
		}
	}
}

//发送拓展ID数据帧
uint8_t CANx_SendExtData(CAN_HandleTypeDef* hcan,uint32_t ID,uint8_t *pData,uint16_t Len)
{
	static CAN_TxHeaderTypeDef   Tx_Header;
	
	Tx_Header.StdId=0;
	Tx_Header.ExtId=ID;						//拓展数据帧ID
	Tx_Header.IDE=CAN_ID_EXT;
	Tx_Header.RTR=CAN_RTR_DATA;
	Tx_Header.DLC=Len;
  //找到空的发送邮箱发送数据
	if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX0) != HAL_OK) 
	{
		if(HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX1) != HAL_OK)
		{
			HAL_CAN_AddTxMessage(hcan, &Tx_Header, pData, (uint32_t*)CAN_TX_MAILBOX2);
		}
	}
}

 3. 数据帧的接收

uint8_t date_CAN1[8];        //用于接收数据

//CAN接收(写在FIFO0接收中断回调里)
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan->Instance ==CAN1)
	{
	  CAN_RxHeaderTypeDef RxHeader;  //接受句柄(不需要配置,只需要拿来接即可,内容已经配置在TxHeader)
	  HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, date_CAN1); //接收,CAN邮箱为0
	}
}

4. 开启CAN

void My_CAN_START(CAN_HandleTypeDef *hcan)
{
	HAL_CAN_Start(hcan);
	if(HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
	{
		Error_Handler();
	}
}

四. 调试记录

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KEIL5是一种嵌入式系统开发工具,可用于编写CAN通信代码。CAN通信是一种常用的嵌入式系统通信协议,用于在不同的设备之间进行高速、可靠的数据传输。 使用KEIL5编写CAN通信代码分为以下几个步骤: 1. 配置CAN硬件: 首先,我们需要配置CAN控制器的工作参数,包括波特率、CAN模式、过滤器等。在KEIL5中,可以通过寄存器等方式来配置CAN硬件。 2. 初始化CAN控制器: 在代码中,我们需要初始化CAN控制器,设置其工作模式、波特率等。这些参数需要根据实际的硬件配置来设置。 3. 使能CAN中断: 可以选择使能CAN中断,以便在接收到CAN消息或者发送完成时触发中断,并进行相应的处理。 4. 编写CAN通信代码: 在代码中,我们需要编写CAN的发送和接收函数。发送函数用于将数据发送到CAN总线上,而接收函数用于接收其他设备发送的CAN消息。这些函数需要根据实际需求编写,包括设置发送/接收的数据帧、标识符等。 5. 测试和调试: 在完成代码编写后,我们可以通过KEIL5提供的仿真功能进行代码的测试和调试。通过调试工具,我们可以检查CAN消息的发送和接收情况,以确保代码的正确性。 总结而言,使用KEIL5编写CAN通信代码需要完成CAN硬件的配置、初始化CAN控制器、使能CAN中断,编写CAN的发送和接收函数等步骤。通过对代码的测试和调试,可以确保CAN通信的正常运行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值