CAN学习历程

这里写自定义目录标题

  • CAN的配置
    • 配置波特率
    • 中断配置
    • 过滤器的配置
  • 用示波器查看波形
  • 关于ID的设置

CAN的配置

我使用的是stm32cubemx进行配置

配置波特率

CAN学习历程_第1张图片
第一项Bit Timing Parameters是用来配置波特率的
Prescaler 波特率预分频器
Time Quanta in Bit Segment 1和Time Quanta in Bit Segment 2 是位段1和位段2的配置
ReSynchronization Jump Width 再同步跳转宽度,一般设置为1
采样点设置为CIA推荐的值
75% bps>800K
80% bps>500k
87.5 bps<=500K
采样点计算公式(1+tbs1)/(1+tbs1+tbs2)
(1+tbs1+tbs2)在8~25之间 //这个值是在网络上查到某个网友说的,可能是经验值

中断配置

CAN学习历程_第2张图片
CAN 通信中的发送中断指的是发送完成中断,即发送邮箱中的数据发送完毕后产生的发送邮箱变为空的中断,一般如果发送的数据大于8个字节,需要分为多个帧发送的话,就可以用中断发送。我这次直接用HAL_CAN_AddTxMessage函数发送的,没有用到发送中断。
使用多个帧发送一组数据的话,一定要定好协议,比如该组数据一共几帧,当前是第几帧等等信息都要包含在数据中,最好是在数据段包含这些信息。有些网友也会利用仲裁场的ID来发送大于8个字节的数据,但是这不是推荐的。
CAN 通信中的接收中断,如果使用的是FIFO0,那么中断入口函数为CAN1_RX0_IRQHandler;如果使用的是FIFO1,那么中断入口函数为CAN1_RX1_IRQHandler。
接收回调函数如下

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
	unsigned char CAN_ReciveBuf[8];
	HAL_StatusTypeDef HAL_back;
	if(hcan==(&hcan1))
	{
		HAL_back = HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &RxHeader, CAN_ReciveBuf);
		if(HAL_back==HAL_OK)
		{
			
		}
	}
}

过滤器的配置

	sFilterConfig.FilterBank = 0;			//用来设置初始化的过滤器组,选择过滤器组0
	sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;//用来选择过滤器组模式,选择标识符屏蔽位模式
	sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;	//用来设置过滤器的位宽,是两个16位还是1个32位
	//用来设置过滤器的32位ID
	sFilterConfig.FilterIdHigh = 0x0000;
	sFilterConfig.FilterIdLow = 0x0000;
	//用来设置过滤器的32位mask id
	sFilterConfig.FilterMaskIdHigh = 0x0000;
	sFilterConfig.FilterMaskIdLow = 0x0000;
	sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;  //用来设置FIFO和过滤器的关联,关联FIFO0到过滤器0
	sFilterConfig.FilterActivation = ENABLE;			//用来激活该过滤器,激活后才会进入接收中断
	sFilterConfig.SlaveStartFilterBank = 14;			//用来设置CAN起始存储区

关于这方面的信息,有一个网友写的特别好
STM32 CAN 发送和接收过滤原理

在设置ID时折腾了一会儿,因为我发送的TxHeader.StdId = 0x12;然后在接收的时候,直接设置

//用来设置过滤器的32位ID
	sFilterConfig.FilterIdHigh = 0x1200;
	sFilterConfig.FilterIdLow = 0x0000;
	//用来设置过滤器的32位mask id
	sFilterConfig.FilterMaskIdHigh = 0xFF00;
	sFilterConfig.FilterMaskIdLow = 0x0000;

我把0x12和0xFF倒腾换了好几个位置都不能接收,后来又仔细看上面的那篇文章才明白,因为我用的是标准格式,仲裁段的ID应该是11位的,这11位是CAN_FxRx寄存器的高11位,所以最后的设置应该是

	//用来设置过滤器的32位ID
	sFilterConfig.FilterIdHigh = 0x0240;
	sFilterConfig.FilterIdLow = 0x0000;
	//用来设置过滤器的32位mask id
	sFilterConfig.FilterMaskIdHigh = 0xFFE0;
	sFilterConfig.FilterMaskIdLow = 0x0000;

另外发现,数据帧的ACK_Slot位,只要有节点接收到数据就会有一个显性位,即便节点的ID对应不上也会有显性位。这主要是用来确定报文至少被一个节点正确接收。
而且如果设置为自动重发模式,只要ACK_Slot为显性位,那么就认为被接收,不会自动重复发送了。

关于错误帧的发送和接收,我认为对于stm32来说,错误帧的发送和接收都是由硬件自己处理的,这一点不用我们关心。我们可以开启错误中断,只要发生了通信错误,就会进入错误中断,通过读取CAN_ESR寄存器的值,判断错误类型,作进一步的处理。
使能错误中断的话,需要使能CAN_IER寄存器的ERRIE和LECIE两个位,并且进入错误中断后,要对CAN_MSR寄存器的ERRI位清零,否则会一直进入该中断,造成程序的运行问题。

用示波器查看波形

1、将示波器的两个接口(接地和探头)分别接在can总线的两条线(CAN_H和CAN_L)上,这里需要注意如果CAN线上需要接一个120欧姆的负载电阻,否则波形是不规整方波,接上负载之后才是规整的方波。(我看到的波形也不是很标准的)
2、根据CAN协议的描述,编码方式是位流编码,帧起始、仲裁场、控制场、数据场以及CRC序列,都通过位填充的方法编码。无论何时,发送器只要监测到位流里有5个连续相同值的位,便自动在位流里插入一位补位。
CAN学习历程_第3张图片
如上图所示,5个联系的显性位后,填充了一个隐性位,实际读取数据的时候填充的这一位是要去掉的。
所以这一段的数据实际是:01000000

关于ID的设置

1、我们知道,ID主要用作CAN总线的仲裁使用,ID值越低,报文优先级越高。
2、ID域可以是11位和29位,其值和含义可以由用户自定义,定义时可以参考CANOpen协议。
CAN学习历程_第4张图片

在这里插入图片描述
CAN学习历程_第5张图片
这样的话,ID的含义就很清晰

3、ID的另一个作用是配合接收方滤波使用,就是说一般接收的滤波器可以设定接收ID的范围等,用于过滤掉不需要接收的信息,减轻CPU的处理负担。

你可能感兴趣的:(学习历程)