stm32f7 cubemx can 通讯

参考:https://blog.csdn.net/u012308586/article/details/81001102

https://blog.csdn.net/flydream0/article/details/52317532

https://blog.csdn.net/u012587637/article/details/52032630

1.CAN配置

 

 54/6/(10+7+1)=500k

 

2.usart.c

/* USER CODE BEGIN 0 */
#include "usart.h"	 
//2个3级深度的FIFO
#define   CAN1FIFO   CAN_RX_FIFO0	           
CAN_TxHeaderTypeDef     TxMeg;
CAN_RxHeaderTypeDef     RxMeg;
/*****************************************************************************
 * 函 数 名  : CAN_User_Init
 * 负 责 人  : by
 * 创建日期  : 2020年8月26日
 * 函数功能  : 
 * 输入参数  : 无
 * 输出参数  : 无
 * 返 回 值  : 
 * 调用关系  : 
 * 其    它  :
过滤器组:STM32总共提供14个过滤器组来处理CAN接收过滤问题,每个过滤器组包含两个32位寄存器CAN_FxR0和CAN_FxR1组成,在设置为屏蔽位模式下,其中一个作为标识符寄存器,另一个作为屏蔽码寄存器。过滤器组中的每个过滤器,编号(叫做过滤器号)从0开始,到某个最大数值(这时最大值并非13,而是取决于14个过滤器组的模式和位宽的设置,当全部配置为位宽为16,且为标识符列表模式时,最大编号为14*4-1=55)。
过滤器的过滤模式:STM32提供两种过滤模式供用户设置:屏蔽位模式和标识符列表模式。
		屏蔽位模式:为了过滤出一组标识符,应该设置过滤器组工作在屏蔽位模式。在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。
		标识符模式:为了过滤出一个标识符,应该设置过滤器组工作在标识符列表模式。在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用2个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符相同。
    列表模式:准备好一张表,把我们需要关注的所有CAN报文ID写上去,开始过滤的时候只要对比这张表,如果接收到的报文ID与表上的相符,则通过,如果表上没有,则不通过,这个就是简单的过滤方案。一个报文ID,则需要往列表中写入这个ID,如果需要关注两个,则需要写入两个报文ID,列表的方式受到列表容量大小的限制,实际上,bxCAN的一个过滤器若工作在列表模式下,scale为32时,每个过滤器的列表只能写入两个报文ID,若scale为16时,每个过滤器的列表最多可写入4个CAN ID
过滤器的位宽:
		每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过滤器组可提供:
		●1个32位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位
		●2个16位过滤器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位
过滤器组的过滤模式和位宽设置
    过滤器组可以通过相应的CAN_FMR寄存器(CAN过滤器主控寄存器)配置。但是不是什么时候都可以直接配置,在配置一个过滤器组前,必须通过清除CAN_FAR寄存器(CAN过滤器激活寄存器)的FACT位,把它设置为禁用状态。然后才能设置或设置过滤器组的配置。
    通过设置CAN_FS1R(CAN过滤器位宽寄存器)的相应FSCx位,可以配置一个过滤器组的位宽。
    通过CAN_FM1R(CAN过滤器模式寄存器)的FBMx位,可以配置对应的屏蔽/标识符寄存器的标识符列表模式或屏蔽位模式。  
*****************************************************************************/
void CAN_User_Init(CAN_HandleTypeDef* hcan )   //用户初始化函数
{
   CAN_FilterTypeDef  sFilterConfig;
   HAL_StatusTypeDef  HAL_Status;
	
  TxMeg.IDE=CAN_ID_STD;//标准帧模式
  TxMeg.RTR=CAN_RTR_DATA;//数据帧(对应有远程帧)
	
  sFilterConfig.FilterBank = 0;                       //过滤器0
  sFilterConfig.FilterMode =  CAN_FILTERMODE_IDMASK;  //设为标识符模式,STM32提供两种过滤模式供用户设置:屏蔽位模式和标识符列表模式    
  sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;  //过滤器位数32,只接收4个16位标准帧,或者2个32位帧
		
  sFilterConfig.FilterIdHigh = 0x0000<<5;   设置标识符寄存器高字节.CAN_FilterIdHigh包含的是STD[0~10]和EXID[13~17],标准CAN ID本身是不包含扩展ID数据,因此为了要将标准CAN ID放入此寄存器,标准CAN ID首先应左移5位后才能对齐.  
  sFilterConfig.FilterIdLow  = 0x0000<<5;    
		
  sFilterConfig.FilterMaskIdHigh =0x0000<<5;
  sFilterConfig.FilterMaskIdLow  =0x0000<<5; 
	
  sFilterConfig.FilterFIFOAssignment = CAN1FIFO;    //接收到的报文放入到FIFO0中 
 
  sFilterConfig.FilterActivation = ENABLE;  	//激活过滤器
  sFilterConfig.SlaveStartFilterBank  = 0; 
 
  HAL_Status=HAL_CAN_ConfigFilter(hcan, &sFilterConfig);
  HAL_Status=HAL_CAN_Start(hcan);  //开启CAN
  if(HAL_Status!=HAL_OK){
	printf("开启CAN失败\r\n");	
 }	
 HAL_Status=HAL_CAN_ActivateNotification(hcan,   CAN_IT_RX_FIFO0_MSG_PENDING);
 if(HAL_Status!=HAL_OK){
	printf("开启挂起中段允许失败\r\n");	
  }
 }
/*****************************************************************************
 * 函 数 名  : HAL_CAN_RxFifo0MsgPendingCallback
 * 负 责 人  : by
 * 创建日期  : 2020年8月26日
 * 函数功能  : 
 * 输入参数  : 无
 * 输出参数  : 无
 * 返 回 值  : 
 * 调用关系  : 
 * 其    它  :
*****************************************************************************/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)  //接收回调函数
{
  uint8_t  Data[8];
  HAL_StatusTypeDef	HAL_RetVal;
  if(hcan ==&hcan1){	
    HAL_RetVal=HAL_CAN_GetRxMessage(hcan,CAN1FIFO,&RxMeg,Data);
    if ( HAL_OK==HAL_RetVal){                              			
      //在这里接收数据
			Usart1SendData_DMA(Data,8);
    }
  }
}
 
/*****************************************************************************
 * 函 数 名  : CANx_SendNormalData
 * 负 责 人  : by
 * 创建日期  : 2020年8月26日
 * 函数功能  : 
 * 输入参数  : 无
 * 输出参数  : 无
 * 返 回 值  : 
 * 调用关系  : 
 * 其    它  :
*****************************************************************************/
uint8_t CANx_SendNormalData(CAN_HandleTypeDef* hcan,uint16_t ID,uint8_t *pData,uint16_t Len)
{
	HAL_StatusTypeDef	HAL_RetVal;
        uint16_t SendTimes,SendCNT=0;
	uint8_t  FreeTxNum=0;
	TxMeg.StdId=ID;
	if(!hcan || ! pData ||!Len)  return 1;
	SendTimes=Len/8+(Len%8?1:0);
	FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(hcan);
	TxMeg.DLC=8;
	while(SendTimes--){
		if(0==SendTimes){
			if(Len%8)
				TxMeg.DLC=Len%8;
		}
		while(0==FreeTxNum){
			FreeTxNum=HAL_CAN_GetTxMailboxesFreeLevel(hcan);
		}
		HAL_Delay(1);   //没有延时很有可能会发送失败
		HAL_RetVal=HAL_CAN_AddTxMessage(hcan,&TxMeg,pData+SendCNT,(uint32_t*)CAN_TX_MAILBOX0); 
		if(HAL_RetVal!=HAL_OK)
		{
			return 2;
		}
		SendCNT+=8;
	}
	
  return 0;
}

/* USER CODE END 0 */

3程序说明

3.1.can.h头文件添加对应函数 

void CAN_User_Init(CAN_HandleTypeDef* hcan );
uint8_t CANx_SendNormalData(CAN_HandleTypeDef* hcan,uint16_t ID,uint8_t *pData,uint16_t Len);   

3.2Usart1SendData_DMA(Data,8); 这个函数是dma串口发送函数,如果没有可以用printf代替,重定义一下即可(&huart2,串口2打印)

#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
	
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart2,(uint8_t *)&ch, 1, 0xFFFF);
	return ch;
}

3.3.若想接收特定的ID数据,可使用屏蔽列表模式,如四个标准帧01、02 、03 、 04

sFilterConfig.FilterMode =  CAN_FILTERMODE_IDLIST;  //设为列表模式   
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;  //过滤器位数16
sFilterConfig.FilterIdHigh = 0x0001<<5;     
sFilterConfig.FilterIdLow  = 0x0002<<5;    
sFilterConfig.FilterMaskIdHigh =0x0003<<5;
sFilterConfig.FilterMaskIdLow  =0x0004<<5; 

若对某些位进行区分,查看手册

 4.main.c

 /* USER CODE BEGIN 2 */ 里添加

	CAN_User_Init(&hcan1);
	uint8_t datasend[8]={0x11,0x12,0x13,0x14,0x15};
CANx_SendNormalData(&hcan1,0x11,datasend,8);
HAL_Delay(100);

 结果,CAN卡

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值