CAN FD简介

本文介绍了CANFD协议,针对传统CAN总线带宽不足的问题,详细阐述了CANFD的技术特点,包括可变速率传输、增强的数据场长度、新的CRC算法及DLC编码方式,并提供了SylixOS中CANFD的具体实现方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CAN FD简介

1 CAN FD简介

  在汽车领域,随着人们对数据传输带宽要求的增加,传统的CAN总线由于带宽的限制难以满足这种增加的需求。此外为了缩小CAN网络(max. 1MBit/s)与FlexRay(max.10MBit/s)网络的带宽差距,BOSCH公司推出了CAN FD。
CAN FD(CAN with Flexible Data rate)继承了CAN总线的主要特性。CAN总线采用双线串行通讯协议,基于非破坏性仲裁技术,分布式实时控制,可靠的错误处理和检测机制使CAN总线有很高的安全性,但CAN总线带宽和数据场长度却受到制约。CAN FD总线弥补了CAN总线带宽和数据场长度的制约,CAN FD总线与CAN总线的区别主要在以下两个方面:
  1. 可变速率:CAN FD采用了两种位速率。从控制场中的BRS位到ACK场之前(含CRC分界符)为可变速率,其余部分为原CAN总线用的速率。两种速率各有一套位时间定义寄存器,它们除了采用不同的位时间单位TQ外,位时间各段的分配比例也可不同;
  2. 新的数据场长度:CAN FD对数据场的长度作了很大的扩充,DLC最大支持64个字节,在DLC小于等于8时与原CAN总线是一样的,大于8时有一个非线性的增长,所以最大的数据场长度可达64字节。

1.1 CAN FD数据帧帧格式

  CAN FD数据帧在控制场新添加EDL位、BRS位、ESI位,采用了新的DLC编码方式、新的CRC算法(CRC场扩展到21位)。CAN FD数据帧格式如下图所示。
CAN FD数据帧格式

1.2 新添加位介绍

  • EDL位(Extended Data Length):原CAN数据帧中的保留位R。隐性表示CAN FD报文(采用新的DLC编码和CRC算法),显性表示CAN报文;
  • BRS位(Bit Rate Switch):该位隐性表示转换可变速率,显性表示不转换速率;
  • ESI位(Error State Indicator):该位隐性表示发送节点处于被动错误状态(Error Passive),显性表示发送节点处于主动错误状态(Error Active);
      EDL位可以表示CAN报文还是CAN FD报文;BRS表示位速率转换,该位为隐性位时,从BRS位到CRC界定符使用转换速率传输,其他位场使用标准位速率,该位为显性时,以正常的CAN FD总线速率传输;通过添加ESI位,可以很方便的知道当前发送节点所处的状态。

    1.3 新的CRC算法

      CAN总线由于位填充规则对CRC的干扰,造成错帧漏检率未达到设计意图。CAN FD对CRC算法做了改变,即CRC以含填充位的位流进行计算。在校验和部分为避免再有连续位超过6个,就确定在第一位以及以后每4位添加一个填充位加以分割,这个填充位的值是上一位的反码,作为格式检查,如果填充位不是上一位的反码,就作出错处理。CAN FD的CRC场扩展到了21位。由于数据场长度有很大变化区间,所以要根据DLC大小应用不同的CRC生成多项式,CRC_17,适合于帧长小于210位的帧,CRC_21,适适合于帧长小于1023位的帧。

    1.4 新的DLC编码

      CAN FD数据帧采用了新的新的DLC编码方式,在数据场长度在0-8个字节时,采用线性规则,数据场长度为12-64个字节时,使用非线性编码。如下图所示。
    DLC编码

    2 SylixOS中CAN FD的实现

    2.1 CAN驱动实现

      SylixOS的CAN驱动框架在原有CAN的基础上增加了对CAN FD的支持。对应于新的CAN帧格式,SylixOS增加了新的帧结构定义,如下所示。

    typedef struct {
    UINT32              CAN_uiId;
    UINT32              CAN_uiChannel;
    BOOL                CAN_bExtId;
    BOOL                CAN_bRtr; 
    UINT32              CAN_uiCanFdFlags;
    #define CAN_FD_FLAG_EDL     1
    #define CAN_FD_FLAG_BRS     2
    #define CAN_FD_FLAG_ESI     4
    UCHAR               CAN_ucLen; 
    UCHAR               CAN_ucData[CAN_FD_MAX_DATA];
    } CAN_FD_FRAME;
    typedef CAN_FD_FRAME   *PCAN_FD_FRAME;

      为了同时兼容CAN与CAN FD,系统在创建CAN设备申请帧缓冲区时,以帧结构较大的CAN FD帧报文为单位进行申请。同时通过ioctl新增加的CAN_DEV_CAN_FD选项查看CAN设备驱动以及控制器是否支持CAN FD。此次查询决定了后续驱动对帧缓冲区进行读写时的帧报文格式,即标准CAN或CAN FD。因此CAN FD驱动的ioctl接口除了要实现标准CAN驱动的选项外,还要额外实现CAN_DEV_CAN_FD选项,如下所示。

    case CAN_DEV_CAN_FD:
        *(UINT *)lArg = CAN_STD_CAN_FD;
        break;

    2.2 应用层实现

      应用层需要收发CAN FD报文时,必须通过ioctl的CAN_FIO_CAN_FD选项对CAN FD进行设置,如下所示。

    CAN_FD_FRAME   canfdframe[10];
    ssize_t        size;
    ssize_t        frame_num;
    long            status;
     ...
    
    canfile = open("/dev/can0", O_RDWR);
    
    ioctl(canfile, CAN_DEV_SET_MODE, 1);
    ioctl(canfile, CAN_DEV_SET_BAUD, LW_OSIOD_LARG(*));
    /*
    *  must call this before read() write()
    */
    ioctl(canfile, CAN_FIO_CAN_FD, CAN_STD_CAN_FD);
    ioctl(canfile, CAN_DEV_STARTUP);
    
    size       = read(canfile, canfdframe, 10 * sizeof(CAN_FD_FRAME));
    frame_num = size / sizeof(CAN_FD_FRAME);
    
    if (frame_num <= 0) {
        ioctl(canfile, CAN_DEV_GET_BUS_STATE, &status);
        ...
        ioctl(canfile, CAN_DEV_REST_CONTROLLER);
    }
    
    ...
    size       = write(canfile, canfdframe, 10 * sizeof(CAN_FD_FRAME));
    frame_num = size / sizeof(CAN_FD_FRAME);

    3 参考资料

      《CAN FD协议介绍》:http://www.cechina.cn/company/50633_156096/messagedetail.aspx

转载于:https://blog.51cto.com/12557713/2131591

05-09
### 关于CAN FD协议及其在汽车和嵌入式系统中的实现 #### CAN FD简介 CAN FD(Controller Area Network Flexible Data-rate)是一种扩展版的CAN总线通信协议,旨在满足现代车辆和工业自动化设备对更高数据传输速率的需求。相比于传统CAN协议的最大波特率1 Mbps,CAN FD支持更高的比特率以及更大的帧长度,从而显著提升了网络性能[^3]。 #### 数据结构与应用开发 为了构建支持CAN FD的应用程序,开发者可以使用`struct canfd_frame`作为基础的数据结构来处理基于`CAN_RAW`套接字的消息传递。当应用程序运行在较旧版本的Linux内核上时,如果启用`CAN_RAW_FD_FRAMES`选项失败,则会回退到传统的CAN消息格式,而不会中断整个系统的正常工作流程。 以下是创建一个简单的CAN FD发送器的例子: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <net/if.h> #include <sys/ioctl.h> #include <linux/can.h> #include <linux/can/raw.h> int main(void) { int s; struct ifreq ifr; struct sockaddr_can addr; /* 创建socket */ if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { perror("Socket"); return 1; } strcpy(ifr.ifr_name, "can0"); // 替换为实际使用的接口名 ioctl(s, SIOCGIFINDEX, &ifr); addr.can_family = AF_CAN; addr.can_ifindex = ifr.ifr_ifindex; bind(s, (struct sockaddr *)&addr, sizeof(addr)); struct canfd_frame frame; memset(&frame, 0, sizeof(struct canfd_frame)); frame.len = 8; // 设置有效载荷大小 memcpy(frame.data, "\x12\x34\x56", 3); // 填充数据部分 write(s, &frame, sizeof(struct canfd_frame)); close(s); return 0; } ``` 此代码片段展示了如何通过C语言编写一段用于初始化并写入单条CAN FD消息至指定硬件接口上的逻辑。 #### 实现细节对比分析 相较于标准CAN协议栈而言,SocketCAN框架提供了更加灵活且易于集成的方式来进行实时通讯管理。它不仅兼容现有的Berkeley sockets API设计模式,还允许程序员利用熟悉的TCP/IP编程技巧快速掌握其操作方法[^1]。此外,在服务导向架构(Service-Oriented Architecture SOA)理念指导下,借助诸如TCP/IP之类的通用网络层协议能够进一步增强不同子模块间协作能力,并促进跨平台互操作性的提升[^2]。 综上所述,无论是从理论层面还是实践角度出发考虑,采用CAN FD技术都将成为未来智能化交通解决方案不可或缺的一部分;同时配合恰当的安全防护措施如MUD策略联合SDN机制共同作用下可有效抵御潜在威胁攻击行为的发生概率降低风险水平[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值