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 offpre-up ip link set $IFACE type can bitrate 125000 triple-sampling onup /sbin/ifconfig $IFACE updown /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"//关闭CAN0int 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驱动器所产生的,离发送端越远,电压差异越大。

Linux下CAN总线通信调试记录相关推荐

  1. Linux第二次试验:Linux下的进程通信实验

    Linux第二次试验:Linux下的进程通信实验 前言 一.实验目的 二.实验工具与设备 三.实验预备知识 三.实验内容和步骤 五.实验代码及步骤截图 六.实验总结 前言 为了帮助同学们完成痛苦的实验 ...

  2. linux下GT911触摸屏驱动优化记录

    linux下GT911触摸屏驱动优化记录 背景 由于最近要做linux内核启动速度优化,所以就对着驱动一点一点优化,加上QT应用程序的初始化,总共的启动时间要做到4S以内.目前先调试GT911驱动程序 ...

  3. linux下c/c++程序调试拾遗

    linux下c/c++程序调试拾遗 以下为整理c++程序调试过程中经常用到的工具链 1. 调试利器GDB linux下c++程序的调试,绕不过去的第一个就是gdb无疑了: 1.1 启动gdb gdb ...

  4. linux常用调试,linux下gdb常用的调试命令

    用gdb调试程序时,常常很困惑一些命令的使用,要么是不知道这个命令,要么忘了命令的使用方法.接下来是小编为大家收集的linux下gdb常用的调试命令,希望能帮到大家. linux下gdb常用的调试命令 ...

  5. Linux下使用GDB进行调试

    Linux下使用GDB进行调试的常用命令记于此. $ sudo su # g++ -g test.cpp -o test -pthread # gdb test         <------- ...

  6. STM32串口通信代码、ASCII码、XU4串口通信,printf只会转换为无符号类型,linux下的串口通信程序

    1.其里面的的通信协议是是自己定的,这里 是检测到数据的结尾是以0x0d.0x0a结尾,则表示接受的数据完成了,这个数据是我想要的,这样子就不会出现一些错乱的数据信息.其中的0x8000.0x4000 ...

  7. linux下的socket通信

    linux下的socket通信 在linux下,无论多么复杂的服务器或客户端程序,无论什么编程语言实现的,其底层都离不开linux内核提供的系统调用(也就十多个函数),其网络通信的基本流程一定如下所述 ...

  8. linux下的串口通信

    一.串口的基本原理 1 串口通讯 串口通讯(Serial Communication),是指外设和计算机间,通过数据信号线.地线等,按位进行传输数据的一种通讯方式.     串口是一种接口标准,它规定 ...

  9. Linux下的段错误调试方法

    转自http://wenku.baidu.com/view/7416d23710661ed9ad51f33f.html 执行socket文件时,出现段错误 (core dumped) 产生段错误就是访 ...

最新文章

  1. 【转】Jmeter常见问题
  2. .Net Compact Framework实现文件下载功能
  3. 使用pip将Python包安装到不同的目录中?
  4. 计算机系统概论寻址空间,自考《计算机系统结构》重点知识概论:数据表示(二)...
  5. radio按扭设置只读_disabled属性样式问题
  6. android中OnItemClickListener的参数解释
  7. 如何接地气地接入微前端?
  8. ios app上架被拒的问题
  9. 阿里巴巴在内蒙古旱区试水物联网灌溉技术,一年省出1.5个西湖
  10. TikTok 已经成为影响力营销的新战场
  11. C++学习书籍推荐《The C++ Standard Library 2nd》下载
  12. Codewar python训练题全记录——持续更新
  13. 基于MUI框架的影视播放APP的设计与实现毕业设计论文参考【原查重5.1%】
  14. 国内外最佳的photoshop教程网站推荐
  15. [原创]浅析汇编之堆栈平衡
  16. [求助]python模拟布丰投针
  17. KGB知识图谱技术能够解决哪些行业痛点?
  18. Pycharm生成.exe文件
  19. 每周读书#11 - 等一朵花开
  20. 2021年,手机拼什么?

热门文章

  1. JAVA多线程同步计数器
  2. 当你写爬虫抓不到APP请求包的时候该怎么办?【高级篇-混淆导致通用Hook工具失效】
  3. Java Ucase_VBScript字符串期函数(InStr、Left、Len、Mid、Replace、StrComp、UCase……)...
  4. 摄影师的“伟大”!分享一组高大上的“照骗”的前期与后期
  5. Linux下可回收删除
  6. 认识中药(4)--陈皮
  7. 电竞Dota2数据API接口 - 【联赛列表】API调用示例代码
  8. 图漾科技招聘|机器视觉算法、嵌入式驱动开发高级工程师等岗位
  9. 家装软件相关算法和技术归纳
  10. 【Centos】Docker停止容器服务后,磁盘I/O仍然迟迟不下降。(未解决)