stm32cubemx hal学习记录:CAN

一、实验内容

RM C板,can1给can2发送数据

二、CAN总线简介

1、控制器局域网络:Controller Area Network

2、异步半双工通信

3、总线制

CAN由一对差分对(两条线)CANH和CANL组成

CANH电压比CANL高视为逻辑0(显性电平),否则为逻辑1(隐性电平)

多个设备可以连接到同一条CAN上

总线上的设备通过ID号区分

ID号长度可以为11位标准长度或者29位拓展长度

4、常用标准

①CAN2.0b标准

最大速率1Mbps,一组数据称为一帧,分为数据帧和远程帧,数据帧最多传输8个字节的数据,每一帧都有CRC校验。

②CAN FD标准,很多设备不支持

最大速率可达8Mbps,数据帧最多可传输64字节数据

5、CAN物理层

单片机一般使用类似串口的CAN RX和CAN TX接口驱动CAN

CAN RX/CAN TX需要经过CAN收发器才能被转换成对应的差分电平

一般CAN差分信号的电压为0-5V,也可以是0-3.3V,但不建议使用3.3v

6、CAN总线结构

CAN有两个120Ω的终端电阻,位于CAN布线的两端,每个设备挂载在总线上幸成数个支路

stm32cubemx hal学习记录:CAN_第1张图片

 7、CAN时序

太复杂懒得学

8、CAN的帧

ID:ID号,标准11位,扩展29位

RTR:区别远程帧与数据帧,一般为数据帧,设置为0

IDE:区别ID号长度,0的话为11位,1的话为29位

DLC:数据长度,发送多少字节的数据,为0-8或者增强帧的0-64位

CRC:校验部分,CRC16,不用管,stm32自动生成

连续的五个以上相同位中间会插入一个相反位,除结尾外

9、CAN的仲裁

①由于CAN定义2条信号线的电压差代表逻辑0或者逻辑1,CAN的两条信号线实质上等效为串口的一条线

②当总线上连续3位的时间为1且没有正在传输的帧时,视为空闲状态,此时设备才能进行发送

③如果有2个或以上设备同时启动了发送则会进入仲裁

发送0更多的设备会赢得仲裁并继续发送

由于CAN时序的规定,仲裁是很难进入的,只有两个设备在同一Tq内启动发送才会进入仲裁

10、STM32的CAN外设

①FDCAN:仅限H系列和G系列(FDCAN和CAN2.0b)

②bxCAN:标准CAN外设,仅支持CAN2.0b

一般有1-3个CAN,CAN1和CAN3是主CAN,CAN2是从CAN

CAN2在CAN1打开之后才能打开,推荐两个同时打开

11、STM32的CAN时序

f=fapb/(psc*(bs1+bs2+1))

常用参数:用于STM32F407,主频为168MHz时,APB1为42MHz,设置BS1=9,BS2=4,BS3=3,此时得到1MHz的CAN频率

三、配置

1、板子接线H连L,L连H

2、配置cubemx基础配置

3、点开CAN1和CAN2

stm32cubemx hal学习记录:CAN_第2张图片

 4、配置CAN的参数

stm32cubemx hal学习记录:CAN_第3张图片

 按照123的顺序配置,否则会报错

5、打开CAN的全部中断

stm32cubemx hal学习记录:CAN_第4张图片

 6、设置PA8为输入模式,使用此按键来触发发送

7、生成代码

四、未添加过滤器代码

初始化

void CAN_ConfigFilter(void)
{
	CAN_FilterTypeDef sFilterConfig;
	sFilterConfig.FilterActivation=CAN_FILTER_ENABLE;
	sFilterConfig.FilterBank=0;  //过滤器编号
	sFilterConfig.FilterFIFOAssignment=CAN_FilterFIFO0; //过滤器给到rx0还是rx1
	sFilterConfig.FilterMode=CAN_FILTERMODE_IDMASK;//模式
	sFilterConfig.FilterScale=CAN_FILTERSCALE_32BIT;//16位还是32位,此时配置32位
	sFilterConfig.FilterIdHigh=0x00;
	sFilterConfig.FilterIdLow=0x00;
	sFilterConfig.FilterMaskIdHigh=0x00;
	sFilterConfig.FilterMaskIdLow=0x00;
	sFilterConfig.SlaveStartFilterBank=14;//定值
	
	if(HAL_CAN_ConfigFilter(&hcan1,&sFilterConfig)!=HAL_OK)
	{
		Error_Handler();
	}
	
	sFilterConfig.FilterBank=14;  //CAN2过滤器编号

	if(HAL_CAN_ConfigFilter(&hcan2,&sFilterConfig)!=HAL_OK)
	{
		Error_Handler();
	}	
	
	if(HAL_CAN_Start(&hcan1)!=HAL_OK)
	{
		Error_Handler();
	}
	
	if(HAL_CAN_Start(&hcan2)!=HAL_OK)
	{
		Error_Handler();
	}
	
	//打开中断
	if(HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING)!=HAL_OK)
	{
		Error_Handler();
	}
	if(HAL_CAN_ActivateNotification(&hcan2,CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING)!=HAL_OK)
	{
		Error_Handler();
	}
}

参数定义

uint8_t txDataBuffer[8],rxDataBuffer0[8],rxDataBuffer1[8];
CAN_TxHeaderTypeDef txHeader;;
CAN_RxHeaderTypeDef rxHeader0,rxHeader1;

uint16_t txID=0x20;	//发送的ID
uint32_t txMailbox;	//发送邮箱的地址

main中按键触发can1发送

  while (1)
  {
    /* USER CODE END WHILE */
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8)==0)
		{
			HAL_Delay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8)==0)
			{
				
				txHeader.StdId=txID;
				txHeader.IDE=CAN_ID_STD;
				txHeader.RTR=CAN_RTR_DATA;  //数据帧
				txHeader.DLC=8;							//8位
				
				*((uint32_t*)(txDataBuffer))=HAL_GetTick();  //发送当前运行的时间
				
				if(HAL_CAN_GetTxMailboxesFreeLevel(&hcan1)!=0)  //检验是否是空闲状态
				{
					HAL_CAN_AddTxMessage(&hcan1,&txHeader,txDataBuffer,&txMailbox);
				}
				
			}
		}
    /* USER CODE BEGIN 3 */
  }

中断can2接收

//接收到的数据将会在rxHeader结构体和rxDataBuffer中
void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan == &hcan2)
	{
		HAL_CAN_GetRxMessage(&hcan2,CAN_RX_FIFO0,&rxHeader0,rxDataBuffer0);
	}
}

void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan)
{
	if(hcan == &hcan2)
	{
		HAL_CAN_GetRxMessage(&hcan2,CAN_RX_FIFO1,&rxHeader1,rxDataBuffer1);
	}	
}

五、过滤器

1、STM32的bxCAN接收时必须使用过滤器接收

2、根据CAN外设数量的不同有以下情况:

①只有CAN1:CAN1有14个过滤器

②有CAN1和CAN2:CAN1和CAN2共享28个过滤器

③有CAN1-3:CAN1和CAN2共享28个过滤器,CAN3则有独立的14个过滤器

3、过滤器可以过滤CAN总线上帧的ID号,可以不处理不想接受的ID号,直接收想要的ID号

4、掩码

①两个单元分别组成匹配ID和掩码

②被过滤的ID号和匹配ID号会和掩码进行按位与运算后再进行匹配,也就是只有对应的掩码为1的位才会被匹配

③例如:

匹配ID为0x200,掩码为0x000,则所有ID号都能通过

匹配ID为0x200,掩码为0x700,则ID为0x200~0x2FF均可通过

匹配ID为0x200,掩码为0x7FF,则只有0x200能通过

void CAN_ConfigFilter(void)
{
	CAN_FilterTypeDef sFilterConfig;
	sFilterConfig.FilterActivation=CAN_FILTER_ENABLE;
	sFilterConfig.FilterBank=0;  												//过滤器编号,CAN1为0-13
	sFilterConfig.FilterFIFOAssignment=CAN_FilterFIFO0; //过滤器给到rx0还是rx1
	sFilterConfig.FilterMode=CAN_FILTERMODE_IDMASK;			//模式
	sFilterConfig.FilterScale=CAN_FILTERSCALE_32BIT;		//16位还是32位,此时配置32位
	sFilterConfig.FilterIdHigh=0x00;
	sFilterConfig.FilterIdLow=0x00;
	sFilterConfig.FilterMaskIdHigh=0x00;
	sFilterConfig.FilterMaskIdLow=0x00;
	sFilterConfig.SlaveStartFilterBank=14;							//定值
	
	if(HAL_CAN_ConfigFilter(&hcan1,&sFilterConfig)!=HAL_OK)
	{
		Error_Handler();
	}
	
	//CAN2设置过滤器,FIFO0
	sFilterConfig.FilterActivation=CAN_FILTER_ENABLE;
	sFilterConfig.FilterBank=14;  											//过滤器编号,CAN2为14-27
	sFilterConfig.FilterFIFOAssignment=CAN_FilterFIFO0; //过滤器给到rx0还是rx1
	sFilterConfig.FilterMode=CAN_FILTERMODE_IDLIST;			//模式
	sFilterConfig.FilterScale=CAN_FILTERSCALE_16BIT;		//16位还是32位,此时配置16位
	//过滤0x200 201 202 203这四个ID号,只有当这个id号完全等于完全匹配的时候,才会被过滤掉
	//如果想要过滤三个,则写一个不存在的id号,例如0x800
	sFilterConfig.FilterIdHigh=0x200<<5;   
	sFilterConfig.FilterIdLow=0x201<<5;
	sFilterConfig.FilterMaskIdHigh=0x202<<5;
	sFilterConfig.FilterMaskIdLow=0x203<<5;
	sFilterConfig.SlaveStartFilterBank=14;							//定值

	if(HAL_CAN_ConfigFilter(&hcan2,&sFilterConfig)!=HAL_OK)
	{
		Error_Handler();
	}	
	
	//CAN2设置过滤器,FIFO1
	sFilterConfig.FilterActivation=CAN_FILTER_ENABLE;
	sFilterConfig.FilterBank=15;  											//过滤器编号,CAN2为14-27
	sFilterConfig.FilterFIFOAssignment=CAN_FilterFIFO1; //过滤器给到rx0还是rx1
	sFilterConfig.FilterMode=CAN_FILTERMODE_IDMASK;			//模式
	sFilterConfig.FilterScale=CAN_FILTERSCALE_16BIT;		//16位还是32位,此时配置16位
	//过滤0x200 201 202 203这四个ID号,只有当这个id号完全等于完全匹配的时候,才会被过滤掉
	//如果想要过滤三个,则写一个不存在的id号,例如0x800
	sFilterConfig.FilterIdHigh=0x200<<5;   
	sFilterConfig.FilterMaskIdHigh=0x700<<5; //这句和上一句说明过滤的为0x200-0x2FF
	sFilterConfig.FilterIdLow=0x201<<5;
	sFilterConfig.FilterMaskIdLow=0x203<<5;
	sFilterConfig.SlaveStartFilterBank=14;							//定值

	if(HAL_CAN_ConfigFilter(&hcan2,&sFilterConfig)!=HAL_OK)
	{
		Error_Handler();
	}		
	
	if(HAL_CAN_Start(&hcan1)!=HAL_OK)
	{
		Error_Handler();
	}
	
	if(HAL_CAN_Start(&hcan2)!=HAL_OK)
	{
		Error_Handler();
	}
	
	//打开中断
	if(HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING)!=HAL_OK)
	{
		Error_Handler();
	}
	if(HAL_CAN_ActivateNotification(&hcan2,CAN_IT_RX_FIFO0_MSG_PENDING | CAN_IT_RX_FIFO1_MSG_PENDING)!=HAL_OK)
	{
		Error_Handler();
	}
}

整理自:CH4.2 CAN 第2讲 过滤器【南工骁鹰嵌入式软件培训】_哔哩哔哩_bilibili

你可能感兴趣的:(stm32,单片机,学习)