STM32_CAN调试记录

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本次CAN调试基于STM32F767系列,用于记录调试过程种发现的问题和难记点


一、调试环境

  • 系统:FreeRTOS
  • 接口:Can1
  • 开发板:野火STM32F767
  • 案例:野火&正点原子

二、程序代码

1.初始化

下面先贴出配置代码:

MSP初始化包括CLK和引脚配置,开启FIFO0接收中断。

/**
  * @brief  CAN_MSP初始化
  * @param  hcan
  * @retval 成功返回@HAL_OK ,故障返回@HAL_ERROR
  */
void HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
	GPIO_InitTypeDef GPIO_InitTypeStruct;
	
	CAN1_CLK_ENABLE();
	
	CAN1_TX_GPIO_CLK_ENABLE();
	
	CAN1_RX_GPIO_CLK_ENABLE();
	
	/* CAN1_TX && CAN1_RX引脚结构体 */
	GPIO_InitTypeStruct.Pin 			= CAN1_TX_PIN | CAN1_RX_PIN;
	GPIO_InitTypeStruct.Alternate = CAN_AF;
	GPIO_InitTypeStruct.Speed 		= GPIO_SPEED_FAST;
	GPIO_InitTypeStruct.Pull			= GPIO_PULLUP;
	GPIO_InitTypeStruct.Mode			= GPIO_MODE_AF_PP;
	HAL_GPIO_Init(CAN1_TX_GPIO_PORT,&GPIO_InitTypeStruct);
	
	/* 开启中断:FIFO 0 message pending interrupt */
	__HAL_CAN_ENABLE_IT(&CAN1_Handler,CAN_IT_FMP0);
	
	/* 开启NVIC  */
	HAL_NVIC_SetPriority(CAN1_RX0_IRQn,5,5);//若要在RTOS中使用系统函数,则优先级要大于5,以被系统调度
	HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
	
}

CAN1配置初始化设置波特率,CAN模式和过滤器设置。

/**
  * @brief  CAN1模式初始化 
  * @param  
	* @param  
	* @param 
	* @param 
  * @retval 成功返回@HAL_OK ,故障返回@HAL_ERROR
  */
HAL_StatusTypeDef CAN1_Config_Init(void)
{
	uint32_t id = 0x0302;
	uint32_t mask = 0x0300;
	/* 
	 *	CiA计算方式:(1+CAN_BS1)/(1+CAN_BS1+CAN_BS2) 
	 *	波特率 = APB1Clock/(1+CAN_BS1+CAN_BS2)/CAN_Prescaler
	*/
	CAN_FilterConfTypeDef CAN_FilterConfStruct; /* 过滤器结构体 */
	
	
	CAN1_Handler.Instance 	= CAN1;						/* CAN1 */
	
  CAN1_Handler.pTxMsg		  =	&Can1TxMsg;     /* 映射TX发送结构体缓冲数据*/	
	
  CAN1_Handler.pRxMsg			=	&Can1RxMsg; 		/* 映射RX发送结构体缓冲数据*/

	CAN1_Handler.Init.Mode			=	CAN_MODE_NORMAL;       /* 模式设置 */
	
  CAN1_Handler.Init.Prescaler	=	6;    /*	配置 CAN 外设的时钟分频,可设置为 1-1024	*/
	
  /* CAN_SJW表示重新同步跳跃宽度,不参与波特率的计算,其值可以编程为1到4个时间单元,表示该总线对波特率范围的容差度	*/
  CAN1_Handler.Init.SJW				=	CAN_SJW_1TQ; 	/*	配置 SJW 极限值 CAN_SJW_1TQ */
 
  CAN1_Handler.Init.BS1				=	CAN_BS1_5TQ;   /*	配置 BS1 段长度 CAN_BS1_5TQ*/      

  CAN1_Handler.Init.BS2				=	CAN_BS2_3TQ;   /*	配置 BS2 段长度 CAN_BS2_3TQ*/    
	
  CAN1_Handler.Init.TTCM			=	DISABLE;    /* 是否使能 TTCM 时间触发功能 */  

  CAN1_Handler.Init.ABOM			=	ENABLE;   	/*	是否使能 ABOM 自动离线管理功能	*/  
	
  CAN1_Handler.Init.AWUM			=	ENABLE;  	/*	是否使能 AWUM 自动唤醒功能 */   

  CAN1_Handler.Init.NART			=	DISABLE;  		/*	是否使能 NART 自动重传功能	*/    

  CAN1_Handler.Init.RFLM			=	DISABLE;    /*	是否使能 RFLM 锁定 FIFO 功能	*/

  CAN1_Handler.Init.TXFP			=	DISABLE;    /*	配置 TXFP 报文优先级的判定方法	*/


	CAN1_Handler.Init.Prescaler =6;		   BTR-BRP 波特率分频器  定义了时间单元的时间长度 54/(1+5+3)/5=1 Mbps
	if(HAL_CAN_Init(&CAN1_Handler) !=HAL_OK)
	{
		
		printf("\r\nCAN初始化失败\r\n");
		return HAL_ERROR;
	}
	else
		printf("OK\r\n");
	
		
	
	/* ----------------- 过滤器部分 -------------------------*/
	CAN_FilterConfStruct.FilterNumber 		= 0;
	
	CAN_FilterConfStruct.FilterIdHigh 		= ((((uint32_t)id<<3)|
										 CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;		/* 要筛选的ID高位 */	
	
	CAN_FilterConfStruct.FilterIdLow			= (((uint32_t)id<<3)|
									     CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;		/* 要筛选的ID低位 */	
	
	CAN_FilterConfStruct.FilterMaskIdHigh =	((((uint32_t)mask<<3)|
										 CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;			/* 筛选器高16位每位必须匹配; 0xFFFF*/
	
	CAN_FilterConfStruct.FilterMaskIdLow	= (((uint32_t)mask<<3)|
									     CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;			/* 筛选器低16位每位必须匹配; 0xFFFF*/
	
  CAN_FilterConfStruct.FilterFIFOAssignment = CAN_FILTER_FIFO0 ;	/* 筛选器被关联到FIFO0 */
	
	CAN_FilterConfStruct.FilterMode						= CAN_FILTERMODE_IDMASK;  /* 工作在掩码模式 */	
	
  CAN_FilterConfStruct.FilterScale     			= CAN_FILTERSCALE_32BIT;  /* 筛选器位宽32位  */
	
	CAN_FilterConfStruct.FilterActivation 		= ENABLE;									/* 激活滤波器0 */	
	
	CAN_FilterConfStruct.BankNumber 					= 14;                     /* 对于双CAN产品,BankNumber(14)起往后的过滤器组分配给CAN2 */
	
	if(HAL_CAN_ConfigFilter(&CAN1_Handler,&CAN_FilterConfStruct) != HAL_OK)
	{
		printf("HAL_CAN_ConfigFilter故障 \r\n");
		return HAL_ERROR;
	}
	return	HAL_OK;
}

2.配置分析

主要分析CAN配置:

2.1波特率设置

此处程序波特率设置是1MHz
主要通过三个设置:

  • SJW
  • BS1
  • BS2

公式如下:

CAN时钟:APB1 = 54MHz

CAN Baudrate = APB1Clock/(1+CAN_BS1+CAN_BS2) / CAN_Prescaler
= 54MHz / (1 + 5 + 3) /6
= 1MHz //1MHz为F767—can最大响应速度

计算原理如下:
CAN波特率计算重点在于位时序的分解

在这里插入图片描述

为了实现位同步,CAN 协议把每一个数据位的时序分解成如图所示的 SS 段、PTS 段、PBS1 段、PBS2段,这四段的长度加起来即为一个 CAN 数据位的长度。分解后最小的时间单位是 Tq,而一个完整的位由 8~25 个Tq组成。为方便表示,图 中的高低电平直接代表信号逻辑 0 或逻辑 1(不是差分信号)。

2.2过滤器设置

参考原文:https://blog.csdn.net/faihung/article/details/98849164

2.2.1过滤器的位宽
  • 1个32位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE和RTR位
  • 2个16位过滤器,包括:STDID[10:0]、IDE、RTR和EXTID[17:15]位

此处程序内用的32位过滤器

	CAN_FilterConfStruct.FilterScale     			= CAN_FILTERSCALE_32BIT;  /* 筛选器位宽32位  */

2.2.2 CAN ID的结构

在这里插入图片描述

如上图,ID分为两种,分别是标准ID和扩展ID。

以下我们以扩展ID作为分析:

扩展格式中ID0~ID17为Extension ID,而ID18~ID28为Base ID

如ID = 0x0x1800f001
用二进制表示为:0b 0001 1000 0000 0000 1111 0000 0000 0001
用括号分别区别为:0b 000[1 1000 0000 0]0[00 1111 0000 0000 0001]

基本ID[28:18](绿色部分) + IDE + 扩展ID(蓝色部分)[17:0] 组成一个扩展ID。


2.2.3位宽为32位的屏蔽模式

在这里插入图片描述

总结

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值