Linux下CAN总线通信调试记录

1. 概述

    CAN总线是德国BOSCH公司从80年代初为解决现代汽车中众多的控制与测试仪器之间的数据交换而开发的一种串行数据通信协议,它是一种多主总线,通信介质可以是双绞线、同轴电缆或光导纤维。通信速率最高可达1Mbps。
    SAMA5D27处理器的CAN控制器使用的是BOSCH公司的MCAN IP核,其手册中MCAN章节的内容与BOSCH的MCAN用户手册基本一致。
    我们的CAN通信测试如下:使用处理器连接CAN分析仪,分析仪为USB转CAN,分析仪连接PC机。在PC机上运行CAN分析仪提供的软件。

    实物连接图如下。
在这里插入图片描述

2. 硬件原理图设计

硬件原理图设计如下。
在这里插入图片描述
在这里插入图片描述
    处理器CAN控制器的CANTX0和CANRX0引脚连接到高速CAN收发器上,CAN收发器的作用:CAN收发器具有“边说边听(同时发送和接收)”和“信号转换(数字信号与总线电压信号的转换)”的作用。
    对应手册查看使用的是处理器的CAN0控制器。
在这里插入图片描述
在这里插入图片描述
手册中CAN控制器的组成框图。
在这里插入图片描述

3. 驱动相关的修改

SAMA5D27使用的是mcan,对应的控制器驱动路径为:

  • \linux-at91-master\linux-at91-master\drivers\net\can\m_can\m_can_platform.c
  • \linux-at91-master\linux-at91-master\drivers\net\can\m_can\m_can.c

控制器驱动没有什么要修改的。

设备树:

  • \linux-at91-master\linux-at91-master\arch\arm\boot\dts\sama5d2.dtsi

    修改了CAN0和CAN1的 message ram的基地址以及长度,及message ram的配置参数等。
在这里插入图片描述
在这里插入图片描述
相应的在dts文件中添加了CAN0节点及其引脚定义并使能。

  • \linux-at91-master\linux-at91-master\arch\arm\boot\dts\at91-sama5d27_som1_ek.dts

在这里插入图片描述
在这里插入图片描述
下面是m_can_platform.c 中匹配相关的属性定义。
在这里插入图片描述
    个人理解:m_can_platform.c 文件作为BOSCH MCAN的总线驱动,主要的工作是CAN总线的注册,以及读写寄存器和读写FIFO数据的接口封装,为用户空间的调用(cansend、candump、canconfig)提供接口。m_can.c文件主要是对读写接口具体的实现,操作CAN寄存器以及FIFO的具体实现。

4. 相关的参考资料

4.1 Message RAM 配置

手册中对Message RAM的介绍:
在这里插入图片描述
参考内核的Documentation:

  • \linux-at91-master\linux-at91-master\Documentation\devicetree\bindings\net\can\m_can.txt

在这里插入图片描述
其他文献参考:https://lkml.org/lkml/2020/12/28/1991
在这里插入图片描述
上述资料的介绍,能够与设备树中配置Message RAM 的参数对应上。

芯片手册中关于Message RAM的介绍:
在这里插入图片描述
    以前的SAMA5D27-ek Demo板使用的 Message RAM 基地址为0x210000,看原厂提供的设备树中配置的也是0x210000,但是使用这个基地址,CAN通信就会异常,配置成0x210000时,CAN控制器会将其映射到0x0这个地址,只有配置成0x200000时,Message RAM的起始地址才是从0x200000开始。
    

5. 详细调试情况

5.1 使用最新的Linux内核

在Microchip 的Git库上拉取的最新的内核代码。
地址:https://github.com/linux4sam
在这里插入图片描述
在这里插入图片描述
开发板启动后查看内核版本:Linux 5.4.104
在这里插入图片描述
CAN驱动加载内核打印日志。
在这里插入图片描述
这里两个CAN控制器都使能了。

5.2 开发板与CAN分析仪硬件连接

开发板的R107和R108虽然DNP,但实际电路板中还是让硬件工程师焊接了电阻(62R),两个电阻串联,等效与120欧姆。
在这里插入图片描述
CAN分析仪的电阻拨码开发也需要拨。
在这里插入图片描述
为什么要使用120欧姆的电阻下面的章节会说明。

5.3 调试步骤

使用canutils工具进行通信测试。
测试工具的使用参考:
https://www.pianshen.com/article/3406986211/
https://blog.csdn.net/segments/article/details/105510658

测试步骤:
1) canconfig can0
查看can0的配置信息
在这里插入图片描述
2) canconfig can0 bitrate 100000
配置波特率为100K
在这里插入图片描述
3) canconfig can0 start
打开使能CAN0
在这里插入图片描述
4) PC上配置CAN分析仪软件工具
这个CAN分析仪工具是购买分析仪时自带的上位机软件。
在这里插入图片描述
在这里插入图片描述
【设备操作】栏,点击【打开设备】
在这里插入图片描述
点击【确定】,然后在弹出的对话框中配置CAN参数,这里使用的CAN的通道1,分析仪上有两个CAN通道,注意别接错喽。
在这里插入图片描述
这里配置波特率为100K,与开发板的波特率保持一致。

5) 开发板发送数据
cansend can0 -i 0x10 0x11 0x22 0x33 0x44
发送的标准帧,ID(0x10),数据(0x11 0x22 0x33 0x44)
在这里插入图片描述
6) 开发板接收数据
PC机上发送数据,发送的标志帧。
ID(0x1),数据(0x11 0x22 0x33 0x44 0x55 0x66 0x77 0x88)
在这里插入图片描述
(除使用canutils工具外,还可以使用ip命令进行CAN的相关配置)

5.4 在 /etc/network/interfaces 文件中初始化CAN

在这里插入图片描述

auto can0
iface can0 inet manual
        #pre-up ip link set $IFACE type can bitrate 125000 listen-only off
        pre-up ip link set $IFACE type can bitrate 125000 triple-sampling on
        up /sbin/ifconfig $IFACE up
        down /sbin/ifconfig $IFACE down

6. 调试其他注意事项

6.1 使用Socket CAN

例程:(CSDN其他吧友的测试程序)

/*********************
 * File: can_test.c
 * ******************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#define command "/sbin/ip link set can0 type can bitrate 100000"//将CAN0波特率设置为100K bps
#define up "ifconfig can0 up"//打开CAN0
#define down "ifconfig can0 down"//关闭CAN0
 
int main()
{
    printf("- can0 down \n");
    system(down);
    printf("- can0 config bitrate-100K \n");
    system(command);
    printf("- can0 up \n");
    system(up);//上面三行关闭CAN设备,设置波特率后,重新打开CAN设备

    int s, nbytes;
    struct sockaddr_can addr;
    struct ifreq ifr;
    struct can_frame frame[2] = {{0}};

    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);//创建套接字
    printf("- can0 socket \n");

    strcpy(ifr.ifr_name, "can0" );
    ioctl(s, SIOCGIFINDEX, &ifr); //指定 can0 设备
    printf("- can0 ioctl \n");

    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    bind(s, (struct sockaddr *)&addr, sizeof(addr));//将套接字与 can0 绑定
    //(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);//设置过滤规则,取消当前注释为禁用过滤规则,即不接收所有报文,不设置此项(即如当前代码被注释)为接收所有ID的报文。
    printf("- can0 binded \n");

    frame[0].can_id = 0x666;
    frame[0].can_dlc = 8;
    frame[0].data[0] = 0x40;
    frame[0].data[1] = 0x20;
    frame[0].data[2] = 0x10;
    frame[0].data[3] = 0x00;
    frame[0].data[4] = 0x03;
    frame[0].data[5] = 0x04;
    frame[0].data[6] = 0x05;
    frame[0].data[7] = 0x06;

    for(int i=0;i<10;i++)
    {
        printf("- for enter: %d \n", i);
        frame[0].data[7]++;
        printf("send frames: 0x40 0x20 0x10 0x00 0x03 0x04 0x05 0x06 \n");
        nbytes = write(s, &frame[0], sizeof(frame[0])); //发送 frame[0]
        if(nbytes != sizeof(frame[0]))
        {
            printf("Send Error frame[0]\n!");
        }
 
        nbytes = read(s, &frame[1], sizeof(frame[1]));//接收总线上的报文保存在frame[1]中
        printf("the nbytes:%d\n", nbytes);
        printf("length:%d \n", sizeof(frame[1]));
        printf("ID=0x%X DLC=%d\n", frame[1].can_id, frame[1].can_dlc);
        printf("data0=0x%02x\n",frame[1].data[0]);
        printf("data1=0x%02x\n",frame[1].data[1]);
        printf("data2=0x%02x\n",frame[1].data[2]);
        printf("data3=0x%02x\n",frame[1].data[3]);
        printf("data4=0x%02x\n",frame[1].data[4]);
        printf("data5=0x%02x\n",frame[1].data[5]);
        printf("data6=0x%02x\n",frame[1].data[6]);
        printf("data7=0x%02x\n",frame[1].data[7]);
        sleep(1);
    }
 
    close(s);
    return 0;
}

亲测编译后可以执行。

6.2 CAN接120欧姆终端电阻的原因分析

    高频信号传输时,信号波长相对传输线较短,信号在传输线终端会形成反射波,干扰原信号,所以需要在传输线末端加终端电阻,使信号到达传输线末端后不反射。对于低频信号则不用 CAN总线两端必须连接终端电阻才可以正常工作,终端电阻应该与通讯电缆的阻抗相同,典型值为120欧姆。其作用是匹配总线阻抗,提高数据通信的抗干扰性及可靠行。 

  1. 终端电阻的作用就是吸收信号反射及回波,而产生信号反射的最大来源便是阻抗不连续以及不匹配。 
  
  2. 如果是加在单独的两根线上,相当于一个开环的状态,根据产生信号反射的来源,也就是说这种连接方式会导致单线上阻抗更加不连续,在末端突然变为0,会导致反射成倍增加。 高速CAN所加的两个120欧的电阻实际上模拟的是线束连接无穷远的时候在传输线上产生的特性阻抗(而不是实际阻抗),这是个典型经验值,具体值取决于所采用的线束类型。 以上如仍有不明之处,请简单查阅下传输线理论和信号反射相关的知识。 
    CAN低速之所以不加终端电阻,是因为不同的频率时,同样的连接方式所产生的信号反射和回波差异很大,频率越高,反射和回波越强烈。另外不同的频率下,传输线的特性阻抗是不同的。

3. 在ISO-11898-2:2003第4页第一段中大致有这么一句话:“当一个显性位发送到至少包含一个CAN驱动处于开启状态的网络上时,意味着有电流经过终端电阻,因此,CAN_H和CAN_L具有了不同的电压值。”,也就是说,在显性状态时,终端电阻会稳定并增强差分电压,当去掉一个或两个终端,通过示波器可以明显看到一是信号不稳,二是差分电压会有变化,缺少终端或没有终端电阻时所测到的电压我认为是单纯由CAN驱动器所产生的,离发送端越远,电压差异越大。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heat.huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值