技术天地

支持CAN FD的扩展模块介绍作者:黄志超    发布时间:2020-5-27 13:57:33    被阅览数:

  随着现在工控领域技术的发展,传输的数据量越来越多, CAN总线在传输速率和带宽渐渐不能满足现场的需求。为了解决这个问题,BOSCH公司推出了CAN FD(CAN with Flexible Data rate)协议,该协议可以支持更高的波特率和更长的数据位,最高波特率可达8Mbit/s,支持最长数据位为64byte,并且可以兼容传统的CAN 2.0B协议。为了在英创Linux工控主板上支持CAN FD,满足客户的需求,英创公司基于SBC8XX系列工控应用底板,设计了扩展模块ETA703。


eta703侧面.png

ETA703模块


  ETA703通过SPI总线扩展出一路支持CAN FD的CAN总线,同时将主板的串口隔离后分别转换为RS232和RS485,并将主板带有的2路CAN总线也经过隔离后引出,因此模块上一共包含3路can、3路RS485和1路RS232:


ETA703工控通讯接口接口数量简要说明
CAN-FD高速现场总线1 8Mbps最高波特率,与CAN2.0B兼容
CAN-2.0B总线2 波特率: 50kbps - 1Mbps
RS4853 自动方向切换
RS2321 3线制


  英创公司已经调试好了ETA703的驱动,用户在使用时调用modprobe eta703命令就能够加载对应的驱动文件。目前能够支持ETA703扩展模块的主板为ESM6800H/E,ESM6802和ESM7000,因为CAN FD是比较新的功能,需要这几款主板使用的较高版本的交叉工具链才能够支持。


  驱动加载成功后系统会生成新的CAN设备,因为ESMARC系列主板都板载了2路CAN总线(can0和can1),所以加载驱动后生成的设备为can2,可以使用命令ifconfig –a来查看。


  关于ETA703更加具体的参数说明可以参考ETA703的数据手册。这里主要介绍关于CAN FD的相关概念和程序接口。CAN FD的全称为CAN with Flexible Data rate,相对于传统的CAN总线协议,主要有两点变化:


  第一点从字面上就能够看出来,即传输速率是可变的,最高可达8Mbit/s。


  第二点是相比传统CAN总线的8byte数据位,CAN FD协议最长可以支持64byte数据位。


  我们可以将CAN FD看作是传统CAN 2.0B协议的升级版本,并且是向下兼容的,即能够同时支持CAN 2.0B协议。所以使用原来英创公司提供的CAN总线例程(test_socketcan)就能够在ETA703上进行正常的通讯,只是没有启用CAN FD的功能而已,关于CAN FD协议更加详细的介绍可以参考网站:https://www.can-cia.org/can-knowledge/can/can-fd/


  接下来我们介绍如何通过程序启用CAN FD协议进行通讯。其实Linux系统使用的socketcan接口已经很好的支持了CAN FD,并且同时能够兼容CAN 2.0B协议。首先来看在<linux/can.h>头文件中对于CAN和CANFD数据帧的结构体定义:



struct can_frame {

       canid_t can_id/* 32 bit CAN_ID + EFF/RTR/ERR flags */

       __u8    can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */

       __u8    __pad;   /* padding */

       __u8    __res0/* reserved / padding */

       __u8    __res1/* reserved / padding */

       __u8    data[CAN_MAX_DLEN] __attribute__((aligned(8)));

};


  上面是对CAN数据帧的定义,和下面CAN FD数据帧的定义对比,可以发现是兼容的,区别只在于数据位的长度上面:



struct canfd_frame {

       canid_t can_id/* 32 bit CAN_ID + EFF/RTR/ERR flags */

       __u8    len;     /* frame payload length in byte */

       __u8    flags;   /* additional flags for CAN FD */

       __u8    __res0/* reserved / padding */

       __u8    __res1/* reserved / padding */

       __u8    data[CANFD_MAX_DLEN] __attribute__((aligned(8)));

};


  关于数据位的长度,根据前面的介绍应该能够了解到CAN FD最长支持64byte的数据位,在头文件中有如下定义:



/* CAN payload length and DLC definitions according to ISO 11898-1 */

#define CAN_MAX_DLC 8

#define CAN_MAX_DLEN 8

 

/* CAN FD payload length and DLC definitions according to ISO 11898-7 */

#define CANFD_MAX_DLC 15

#define CANFD_MAX_DLEN 64


  启用CAN FD具体命令为ip link set can2 up type can bitrate 1000000 dbitrate 2000000 fd on restart-ms 100,可以看到是在原来使能CAN总线命令的基础上增加了CAN FD的波特率的设置。同时在程序中也需要调用ioctl来使能CAN FD,具体代码如下:



/* try to switch the socket into CAN FD mode */

canfd_on = 1;

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on));


  在使能了CAN FD协议后,数据通讯的部分使用的函数和标准的CAN通讯是相同的,都是使用write和recv函数,驱动会根据传输的帧的长度,自动判断是否为CAN FD数据帧。所以客户在编写程序的时候,只需要注意一下填入的传输数据长度即可,这里可以利用头文件中的宏定义:



#define CAN_MTU           (sizeof(struct can_frame))

#define CANFD_MTU       (sizeof(struct canfd_frame))


  发送CAN FD数据的具体代码如下:



struct canfd_frame   frame;

frame.len = 64;

nbytes = write(s, &frame, CANFD_MTU);


  如果将frame.len的值改为8,write函数中的长度改为CAN_MTU,驱动就自动切换成CAN 2.0B协议进行发送。同样的在接收数据的时候,可以通过recv函数的返回值来判断,具体代码如下:



nbytes = recv(can_sock, &frame, CANFD_MTU, 0 );

if (nbytes < 0)

{

       perror("can raw socket read");

       break;

}

if ((size_t)nbytes == CAN_MTU) {

       maxdlen = CAN_MAX_DLEN;

}

else if ((size_t)nbytes == CANFD_MTU) {

       maxdlen = CANFD_MAX_DLEN;

}

else {

       fprintf(stderr, "read: incomplete CAN frame\n");

       return 1;

}


  从上面的代码可以看出CAN FD的编程十分简单,socketcan提供的接口完美的兼容了CAN 2.0B和CAN FD,只需要在原来标准CAN总线的例程中增加对CAN FD的使能就可以了,在数据传输时候,根据数据帧长度就能判断出类型,然后做出对应的处理。


  感兴趣的客户可以和英创的工程师联系,索取完整的例程代码。

Go Top
影音先锋av电影院资源,一女子多男子三级片,香港三级经典片,萝莉装av,有关色情的电影网址