CAN总线简单介绍

什么是can总线?controller area network,简称can或者can bus) 是一种功能丰富的串行总线标准,最早的can控制芯片在奔驰车上应用并量产,因为支持多主机,多从机的优点,所以一辆车所有控制器,传感器,电子设备直接的通信只需要两条线就够了,大大优化了整车的布线。
随着技术的不断发展,can发布了相应的标准,国际化标准组织,公布了can的不同标准;
标准 涵盖内容
iso 11898-1 数据链路层
iso 11898-2 高速can的物理层
iso 11898-3 低速容错can的物理层
iso 11898-1  ,iso 11898-2是对应的设计标准,去搜索就可以知道这个技术点是如何进行设计的。
物理层差分信号这里我们介绍一下物理层,什么是物理层呢?就是can的电信号的传输过程。can是串行异步通讯,只有can_high和can_low两条差分信号线,数据通过差分信号的方式进行通讯,其优点就是可以增加信号的抗干扰能力,抑制共模信号的干扰;
具体如下图所示;

所以,信号在变成一个字节一个字节的数字信号之前,就是按照这种差分形式的模拟信号来传输的。
我们可以简单地理解一下,当can_high减去can_low大于某个阈值的时候,可以把它当做逻辑高,反之,当小于某一个阈值时,就变成逻辑低。
下面我们再来看看can总线设备之间是如何连接的。
连接方式can总线支持多个节点挂载在总线上,比较类似i2c总线,可以在scl和sda上挂载多个从机,具体如下图所示;

不过can总线其实没有主从的概念,每个设备都是一个节点(node),节点直接可以相互通讯,相较于i2c总线,can总线设置了终端电阻,常见的一种闭环连接模式,相对的还有开环的连接模式。
不同的连接模式,他们的通讯速率也大不相同,这里也就是高速can和低速can的区别。
两条电线组成一条双绞线,并且接有120ω的特性阻抗。iso 11898-2,也称为高速度can。它在总线的两端均接有120ω电阻。
使用了120ω终端电阻(这是can的iso标准里规定的),这种模式的最高通讯速率可以达到1mbps,下面是传输距离和传输速度的关系;

can总线长度与信号速率关系
高速can的拓扑结构具体如下所示;

还有一种是低速can,或者也叫做容错can,低速容错 can 总线将通讯的最大带宽从 1 mbps 降低到 125 kbps,并且不再在总线的起点和终点使用两个终端电阻,而是将电阻分布在每个节点上。具体如下图所示;

由于高速can和低速can的拓扑结构不同,另外终端电阻的分布也不同,所以can_high和can_low上的电平是不相同的,这里有隐性电平和显性电平。
硬件上的连接基本上都搞清楚了,下面就是如何去实现一个具体的can节点。我们来简单地介绍一下。
can节点can节点通常分为三个部分;
mcu/cpu;
can控制器,
can收发器;
通常一些单片机内部就集成了相应的can控制器外设,比如我们比较常用的单片机——stm32,所以我们常见的结构一般是这样子的。

所以整体的流程是这样的,如下:
can总线上通过差分信号进行数据传输;
can收发器将差分信号转换为ttl电平信号,或者将ttl电平信号转换为差分信号;
can控制器将ttl电平信号接收,并传输给mcu;
那么,对于单片机开发者而言,需要关注的就是最终can控制器传输给mcu的数据,如何去配置can控制器,以及使用can控制进行数据的读取和发送。
既然这样,我们就不得不去了解一下can总线的通信原理,如何寻址,上层协议如何规定的。
can协议can协议和网络协议比较类似,进行了分层的设计思想;

按照我的理解;
物理层就是前面提到过的硬件拓扑结构,包括高速can和低速can,而can收发器就属于物理层;
传输层则是can控制器所需要做的事情,包括can时序,同步,消息仲裁,确认,错误检验等,这个比较复杂,如果只是应用开发,我认为,简单了解一下即可;这一层需要做的工作包括:
故障约束;
错误监测;
消息验证;
信息确认;
仲裁;
信息帧;
传输速率和时间;
路由信息;
对象层,mcu应该是属于这一层,我们需要对can消息做信息的过滤设置,can消息的处理等等;
应用层就是基于对象层的进一步封装,不同的can标准,比如工业自动化领域的canopen,汽车诊断iso 14229 定义的uds等等;
如何寻址?can总线上的每个节点不需要设置节点的地址,而是通过消息的标识符(identifier)来区别信息。因为can总线的消息是广播的(就是大家都可以收到消息),比如总线上有节点a,节点b,节点c,那么节点a发消息,节点b和节点c都会收到消息;
节点b 和 节点c 会根据消息中的标识符,以及b和c中的消息过滤规则进行比较,如果不满足规则,就不接受这条信息。
这里需要注意的是:
发送消息的时候,总线必须处于空闲状态;
标识符越小,则消息获取总线的优先级越高;
在这里我们已经了解如何寻址,下面就看一下消息帧了。
帧类型can有4种帧类型:
数据帧:包含用于传输的节点数据的帧
远程帧:请求传输特定标识符的帧
错误帧:由任何检测到错误的节点发送的帧
过载帧:在数据帧或远程帧之间插入延迟的帧
这里我们有必要重点了解一下数据帧,下面继续介绍各种帧之间的区别。
数据帧数据帧分为标准帧和扩展帧两种格式;
基本帧格式:有11个标识符位
扩展帧格式:有29个标识符位
数据帧的结构具体如下所示;

数据帧格式
简单介绍一下数据帧的细节;
sof:start of frame,表示数据帧开始;(1 bit)
identifier:标准格式11 bit,扩展格式29 bit包括base identifier(11 bit)和extended identifier(18 bit),该区段标识数据帧的优先级,数值越小,优先级越高;
rtr:远程传输请求位,0时表示为数据帧,1表示为远程帧,也就是说rtr=1时,消息帧的data field为空;(1 bit)
ide:标识符扩展位,0时表示为标准格式,1表示为扩展格式;(1 bit)
dlc:数据长度代码,0~8表示数据长度为0~8 byte;(4 bit)
data field:数据域;(0~8 byte)
crc sequence:校验域,校验算法,
del:校验域和应答域的隐性界定符;(1 bit)
ack:应答,确认数据是否正常接收,所谓正常接收是指不含填充错误、格式错误、 crc 错误。发送节点将此位为1,接收节点正常接收数据后将此位置为0;(1 bit)
srr:替代远程请求位,在扩展格式中占位用,必须为1;(1 bit)
eof:连续7个隐性位(1)表示帧结束;(7 bit)
itm:帧间空间,intermission (itm),又称interframe space (ifs),连续3个隐性位,但它不属于数据帧。帧间空间是用于将数据帧和远程帧与前面的帧分离开来的帧。数据帧和远程帧可通过插入帧间空间将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。过载帧和错误帧前不能插入帧间空间。
远程帧一般地,数据是由发送单元主动向总线上发送的,但也存在接收单元主动向发送单元请求数据的情况。远程帧的作用就在于此,它是接收单元向发送单元请求发送数据的帧。远程帧与数据帧的帧结构类似,如上图x所示。远程帧与数据帧的帧结构区别有两点:
数据帧的 rtr 值为“0”,远程帧的 rtr 值为“1”
远程帧没有数据块
远程帧的 dlc 块表示请求发送单元发送的数据长度(byte)。当总线上具有相同标识符的数据帧和远程帧同时发送时,由于数据帧的 rtr 位是显性的,数据帧将在仲裁中赢得总线控制权。
错误帧用于在接收和发送消息时检测出错误时,通知错误的帧。错误帧由错误标志和错误界定符构成。错误帧的帧结构如图11示。
错误标志:
个显性/隐性重叠位
主动错误标志(6个显性位):处于主动错误状态的单元检测出错误时输出的错误标志
被动错误标志(6个隐性位):处于被动错误状态的单元检测出错误时输出的错误标志
错误界定符:8 个隐性位

过载帧过载帧是用于接收单元通知发送单元它尚未完成接收准备的帧。在两种情况下,节点会发送过载帧:
接收单元条件的制约,要求发送节点延缓下一个数据帧或远程帧的传输;
帧间空间(intermission)的 3 bit 内检测到显性位
每个节点最多连续发送两条过载帧。过载帧由过载标志和过载界定符(8 个隐性位)构成。数据帧的帧结构如图12所示。

can_overload_frame
这里基本把帧介绍完了,但是每个节点之间的通讯,我们如何知道这一帧开始接收了,这一帧已经接收结束了呢?下面就需要了解一下消息的时序和消息同步的方法。
消息时序以及同步位时序在讲can消息时序和同步之前,我们可以对照一下uart串口的传输协议,他有起始位和停止位,然后大家都规定使用相同的通讯速率(波特率);
其实can通讯也是类似的方式,它属于异步通讯,没有时钟信号线,所以所有节点之间要约定好使用相同的波特率来传输数据。
在总线空闲一段时间后,在(起始位) 进行硬同步,同步方式是将每一位划分成多个称为量子的时间段(time quanta),并分配一定数量的量子到位中的四个阶段完成的。
这四个阶段分别为:
sync_seg:同步段,1 个时间量子长度。它用于同步各种总线节点;
prop_seg:传播段,1~8 时间量子长度。它用于补偿网络上的信号延迟。
phase_seg_1:相位缓冲段1,1~8 时间量子长度。它用于补偿边缘相位误差,在重新同步期间可能会延长。
phase_seg_2:相位缓冲段2,2~8 时间量子长度。它用于补偿边缘相位误差
具体如下图所示;

位时序
波特率如何计算波特率,需要知道每个量子时间的长度(time quanta),以及每一位需要多少个量子时间,
假设这里time quanta = 1us ,并且1 bit = 8 tq,那么上图中的波特率就应该是:
消息过滤器前面有提到消息在can总线上是广播式的,但并不是所有节点都会对总线上所有消息感兴趣。节点通过控制器中过滤码(filter code )和掩码(mask code),再检验总线上消息的标识符,来判断是否接收该消息(message filtering)。
对于掩码,“1”表示该位与本节点相关,“0”表示该位与本节点不相关。举例如下:
例1:仅接收消息标识符为00001567(十六进制)的帧
设置过滤码为00001567
设置掩码为1fffffff
节点检测消息的标识符的所有位(29位),如果标识符为00001567接收,否则舍弃。
例2:接收消息标识符为00001567 到0000156f 的帧
设置过滤码为00001560
设置掩码为1ffffff0
节点检测消息的标识符的高25位,最低的4位则不care。如果标识符最高25位相同则接收,否则舍弃。
例3:接收消息标识符为00001560 到 00001567 的帧
设置过滤码为00001560
设置掩码为1ffffff8
节点检测消息的标识符的高26位,最低的3位则不care。如果标识符最高26位相同则接收,否则舍弃。
例4:接收所有消息帧帧
设置过滤码为0
设置掩码为0
节点接收总线上所有消息。
如何配置?上面介绍了帧类型,那么如何基于mcu进行配置呢?这里以stm32f407为硬件平台,使用hal库进行初始化,看一下都对哪些地方进行了配置。一般来说,我们需要配置can的波特率,消息过滤器等等,下面是简单的配置的代码;
can_handletypedef hcan;void mx_can_init(void){    can_filtertypedef   sfilterconfig;    /*can单元初始化*/    hcan.instance = can1;      /* can外设 */     /* btr-brp 波特率分频器  定义了时间单元的时间长度42/(1+6+7)/6=500kbps */    hcan.init.prescaler = 6;    hcan.init.mode = can_mode_normal;   /* 正常工作模式 */    hcan.init.syncjumpwidth = can_sjw_1tq;  /* btr-sjw 重新同步跳跃宽度 1个时间单元 */    hcan.init.timeseg1 = can_bs1_6tq;   /* btr-ts1 时间段1 占用了6个时间单元 */    hcan.init.timeseg2 = can_bs2_7tq;   /* btr-ts1 时间段2 占用了7个时间单元 */    hcan.init.timetriggeredmode = disable;  /* mcr-ttcm  关闭时间触发通信模式使能 */     hcan.init.autobusoff = enable;    /* mcr-abom  自动离线管理 */    hcan.init.autowakeup = enable;    /* mcr-awum  使用自动唤醒模式 */    hcan.init.autoretransmission = disable;  /* mcr-nart  禁止报文自动重传   disable-自动重传 */    /* mcr-rflm  接收fifo 锁定模式  disable-溢出时新报文会覆盖原有报文 */    hcan.init.receivefifolocked = disable;      /* mcr-txfp  发送fifo优先级 disable-优先级取决于报文标示符 */    hcan.init.transmitfifopriority = disable;     if (hal_can_init(&hcan) != hal_ok)    {        //error_handler();    } // 初始化发送器 hcan1_txmessage.ide = can_id_std; hcan1_txmessage.rtr = can_rtr_data; hcan1_txmessage.transmitglobaltime = enable;  // 初始化滤波器 设置为0 则不对消息进行过滤    hcan1_filter.filteridhigh               = 0;  /* 要过滤的id高位 */    hcan1_filter.filteridlow                = 0;  /* 要过滤的id低位 */    hcan1_filter.filtermaskidhigh          = 0;  /* 过滤器高16位每位必须匹配 */    hcan1_filter.filtermaskidlow            = 0;  /* 过滤器低16位每位必须匹配 */    hcan1_filter.filterfifoassignment   = can_filter_fifo0;/* 过滤器被关联到fifo 0 */    hcan1_filter.filterbank                 = 0;    hcan1_filter.filtermode                 = can_filtermode_idmask; /* 工作在标识符屏蔽位模式 */    hcan1_filter.filterscale                = can_filterscale_32bit;  /* 过滤器位宽为单个32位。*/    hcan1_filter.filteractivation        = enable;    hcan1_filter.slavestartfilterbank   = 0;   hal_can_configfilter(&hcan, &hcan1_filter);  while(hal_can_start(&hcan) != hal_ok ) {  printf(\ncan_start failed!!);  hal_delay(100); } hal_can_activatenotification(&hcan, can_it_rx_fifo0_msg_pending);}下面是can发送的函数,我们需要自己构建相应的消息帧格式,通常需要设置消息帧的id格式,消息长度,具体如下;
void can_txmessage(can_handletypedef *hcan,uint16_t id ,uint8_t adata[], uint8_t dlc){    uint32_t tx_mailbox;    /*-1- 配置数据段长度 ----------------------------------------*/  hcan1_txmessage.ide  =   can_id_std; hcan1_txmessage.rtr  =   can_rtr_data; hcan1_txmessage.stdid =   id;    hcan1_txmessage.dlc     =    dlc;   hcan1_txmessage.transmitglobaltime = enable;    /*-2- 发送adata ---------------------------------------------*/    while(hal_can_addtxmessage(hcan, &hcan1_txmessage, adata, &tx_mailbox) != hal_ok)    {        hal_delay(5);    }}上述代码设置发送消息:
can_id_std设置为标准id;
can_rtr_data设置消息为数据帧;
stdid为当前消息的id;
dlc为当前消息的长度;
整体可以参考前面介绍的消息帧格式,篇幅有限,这里就先简单的介绍一下。
总结本文对can总结进行了简单的介绍,can通讯的特点可以总结如下;
符合osi开放式通信系统参考模型;
两线式总线结构,电气信号为差分式;
多主控制。在总线空闲时,所有的单元都可开始发送消息,最先访问总线的单元可获得发送权;多个单元同时开始发送时,发送高优先级 id 消息的单元可获得发送权;
消息报文不包含源地址或者目标地址,仅通过标识符表明消息功能和优先级;
基于固定消息格式的广播式总线系统,短帧结构;
事件触发型。只有当有消息要发送时,节点才向总线上广播消息;
可以通过发送远程帧请求其它节点发送数据;
消息数据长度 0~8 byte;
错误检测功能。所有节点均可检测错误,检测处错误的单元会立即通知其它所有单元;
发送消息出错后,节点会自动重发;
故障限制。节点控制器可以判断错误是暂时的数据错误还是持续性错误,当总线上发生持续数据错误时,控制器可将节点从总线上隔离;
通信介质可采用双绞线、同轴电缆和光导纤维,一般使用最便宜的双绞线;
理论上,can总线用单根信号线就可以通信,但还是配备了第二根导线,第二根导线与第一根导线信号为差分关系,可以有效抑制电磁干扰;
在40米线缆条件下,最高数据传输速率 1mbps;
总线上可同时连接多个节点,可连接节点总数理论上是没有限制的,但实际可连接节点数受总线上时间延迟及电气负载的限制;
文章来源于小麦大叔 ,作者小麦大叔

研发销售6轴、9轴电子罗盘(陀螺仪|加速计|磁力计)、倾角传感器、姿态传感器,惯导、数据采集盒、iot远程智慧监测等
产品广泛应用于:无人机、无人船、巡检/引导/送餐/水下机器人、agv、云台装置、望远镜、qiang支瞄准镜、雷达定位、聚光太阳能、工矿/隧道无人设备等!
核心研发人员十年技术积累,专业研发团队,军工级品质,替代进口。

Intel Xe驱动代码严重缺乏测试
中国智能手机步入“存量市场”下半场 下滑压力链传导至上游
空气质量实时监测系统的使用有何意义
从感觉上“看到”东西
3D打印为何会成为一股强大科技力量
CAN总线简单介绍
电热设备电力装置设计规范GB50056-93
信步科技OPS-J1900规格
智能手表的测试需要一款可以应对小pitch的连接测试模组
galaxy note 2上市时间_三星galaxy note 2什么时候上市
魅蓝note5 21秒售万台破纪录 李楠:明年不做这么多手机了
锡膏厂家:LED专用的锡膏质量会影响led灯品质吗?
物联网协议
“开架式”软件架构设计
晃电的定义、危害及治理方法
怎么恢复手机电池寿命
Type-C接口供电优势 Type-C接口供电接法详解
金升阳无风扇半灌胶电源LMF-UH系列产品的应用
2018年机器人北美出货量创纪录 达35,000台
云天励飞与深圳市智慧城市集团签署项目合作协议