CAN通讯相关知识拆解&&报文格式&&过滤器&&数据交互

在嵌入式系统中使用CAN(Controller Area Network)通讯,需要掌握以下内容:

  1. CAN协议:了解CAN总线通讯的基本原理,包括帧格式、报文结构、消息ID等内容。
  2. CAN控制器:理解CAN控制器的工作原理以及如何配置和控制CAN控制器,包括波特率设置、过滤器配置等。
  3. CAN硬件:熟悉CAN硬件接口的相关信息,包括传输线路、终端电阻等。
  4. CAN通讯模式:了解CAN通讯的多种通讯模式,如标准帧模式、扩展帧模式、远程帧模式等。
  5. 数据处理:掌握CAN数据的发送和接收处理方法,包括数据打包、解析、校验等。
  6. 错误处理:了解CAN通讯中可能出现的错误类型,如位错误、帧错误等,以及相应的处理方法。
  7. 实时性:理解CAN通讯在嵌入式系统中的实时性要求,确保数据的及时性和可靠性。
  8. 调试工具:熟练掌握CAN通讯调试工具的使用,如CAN分析仪、逻辑分析仪等,以便快速排查问题。

下面就大致介绍一下CAN总线数据的组成以及帧格式的具体内容。

一、CAN数据的组成

1、头尾段

2、仲裁段

从该分析过程得出结论是:帧ID值越小,优先级越高

对于同为扩展格式数据帧、标准格式远程帧和扩展格式远程帧的情况同理。

3、控制段

4、数据段

5、CRC段

6、ACK段



二、CAN数据的格式

CAN通信帧共分为数据帧、远程帧、错误帧、过载帧和帧间隔五种类型。

1、数据帧

结构上由7个段组成,其中根据仲裁段ID码长度的不同,分为标准帧(CAN2.0A)和扩展帧(CAN2.0B)。

2、远程帧

数据帧与远程帧的区别

3、错误帧

4、过载帧

5、帧间隔

————————————————

以上内容参考大佬文章:

原文链接:图解CAN总线数据的组成和帧格式_can总线帧头-CSDN博客



三、CAN控制器

CAN(控制器局域网)控制器是一种专门用于处理CAN通信协议的集成电路,它能够管理和控制CAN网络中的数据传输。CAN控制器的主要功能包括消息的发送、接收和过滤。以下是CAN控制器工作原理的详细介绍:

CAN控制器通常包含以下几个关键模块:

  1. 发送缓冲区:存储待发送的CAN消息。
  2. 接收缓冲区:存储接收到的CAN消息。
  3. 滤波器和掩码寄存器:用于消息的过滤。
  4. 协议控制逻辑:负责CAN协议的具体实现,包括帧格式的生成和校验。
  5. 错误管理模块:处理错误检测和纠正。
  6. 时钟和定时器模块:用于同步和控制消息的发送和接收时序。

1. 消息发送

CAN控制器在发送消息时,经历以下几个步骤:

  1. 消息装载:应用程序将消息数据和标识符(ID)装载到发送缓冲区。
  2. 仲裁过程:CAN总线上多个节点可能同时发送消息。CAN控制器通过标识符的仲裁机制确定优先级,ID值越低优先级越高。
  3. 消息发送:优先级最高的消息赢得仲裁后开始发送。发送过程中,包括了帧起始、标识符、控制字段、数据字段、CRC校验和帧结束等步骤。
  4. 发送确认:发送完成后,控制器等待其他节点的确认。如果未收到确认,将重试发送。

2. 消息接收

在接收消息时,CAN控制器执行以下步骤:

  1. 总线监听:控制器持续监听CAN总线上的所有通信。
  2. 消息捕获:接收到CAN消息后,首先将其存储在接收缓冲区。
  3. 消息过滤:通过滤波器和掩码寄存器,控制器判断消息是否与节点相关。只有通过过滤器的消息才会继续处理。
  4. 错误检测:控制器检查接收到的消息是否有错误,包括位错误、填充错误、CRC错误等。
  5. 消息处理:没有错误且通过过滤器的消息被传递给应用层进行处理。

3.错误处理

CAN控制器内置多种错误处理机制,以确保通信的可靠性:

  1. 错误检测:包括位错误、填充错误、CRC错误、确认错误和格式错误。
  2. 错误计数:控制器维护发送错误计数器(TEC)和接收错误计数器(REC),用于记录错误发生的次数。
  3. 错误状态管理:根据错误计数器的值,控制器可以进入不同的错误状态,如错误主动状态、错误被动状态和总线关闭状态。

4.时钟同步

CAN通信需要严格的时间控制,CAN控制器使用内部时钟和定时器模块来保持同步。通过同步段、传播段、相位缓冲段1和相位缓冲段2来控制比特时间,确保各节点能够在精确的时间点发送和接收数据。



四、通信模式

CAN总线控制器有4种通信模式:

◼ 静默(Silent)通信模式;

◼ 回环(Loopback)通信模式;

◼ 回环静默(Loopback and Silent)通信模式;

◼ 正常(Normal)通信模式。

1.静默(Silent)通信模式 【可以接收但不发送

在静默通信模式下,可以从CAN总线接收数据,但不向总线发送任何数据。将CAN_BT寄存器中的SCMOD位置1,使CAN总线控制器进入静默通信模式,将其清0可以退出静默通信模式。 静默通信模式可以用来监控CAN网络上的数据传输。

2.回环(Loopback)通信模式 【自发自收用于自测】

在回环通信模式下,由CAN总线控制器发送的数据可以被自己接收并存入接收FIFO,同时这些发送数据也送至CAN网络。将CAN_BT寄存器中的LCMOD位置1,使CAN总线控制器进入回环通信模式,将其清0可以退出回环通信模式。 回环通信模式通常用来进行CAN通信自测。

3.回环静默(Loopback and Silent)通信模式

在回环静默通信模式下,CAN的RX和TX 引脚与CAN网络断开。CAN总线控制器既不从CAN网络接收数据,也不向CAN网络发送数据,其发送的数据仅可以被自己接收。将CAN_BT寄存器中的LCMOD位和SCMOD位置1,使CAN总线控制器进入回环静默通信模式,将它们清0可以退出回环静默通信模式。 609 GD32F30x 用户手册 回环静默通信模式通常用来进行CAN通信自测。对外TX引脚保持隐性状态(逻辑1),RX引脚保持高阻态。

4.正常(Normal)通信模式

CAN 总线控制器通常工作在正常通信模式下,可以从CAN总线接收数据,也可以向CAN总线发送数据。这时需要将CAN_BT寄存器的LCMOD位和SCMOD位清0。

五、数据发送

发送寄存器 数据发送通过3个发送邮箱进行,可以通过寄存器CAN_TMIx,CAN_TMPx,CAN_TMDATA0x和CAN_TMDATA1x 对发送邮箱进行配置

1.数据发送步骤如下:

第1步:选择一个空闲发送邮箱

第2步:根据应用程序要求,配置4个发送寄存器;

第3步:将CAN_TMIx寄存器的TEN置1;

第4步:检测发送状态和错误信息。典型情况是检测到MTF和MTFNERR置1,说明数据被成功发送。

2.发送邮箱状态转换

当发送邮箱处于empty 状态时,应用程序才可以对邮箱进行配置。当邮箱被配置完成后,可以将CAN_TMIx寄存器的TEN位置 1,从而向CAN总线控制器提交发送请求,这时发送邮箱处于pending状态。当超过1个邮箱处于pending状态时,需要对多个邮箱进行调度,这时发送邮箱处于scheduled 状态。当调度完成后,发送邮箱中的数据开始向 CAN总线上发送,这时发送邮箱处于transmit 状态。当数据发送完成,邮箱变为空闲,可以再次交给应用程序使用。

3.发送状态检测

CAN_TSTAT寄存器中的MTF,MTFNERR,MAL和MTE位用来说明发送状态和错误信息。

◼ MTF:发送完成标志位。当数据发送完成时,MTF置1。

◼ MTFNERR:无错误发送完成标志位。当数据发送完成且没有错误时,MTFNERR置1。

◼ MAL:仲裁失败标志位。当发送数据过程中出现仲裁失败时,MAL置1。

◼ MTE:发送错误标志位。当发送过程中检测到总线错误时,MTE置1。

4.发送优先级

当有2个及其以上发送邮箱等待发送时,寄存器CAN_CTL的TFO位的值可以决定发送顺序。

当TFO为1,所有等待发送的邮箱按照先来先发送(FIFO)的顺序进行。

当TFO为0,具有最小标识符(Identifier)的邮箱最先发送。如果所有的标识符(Identifier)相等,具有最小邮箱编号的邮箱最先发送。

六、数据发送

应用程序通过2个深度为3的FIFO接收来自CAN网络的数据

1.数据接收步骤

第1步:查看FIFO中帧的数量。

第2步:通过CAN_RFIFOMIx , CAN_RFIFOMPx , CAN_RFIFOMDATA0x 和CAN_RFIFOMDATA1x读取数据。

第3步:将寄存器CAN_RFIFOx的RFD置1释放邮箱,并且等待其由硬件自动清0。

2.接收FIFO

每个接收FIFO包含3个接收邮箱,用来接收存储数据帧。这些邮箱按照先进先出方式进行组织,最早从CAN网络接收的数据,最早被应用程序处理。 寄存器CAN_RFIFOx包含FIFO状态信息和帧的数量。当FIFO中包含数据时,可以通过寄存器CAN_RFIFOMIx,CAN_RFIFOMPx,CAN_RFIFOMDATA0x和CAN_RFIFOMDATA1x读取数据,之后将寄存器CAN_RFIFOx的RFD置1释放邮箱。

3.接收FIFO状态信息

接收FIFO状态信息包含在寄存器CAN_RFIFOx中。

RFL:FIFO中包含的帧数量。FIFO为空时,RFL为0;FIFO为满时,RFL为3。

RFF:FIFO满状态标志位。这时RFL为3。

RFO:FIFO溢出标志位。当FIFO已经包含了3个数据帧时,新的数据帧到来使FIFO发生溢出。

如果CAN_CTL寄存器的RFOD位被置1,新的数据帧将丢弃。如果该位被清0,新的数据帧将覆盖接收FIFO中最后一帧数据。

七、滤功能

一个待接收的数据帧会根据其标识符(Identifier)进行过滤:硬件会将通过过滤的帧送至接收

硬件过滤的做法节省了CPU开销,否则就必须由软件过滤从而占用一定的CPU开销

1.过滤器关联的FIFO

28个过滤单元均可以关联接收FIFO0或接收FIFO1。一旦一个过滤单元关联到接收FIFO,只有通过这个过滤单元的帧才会被传送到接收FIFO中存储。

2.优先级

过滤器优先级规则如下:

1、32-bits位宽模式高于16-bits位宽模式;

2、列表模式高于掩码模式;

3、较小的过滤序号(Filter Number)具有较高的优先级。

3.过滤器模式

(1)掩码模式

对于一个待过滤的数据帧的标识符(Identifier),掩码模式用来指定哪些位必须与预设的标识符相同,哪些位无需判断。

设得宽,则可以通过的多(所有位为0,则不过任何过滤操作,则谁都可以通过),设得窄,则通过的少(所有位设为1,则只有一个能通过)。

(2)列表模式

对于一个待过滤的数据帧的标识符(Identifier),列表模式用来表示与预设的标识符列表中能够匹配则通过,否则丢弃。

4.过滤器的位宽

在非GD32F30x CL系列产品中,过滤器由14个单元( Bank)组成,它们是bank0到bank13。在GD32F30x CL系列产品中,过滤器包含28个单元,它们是bank0到bank27。

每一个过滤器单元有2个寄存器CAN_FxDATA0和CAN_ FxDATA1,它们可以配置为2种位宽:32-bit位宽和16-bit位宽。 【配置的位宽】

32位宽的掩码模式, 配置过滤2个不同的ID号

32位宽的列表模式, 配置过滤4个不同的ID号

16位宽的列表模式, 配置过滤2个不同的ID号

16位宽的掩码模式, 配置过滤1个不同的ID号

5.过滤器的代码实现

注意:若配置了多组标识符掩码,则只要接收到的标识符符合其中任意一组掩码的都会通过滤波器,所以千万不要有其中一组是通配的(即掩码为0x0000),否则你设置的其它掩码组都会无效

以下是实现每种CAN滤波器配置情况的实际代码示例。假设我们使用的CAN控制器支持相应的配置方式,并使用C语言或C++编写代码。

1. 32位宽的掩码模式,配置过滤2个不同的ID号

解释:

  1. 左移3位:空出低3位用于控制位(SRR、IDE、RTR等)。
  2. 右移16位:提取高16位部分用于高位寄存器。
  3. 与0xffff按位与:确保只取低16位。
  4. 或操作设置扩展ID标志位:标记该ID为扩展ID

假设使用的是某个CAN控制器的库函数CAN_SetFilter来配置滤波器:

// 设置32位宽掩码模式的过滤器1
CAN_FilterTypeDef sFilterConfig1;
sFilterConfig1.FilterIdHigh = (0x12345678 >> 13) & 0xFFFF;
sFilterConfig1.FilterIdLow = (0x12345678 << 3) & 0xFFFF;
sFilterConfig1.FilterMaskIdHigh = (0x1FFFFFFE >> 13) & 0xFFFF;
sFilterConfig1.FilterMaskIdLow = (0x1FFFFFFE << 3) & 0xFFFF;
sFilterConfig1.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig1.FilterBank = 0; // 滤波器编号
sFilterConfig1.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig1.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig1.FilterActivation = ENABLE;
CAN_SetFilter(&sFilterConfig1);

// 设置32位宽掩码模式的过滤器2
CAN_FilterTypeDef sFilterConfig2;
sFilterConfig2.FilterIdHigh = (0x12345679 >> 13) & 0xFFFF;
sFilterConfig2.FilterIdLow = (0x12345679 << 3) & 0xFFFF;
sFilterConfig2.FilterMaskIdHigh = (0x1FFFFFFE >> 13) & 0xFFFF;
sFilterConfig2.FilterMaskIdLow = (0x1FFFFFFE << 3) & 0xFFFF;
sFilterConfig2.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig2.FilterBank = 1; // 滤波器编号
sFilterConfig2.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig2.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig2.FilterActivation = ENABLE;
CAN_SetFilter(&sFilterConfig2);

2. 32位宽的列表模式,配置过滤4个不同的ID号

// 设置32位宽列表模式的过滤器
CAN_FilterTypeDef sFilterConfig;

// 过滤器1
sFilterConfig.FilterBank = 0; // 滤波器编号
sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterIdHigh = (0x12345678 >> 13) & 0xFFFF;
sFilterConfig.FilterIdLow = (0x12345678 << 3) & 0xFFFF;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterActivation = ENABLE;
CAN_SetFilter(&sFilterConfig);

// 过滤器2
sFilterConfig.FilterBank = 1; // 滤波器编号
sFilterConfig.FilterIdHigh = (0x23456789 >> 13) & 0xFFFF;
sFilterConfig.FilterIdLow = (0x23456789 << 3) & 0xFFFF;
CAN_SetFilter(&sFilterConfig);

// 过滤器3
sFilterConfig.FilterBank = 2; // 滤波器编号
sFilterConfig.FilterIdHigh = (0x34567890 >> 13) & 0xFFFF;
sFilterConfig.FilterIdLow = (0x34567890 << 3) & 0xFFFF;
CAN_SetFilter(&sFilterConfig);

// 过滤器4
sFilterConfig.FilterBank = 3; // 滤波器编号
sFilterConfig.FilterIdHigh = (0x45678901 >> 13) & 0xFFFF;
sFilterConfig.FilterIdLow = (0x45678901 << 3) & 0xFFFF;
CAN_SetFilter(&sFilterConfig);

3. 16位宽的列表模式,配置过滤2个不同的ID号

// 设置16位宽列表模式的过滤器
CAN_FilterTypeDef sFilterConfig;

// 过滤器1
sFilterConfig.FilterBank = 0; // 滤波器编号
sFilterConfig.FilterMode = CAN_FILTERMODE_IDLIST;
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterIdHigh = 0x1234 & 0xFFFF;
sFilterConfig.FilterIdLow = 0x5678 & 0xFFFF;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterActivation = ENABLE;
CAN_SetFilter(&sFilterConfig);

// 过滤器2
sFilterConfig.FilterBank = 1; // 滤波器编号
sFilterConfig.FilterIdHigh = 0x5678 & 0xFFFF;
sFilterConfig.FilterIdLow = 0x0000;
CAN_SetFilter(&sFilterConfig);

4. 16位宽的掩码模式,配置过滤1个不同的ID号

// 设置16位宽掩码模式的过滤器
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0; // 滤波器编号
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_16BIT;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;

// 过滤器ID
sFilterConfig.FilterIdHigh = 0x1234 & 0xFFFF;
// 掩码
sFilterConfig.FilterMaskIdHigh = 0xFFFF; // 完全匹配

sFilterConfig.FilterActivation = ENABLE;
CAN_SetFilter(&sFilterConfig);

这些代码示例展示了如何配置不同位宽和模式的CAN滤波器,以实现对不同数量ID号的过滤。具体实现可能会因不同的CAN控制器和库函数有所不同,请参考具体硬件的文档和API。

  • 15
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值