穷尽CAN的一生

  一、CAN的发展

1.经典CAN

        1986年2月,Robert Bosch公司在 SAE(汽车工程协会)大会上介绍了一种新型的串行总线––CAN控制器局域网,那是CAN诞生的时刻。今天,在欧洲几乎每一辆新客车均装配有 CAN局域网。同样,CAN也用于其他类型的交通工具,从火车到轮船或者用于工业控制。 CAN已经成为全球范围内最重要的总线之一甚至领导着串行总线。

        在底特律的汽车工程协会大会上,由 Bosch 公司研究的新总线系统被称为“汽车串行控制器局域网”。Uwe Kiencke、Siegfried Dais 和MartinLitschel 分别介绍了这种多主网络方案。此方案基于非破坏性的仲裁机制,能够确保高优先级报文的无延迟传输。并且,不需要在总线上设置主控制器。此外CAN 之父——上述几位教授和 Bosch 公司的 Wolfgang Borst、Wolfgang Botzenhard、Otto Karl、Helmut Schelling、Jan Unruh 已经实现了数种在 CAN 中的错误检测机制。该错误检测也包括自动断开故障节点功能,以确保能继续进行剩余节点之间的通讯。 传输的报文并非根据报文发送器/接收器的节点地址识别(几乎其它的总线都是如此),而是根据报文的内容识别。同时,用于识别报文的标识符也规定了该报文在系统中的优先级。

        当关于这种革新的通讯方案的大部分文字内容制定之后,于 1987 年中期,Intel 提前计划 2 个月交付了首枚 CAN 控制器:82526,这是 CAN 方案首次通过硬件实现。仅仅用了四年的时间,设想就变成了现实。不久之后, Philips 半导体推出了82C200。

        这两枚最先的 CAN 控制器在验收滤波和报文控制方面有许多不同。一方面,由 Intel 主推的 FullCAN 比由 Philips 主推的 BasicCAN 占用较少的 CPU 载荷;另一方面, FullCAN器件所能接收的报文数目相对受到限制,BasicCAN 控制器仅需较少的硅晶体。今天的 CAN 控制器中,后辈们在同一模块中的验收滤波和报文控制方面仍有相当的不同,制造出 BasicCANFullCAN 两大阵营。

2.时间触发TTCAN

        传统的CAN是基于事件触发的,信息传输时间的不确定性和优先级反转是它固有的缺陷。当总线上传输消息频率不高时,这些缺陷相对影响较小;但随着发送频率的不断增加,性能会急剧下降。

        为了满足汽车控制对实时性和传输消息密度不断增长的需要,改善CAN总线的实时性能非常必要。于是,传统CAN与时间触发机制相结合产生了TTCAN(Time-Triggered CAN),ISO11898-4己包含了TTCAN。 TTCAN总线和传统CAN总线系统的区别是:总线上不同的消息定义了不同的时间槽(Timer Slot)。

3.高速的CAN FD

        2011年初,通用汽车和博世开始着手开发一些有关提高吞吐量的CAN协议。当将越来越多的软件包下载到电子控制单元(ECU)时,汽车行业尤其受苦。高性能通信系统必须缩短这项耗时的任务。通过引入第二个比特率来提高CAN传输速度的想法并不新鲜。自2000年初以来,已有几位学者发表了研究方法。但是,没有一个研究者能够说服汽车制造商。博世与其他CAN专家合作,预先开发了CAN FD规范,该规范于2012年在德国哈姆巴赫城堡举行的第13届国际CAN会议上正式推出。

4.更高速CAN XL

        2020年的第17届国际CAN大会(ICC)上,第三代CAN通信技术CAN XL将启动。

        CAN XL提供一个最大2048字节的数据字段(例如IP(Internet协议),甚至可以传输完整的以太网帧)。11位优先级字段可由网络层用于寻址和指示数据字段的内容。此外,CAN XL协议为使用的下一个更高协议提供8位指示符,其嵌入式层设置参数对于其他高层协议也很有帮助,以简化多协议堆栈。 CAN XL帧通过两个CRC(循环冗余校验)进行保护,其Hamming距离为6,这意味着可以检测到五个随机分布的比特错误。

        CAN XL是一种高度可扩展的通信技术,涉及比特率和数据字段的长度。物理层仍在开发中,目标是实现高达10+ Mbit / s的比特率。 CAN XL针对面向区域的异构网络体系结构进行了优化。该方法以最优的长度满足未来车载网络的要求。汽车工业试图减少布线,以最小化重量,或者换句话说,是限制能耗。

        CAN-XL与CAN-FD一样具有两个比特率相位。在仲裁阶段,经典CAN和CAN FD一样,比特率被限制为1 Mbit / s;在数据阶段,由于只有一个节点正在传输,因此可以提高比特率。

二、CAN的特点

1.串行异步通信

        串行和并行的区别就是一次性发送的位数;并行是把字符编码的各位(比特)同时传输,而串行则是将组成字符的各位一个一个地发往线路。

        下图显示,上面的一次性可以发出三个Bit,而下面一次性只能发一个Bit。

        异步通信,总线里并没有时钟;这个很好理解区分。举一个代表,SPI是串行同步通信,发送方和接收方共享一个时钟。而CAN里没有时钟,所以是异步。

2.优先仲裁功能

        多个控制模块通过CAN控制器挂到CAN-bus上,形成多主机局部网络;网络通信重要的就是总线的使用权,谁使用总线才可以通信。那么总线总裁是一个很重要的功能,决定着哪个模块拥有总线使用权;必须要有相应的总裁机制。其中CAN的总裁机制十分巧妙,是根据仲裁段的标识符决定接收或屏蔽该报文。

        实现原理:采用逻辑与功能,0&0=0,0&1=0,1&0=0,1&1=1。在仲裁段里连续判断发送的位和采集的位是否一致;一致说明当前时刻是本节点优先级更高,不一致则说明是其他节点优先级高,直接退出争夺总线使用权,等待下次。通过上面的逻辑与功能,可以发现0越多,那么优先级越高。参考下面例子:

节点

总线状态

继续

仲裁

BitA

仲裁Bit9

仲裁

Bit8

仲裁Bit7

仲裁

Bit6

仲裁Bit5

仲裁

Bit4

仲裁Bit3

仲裁Bit2

仲裁Bit1

仲裁Bit0

总线值

0/1

0

0

0

0

0

1

0

1

0

1

1

A

0

B

0

C

1

0

0

0

0

1

D

1

0

0

0

0

0

1

0

1

0

1

1

E

1

0

1

F

1

1

        其中只有节点D获取总线控制权,优先发送节点D,CANID是0x01D。

        第二优先级是节点C,CANID是0x040。

        第三优先级是节点E,CANID是0x100。

        第四优先级是节点F,CANID是0x400。

        所以CANID越小,优先级越大,仲裁级别高。

3.抗干扰能力强

        通过CANH、CANL双线之间的差分信号传递数据,可以有效抵抗电磁干扰。

        简单地说,干扰磁场会改变两根线的电压,但对两根线的作用基本相同,那么两根线的压差就不会变,还是干扰之前的值。

4.可靠检错机制

        这检错校验机制在CAN控制器里实现的,通过分析CAN报文的组成部分,可以看到有一个CRC校验数据,通过CRC值来判定数据在传输过程中有无丢失。下图是标准帧的格式,其中CRC值共占用了15个Bit,校验发送过来的数据。

名字

SOF

CANID

RTR

IDE

R0

DLC

DATA

CRC值

CRC

界定符

ACK值

ACK

界定符

EOF

Bit位

0

1-11

12

13

14

15-18

19-82

83-97

98

99

100

101-107

长度

1

11

1

1

1

4

64

15

1

1

1

7

显隐性

        由以下部分组成,仲裁领域、控制领域、 数据字段、CRC领域、ACK字段;

        如果想要干扰CAN报文,也可以从以下入手;干扰填充错误、位错误、ACK响应错误、界定符错误。本来此时刻是1,干扰设备强行发出0,两者碰撞结局是CAN线上是0,从而达到干扰。不能干扰Data数据域,数据具体是0还是1无从判断,其余都是固定的格式。

        CAN显性超时:当TXD一直是显性(输出逻辑电平0)时,会一直占用CAN总线,导致其他节点无法使用CAN网络。因此收发器要有最大规定时间发出显性。规范要求最多连续发出11个显性位。

5.自动重发机制

        发送的信息遭到破坏后,可自动重发。这里使用了CAN总线应答的机制,CAN的发送是个双向互动过程,发送节点在发送数据的同时会对总线上数据进行回读以及ACK场的判定;接收节点在发送节点发送过程中需及时确认报文正确性并令总线上ACK位置 “显性”,以告知发送节点数据正常接收;

6.自动退出功能

        节点在错误严重的情况下具有自动退出总线的功能;

7.广播机制

        报文不包含源地址或目标地址,仅用标志符来指示功能信息、优先级信息。接收的标识符只要符合设定,都会接收数据。

三、CAN的组成

        CAN全称是控制器局部网络,既是一个通信协议,有物理媒介,也有一些概念名词;例如CAN FD、CANID、收发器等等,很多人都容易搞混淆。就像串口、RS485、RS422之间的关系,初学者都很容易混淆。

        CAN主要有CAN总线CAN收发器CAN控制器三个物理媒介组成。其中,总线和收发器都是肉眼可见的,控制器都是处于芯片内部,属于集成电路,肉眼无法看到罢了。

1.CAN总线

        CAN总线是一个使用非归零(NRZ)编码的两线制差分总线,由两根双绞线组成而成。

1.1.显隐性

        CAN总线是根据差分电压来传递数据的;这符合大多数串口通信。其中两根线分别是CAN H、CAN L,其中正常情况下CAN H的电压有2.5V、4V两种情况;CAN L有2.5V、1.5V两种情况。

        但CAN总线只有两种状态:显性、隐性。

      个人脑补理解:显性是指总线处于被控制状态,隐性是指总线处于空闲状态,这个跟1==True、0==False一样的理解。控制状态下需要设置两根线有两个电压水平,消耗更多能量;而隐性状态下只需要让两根线保持一个电压即可,消耗能量较少;因为消耗更多能量肯定不是常有现象,所以默认状态设置为隐性。

        显性是控制状态,隐性是空闲状态,又是怎么和逻辑0、1关联上呢?常理上都认为1代表控制,0代表空闲。这里用到了上面仲裁的原理,0和1之间的优先级,0比1优先级更高,那么0就代表着控制,1就代表了空闲。

        显性--控制状态--有压差--能量高--优先级高--逻辑0

        隐性--空闲状态--无压差--能量低--优先级低--逻辑1

状态隐性状态显性状态
CAN H电压2.5V3.5V
CAN L电压2.5V1.5V
差分电压0V2.5V
逻辑数值10

        排查问题时可以用示波器查看CANH、CANL之间的压差,无数据压差为0,有数据压差2.5V左右。

1.2.波特率

        串口通信的属性之一,双方约定好发送数据的速度,才能及时有效地接收数据。

        CAN的波特率常用500Kbit/s,即一秒发送500*1000个Bit,那么一个Bit就用2us,这个2us的时间就是发送接收一个位的时间,简称位时间。不同的波特率就有不同的位时间。

1.3.采样率

        当发送方在一个位时间里发送了Bit1,那么接收方什么时候接收1,也就是采集这个电压?是在2us里的前半部分还是后半部分?这就涉及到了采样率。

        一个位时间又分成四部分:同步段(SS)、传播时间段(PTS)、相位缓冲段 1(PBS1)、相位缓冲段 2(PBS2)。采样率计算公式= ( 1 + PBS1) / (1 + PBS1+ PBS2)。

2.CAN收发器

        CAN收发器是什么?为什么会有这个东西?

        下图是一个CAN收发器的原理图,右边连接着外部的CAN总线;分别是CANH、CANL。左边连接着CAN控制器。承担着转换信号的作用,把接收过来的差分信号转成单端信号,并通过CAN RX线路传给CAN控制器。反之亦然。

        个人脑补:收发器负责处理(Tx、Rx)逻辑数和总线电压(CANH、CANL)之间的转换。将总线的显性状态转成0、隐性状态转换为1。

2.1.TJA1145

        在收发器里,使用较多的就是TJA1145,具有CAN局部唤醒功能。大白话就是可以被指定的帧唤醒。

        硬件功能:具有本地Wake唤醒引脚、具有INH输出引脚、具有SPI通信通道、常规的CANH和CANL。INH:由TJA1145输出,可以控制主芯片电源。SPI:负责主芯片和TJA1145通信,主要用途由主芯片轮询控制TJA1145状态、TJA1145反馈唤醒状态。

        主要配置:怎么让TJA1145进入休眠状态、怎么唤醒TJA1145。

唤醒方式有本地唤醒、CAN唤醒。本地唤醒包括上升沿、下降沿触发;CAN唤醒有两种,一个是无差别唤醒,只要是CAN帧就会唤醒;一个是局域网唤醒,只能是指定内容的帧才能唤醒。其中局域网唤醒功能需要使能,默认是无差别唤醒。

2.2.进入休眠模式

        TJA1145想要进入休眠模式必须至少要有一个唤醒事件,要么有CAN唤醒,要么有本地唤醒。如果没有这两个,那么是无法正常进入休眠模式的。下面是进入休眠模式的条件:

  • 至少一个常规唤醒事件
  • 当前无唤醒事件
  • 事件状态位全部清除

注:所以事件寄存器都是可读可写;写0无效,写1清除,读是正常读;

2.3.特定帧唤醒

        想实现特定帧唤醒,首先正确配置好要唤醒的特定帧,其次能正常进入休眠模式下。而配置唤醒帧的步骤如下:

  • 使能常规唤醒里的CAN wake-up:CWE = 1
  • 使能Can选择性唤醒功能CPNC=1
  • 配置Can特定帧的格式:例如ID、DLC和Data。
  • 配置正确参数标志位:PNCOK=1

2.4.注意事项

        可以屏蔽非预期的CAN FD帧唤醒

        写寄存器的时候需要解锁、上锁

        Vcc、Vio欠压会让TJA1145强制休眠

        策略如下:

  •                 清除所有捕捉事件;
  •                 使能CAN唤醒和本地唤醒;
  •                 关闭局域网唤醒功能,为了立即被唤醒;
  •                 局域网配置位清除;

3.CAN控制器

        上面提到的Inter制作了82526控制器和Philips 半导体推出了82C200控制器,这些就是CAN的控制器,本质上是由与或非等电路组成的集成电路。同时也在滤波上延申出两个方向,那就是Basic CAN、Full CAN,这个后面再做解释。

        CAN控制器里有很多的寄存器,包括状态寄存器、波特率寄存器、发送使能寄存器等等,这里面就包含了我们平常听到的名词。在介绍CAN控制器之前,先介绍下芯片里常见的IP概念。

3.1.M_CAN IP

        芯片IP 核(Intellectual Property):是具有知识产权核的集成电路芯核的总称,是芯片设计环节中逐步分离出来的经过反复验证过的、具有特定功能的、可以重复使用的、包含特定核心元素的(指令集、功能描述、代码等)集成电路设计宏模块(逻辑或功能单元),可以理解为部分可重复使用的“芯片设计模块”,如 AHB、APB、CAN、SPI、I2C、MIPI、USB、UART内核等,其作用就是在芯片设计环节中降低冗余设计成本,降低错误发生的风险,提高芯片设计效率。根据不同的IP内核,可以实现不同的CAN功能;当前使用比较多的CAN IP内核就是M_CAN。

        这个是由博世开发的一个IP核,博世CAN IP可以作为一个独立的CAN控制器,可集成于ASIC或FPGA芯片内部。它支持经典的CAN和CAN FD(具有灵活数据速率)。符合ISO11898-1:2015标准。需要额外的收发器硬件来连接到CAN物理层。报文可存储于模块外部单口或双口RAM,它通过通用主接口与M_CAN相连。根据所选择的集成方式,多个M_CAN控制器可以共享同一个报文RAM,主机CPU通过32位通用接口连接;下面是M_CAN IP的特点。

  • 支持符合ISO 11898-1:2015标准的经典CAN和CAN FD
  • 最长支持64字节的有效数据,可以更快地传输大数据字段
  • Support as CAN FD Light Commander:
  • Standardization published in CiA 604-1: CAN FD Light Protocol for responder nodes
  • > More information about CAN FD Light
  • 多个M_CAN模块可以访问一个共享存储器
  • 可连接到8/16/32位通用CPU接口的客户特定主机CPU上
  • 比特率最高支持8 Mbit/s,取决于应用和使用的收发器
  • 使用17/21位CRC(CAN FD)或15位CRC(CAN)进行安全通信
  • M_TTCAN还支持符合ISO 11898-4的时间触发CAN的实时应用。

3.2.TI_MCAN

        TI的280039C和英飞凌的TriCore377这两款芯片都是基于博世的MCAN IP进行开发的,所以这两款芯片上关于MCAN操作基本都是一致的,在芯片手册里的介绍布局都差不多,具体可以参考芯片手册(官网直接下载),主要介绍了操作模式、接收处理、发送处理、FIFO通知处理、Message RAM处理。后面的介绍是TI基于M_CAN内核开发的MCAN。

        MCAN模块的内部组成有:CAN核心、消息处理、模块接口、RAM接口、RAM内存。

        输入部分有:两个时钟、时钟请求停止位、复位请求位、中断请求、CPU总线。

        输出部分有:Rx、Tx。

CAN核心:CAN核心由CAN协议控制器和Rx/Tx移位寄存器组成。它处理所有的ISO 11898-1:2015协议功能,并支持11位和29位标识符。

Message Handler:消息处理是一个状态机,控制着移位寄存器和RAM之间的数据传输;处理接收过滤功能和生成中断。

Register and Message Object Access:寄存器和消息对象访问,通过对消息对象的间接访问来提供数据一致性。

Message RAM:属于内存的一部分,是TI官方给MCAN配置的专属内存区域,主要存放接收来的数据和将要发送的数据。数据具有安全保密性,所以用户无法直接对此RAM区域进行操作。

注:此块RAM区域也可以当作普通RAM给用户使用。

RAM Interface:RAM的对外接口,用户只能通过此接口才读取RAM数据或者写入RAM数据。

模块接口:用户的软件可以通过一个32位外围总线接口访问MCAN模块的寄存器。

扩展接口:所有选定的内部状态和控制信号都被路由到这个接口。

Tx、RX:外接CAN收发器。

Interrupt:MCAN模块向中断控制器请求中断接口。

CLK:为MCAN模块提供两个时钟:外设同步时钟(CAN_ICLK)和外设异步时钟(MCAN_FCLK)。

CLK STOP:请求时钟停止恢复位,让MCAN处于休眠、工作状态等。

3.3.主要功能

  • 支持CANFD,最多64个字节
  • 专用发送缓冲区,最多32个
  • 可配置发送FIFO,最多32个元素
  • 可配置发送队列,最多32个元素
  • 可配置发送事件FIFO,最多32个元素
  • 最多64个专用接收区缓冲区
  • 两个可配置的接收FIFO,每个最多有64个元素
  • 最多有128个过滤器
  • 回环、中断、ECC、时钟停止与唤醒支持
  • 时间戳计数器

        通过上面介绍,MCAN模块的RAM内存很重要,是实现功能的主要载体。MCAN的内存大小是2048KByte,用于存放过滤器、Rx Buff、Rx FIFO0\1、TxBuff、TxEventFIFO。好奇的是为什么过滤器非要放在RAM里,而不是做成寄存器?这样不是更容易理解过滤器吗。

        过滤器:可以接收指定标识符数据,并存放在相应区域。        

        RxBuff,如果过滤器的配置是存放在Rx Buff里,那么New Data寄存器里就会有相应的位置一,可以在中断或者轮询检查。

        RxFIFO,如果过滤器的配置是存放在Rx FIFO里,同样检查FIFO Level,判断是否小于水印值来读取数据。FIFO当数据写满的时候,有覆盖、停止写入两种处理。

        发送事件FIFO,这个存放发送后证明数据,用于发送确认功能。

        TxBuff,可以配置发送的格式:CAN FD还是经典CAN、速率是否可变、是否存储TxEvent、消息标志等等。发送缓冲区的数量是在TXBC里进行配置,后面直接根据发送缓冲区的下标进行使用;当往发送缓冲区的RAM里写好了数据,需要请求发送位置一。每次都是往RAM里写数据,所以写的数据可以是任何,那么一个缓冲区可以发送多次使用、发送多个不用ID数据。

        TxFIFO和TxQueue不经常用,暂时略过。

3.4.过滤器

        RAM的第一个内容就是过滤器,当接收到一帧报文的时候,控制器就会在过滤器的内存上寻址,只要找到符合条件的过滤器,就会把数据存放在过滤器要求的位置里。接收过滤器可以有1-128个,每个过滤器都有三种过滤方案:范围过滤、特殊ID过滤、经典位过滤,可以把数据存放在专属缓存区或者FIFO0、1里面。所以自由度很高,可以配合使用满足需求。

        过滤器由四个部分组成,分别是SFT、SFEC、SFID1、SFID2。SFT指定过滤方式,SFEC指定存储位置。SFID1、2就是Filter ID1、2,但是这两个在不同的过滤、存储配置下,代表了不同的意思。

        如果配置数据存放在Rx Buff,过滤方式则无效,系统默认选择经典过滤,ID1就是必须匹配的标识符,没有掩码可以使用。SFID2的前五位Bit是存放专属缓存区的偏移量,也就是Rx Buff的下标。配置数据:SFEC=0x7;SFID1=过滤ID;SFID2=RxBuffIndex;然后将这个过滤器写进RAM里,写进RAM的位置下标(StdFilterIndex)建议跟RxBuffIndex一致,

        如果存放在FIFO里,三种过滤方式都支持,SFID1、2都是过滤ID。

         如何配置?参考下图:

        过滤器0是经典过滤,它接收的数据存放在RxBuff0里,因为SFID2指定存放在下标为0的RxBuff里。

        过滤器1也是如此,数据存放在RxBuff1里,SFID2指定存放在下标为1。

        过滤器2是接收FilterID1到FilterID2之间的ID,并存放在FIFO0里。

        过滤器3是接收FilterID1和Filter2两个ID,并存放在FIFO1里。

        过滤器4是拒绝FilterID1到FilterID2之间的ID。

3.5.发送事件

        当发送一帧报文后,需要给上层发送CanIf_Comfirmation,因此需要用到发送存储事件。按照之前的控制器,都是有发送成功中断的,在中断里进行处理,但增大了中断使用率。现在的MCAN控制器每当成功发送一帧后,可以自主选择是否存放发送事件FIFO里,然后再轮询里读取发送成功的数据,再进行相应的处理。

        上面提到这个存放TxEventFIFO里是可以配置的,在Tx Buff Element里的EFC置1则存储。同时存放的数据也很多,包含标识符ID、时间戳、消息标志(MM)等等。具体数据参数芯片手册里的介绍。

        从TxEventFIFO里读出数据后,需要把读出来的GetIndex写入Acknowledge寄存器里。

3.6.中断

        MCAN本身有很多的中断源,一共有30个。这30个中断共用两跟中断线,中断线连接着中断处理器。

        中断信号有很多,主要有BusOff中断、Rx Buff接收到新数据中断、Rx FIFO接收到新数据中断、Rx FIFO到达水印中断、Rx FIFO满中断、Tx Buff发送成功中断、Tx Buff取消发送成功中断、TxEventFIFO有新数据接收、TxEventFIFO到达水印、TxEventFIFO满中断。

        其中发送成功中断(TC)需要使能TxBTIE里的位,可以使能32个Buff里的任意。

四、CAN的开发

        此部分参考Specification of CAN Driver AUTOSAR Release 4.2.2版本,学习CAN的规范设计,掌握稳定的底层架构。 开发不仅涉及到CAN控制器的配置,也涉及到如何实时有效处理各种事件;中断处理、溢出处理、超时处理、状态处理等等。

        路线:

        1、研究4.2.2的规范文档,明白CAN的数据类型、接口名称、与其他模块的关联调度、错误处理、CanConfig架构;

        2、使用EB配置CAN;

        3、研究CAN代码;

1.名词介绍

缩写描述
CAN Hardware Unit一个CAN硬件单元可以由一个或多个CAN控制器组成
CAN Controller

一个CAN控制器只服务于一个物理通道

CAN Hardware Object一个CAN硬件对象可以理解为一个PDU缓存区,PDU缓存区位于CAN硬件单元的RAM区
HOH

Hardware Object Handle

硬件对象句柄:硬件发送句柄+硬件接收句柄

HTH

Hardware Transmit Handle

硬件发送句柄,包含一个或多个CAN Object

HRH

Hardware Receive Handle

硬件接收句柄,仅包含一个CAN Object

CAN L-PDU
Can Protocol Data Unit
协议数据单元,包含一个标识符ID、一个DLC、一个数据SUD,此部分只针对CanDriver。
CAN L-SDU

CAN Service Data Unit。

是L-PDU发送里的数据。这个只针对CAN IF的上层。

        有一说一,这些概念是很难搞懂的,需要慢慢理解。首先CAN Controller很容易理解,对应着一个物理通道,也就是一个TX和RX组成的节点。我们都知道CAN控制器里有RAM内存,用于存放发送、接收的CAN ID、DLC、Data三个数据。在不同的架构对这些RAM有着不同的处理,像Basic CAN就是把多个RAM集中在一起管理,同时用于发送或接收。而Full CAN是管理单个RAM,专门用于接收或者发送。管理一个RAM和多个RAM有以下区别:

        多个RAM可以接收多个任意的ID报文,可以都一样,也可以都不一样。但是接收了第一个报文之后,不能立即做出处理,要等多个RAM都接收到才行;所以处理速度慢。但是可以接收多个相同ID的报文,具有缓冲作用!

        单个RAM只要接收指定ID报文,就可以立即做出动作,处理速度快。只能接收一次数据,没有缓冲区作用。

        上面单个RAM存放一个ID、一个DLC、一个Data,官方称之为L-PDU。对于接收,一个L-PDU就是一个HRH;对于发送,一个或多个L-PDU是一个HTH。HRH+HTH为Hardware Object,是由多个L-PDU组成的。

        硬件对象除了ID、DLC、SDU三个数据,还有其他的配置参数;例如CanHandleType、CanIdType、CanObjectId、CanObjectType、CanHwFilter等等。这几个有些是配置寄存器的参数,有的是为了方便管理的ObjectId概念。共同组成了CAN Driver里的最小单元!

2.功能规范

        CAN模块应该使用OScounter计数,防止硬件不会在预期的时间内做出反应(硬件故障),以防止无穷无尽的循环。同时CAN模块的上锁时间要小于主函数周期。超时处理方法:定义一个变量,获取当前OSCounter1;判断处理时刻的OSCounter2是否超过OSCounter1+设定值。

        Can模块有一个非常简单的状态机,有两个状态:CAN_UNINIT和CAN_READY;

        CAN控制器有四种状态:Uninit、Stopped、Start、Sleep。

        CAN模块要有几个必要的接口,CAN_Init、CAN_SetBaudrate等等

        CAN模块的状态被两个外部事件改变:Busoff、WakeUp。这些事件通过中断或通过在Can_MainFunction_BusOff或Can_MainFunction_Wakeup中轮询的状态位来表示。

        CAN的状态机跳转条件:默认Stopped

        支持CAN  FD。

        

3.API接口

        API的接口名称都是固定不变的,但是里面的实现方法都是根据具体的CAN控制器开发的;这个也是MCAL的优势,方便平台移植。那具体的实现代码大多数都是工具生成,但是也要能看懂才行。下面列举了规范里所要求的接口函数。

3.1.Can_Init()

        包含全局初始化、内核初始化;全局初始化里实现CAN控制器外部之间的功能初始化,包括时钟、中断!内核初始化实现CAN的全局变量初始化、轮询CAN控制器初始化。CAN控制器初始化包括中断线选择、进入初始化模式、设置配置改变使能、设置波特率、设置CAN ID Filer、设置RxMsgObj的参数(FIFO的水印等)、设置TxEvent参数、BusOff处理模式、设置CAN停止模式、设置CAN全局状态。

3.2.Can_DeInit()

        反初始化

3.3.Can_SetBaudrate()

        设置波特率

3.4.Can_CheckBaudrate()

        改变波特率

3.5.Can_SetControllerMode()

        设置CAN控制器状态,在Uninit、Stopped、Start、Sleep跳转。如果控制器不支持Sleep模式,就直接Stopped。

3.6.Can_SetIcomConfiguration()

        公共配置参数

3.7.Can_GetVersionInfo()

        获取版本信息

3.8.Can_EnableControllerInterrupts()

        直接使能中断使能寄存器里响应的位,这个使能无关CAN寄存器是否初始化、全局中断是否开启、CAN中断线是否使能。大多数使能BusOff Interrupt、TxEvent Interrupt、DedicatedBuffs Interrupt、FIFO0Watermark Interrupt、FIFOFull Interrupt。

3.9.Can_DisableControllerInterrupts()

        禁止中断

3.10.Can_CheckWakeup()

        检查唤醒

3.11.Can_Write()

        函数里主要判断状态、获取控制器下标、HTH下标等等;内联一个发送Object函数,它主要操作发送具体的数据和功能;根据配置参数选择CAN FD、是否产生TxEvent、数据长度、数据帧的格式、记录MassageMarker、请求发送位。

3.12.Can_MainFunction_Write()

        判断是否是Polling,处理发送事件,读取Event的MM、Get Index;写入Acknowledge,并引用CanIf_TxConfirmation。

3.13.Can_MainFunction_Read()

        判断是否是Polling,轮询模式下,一直读取FIFO的Fill Level、NewData位。如果有数据,读取出来,并引用CanIf_RxIndication()。

3.14.Can_MainFunction_BusOff()

        判断是否是Polling,检查CAN是否处于BusOff状态,是即取消所有发送请求位,设置CAN状态为Stopped,并引用CanIf_ControllerBusOff()。

3.15.Can_MainFunction_Wakeup()

        检查是否支持Wakeup功能,获取CAN数据,判断是否有唤醒报文,有则上传CanIf。

        这里的休眠是指功能的休眠,并非掉电休眠,整个芯片还是在电工作的。

3.16.Can_MainFunction_Mode()

        掌管CAN的模式、状态机跳转。Uninit、Stopped、Start、Sleep。动不动就Stopped

下面是非标准的函数,但是建议有,便于理解

3.17.Can_IsrBusOffHandler()

        BusOff中断服务函数,被CAN的总中断服务函数引用。Bus Off触发的中断,读取中断状态寄存器里的BO位进行数据处理。引用CanIf_ControllerBusOff()。

3.18.Can_IsrReveiveHandler()

        接收专属缓冲区的中断服务函数,被CAN的总中断服务函数引用。专属Buff接收到数据触发的中断,根据New Data进行处理数据

3.19.Can_IsrRxFIFOHandler()

        FIFO的中断服务函数,被CAN的总中断服务函数引用。FIFO状态到达水印或者溢出触发的中断,也可以是FIFO进入新数据触发中断。

3.20.Can_IsrTransmitHandler()

        发送处理中断服务函数,被CAN的总中断服务函数引用。可以是发送成功触发的中断,也可以是发送事件的中断。发送事件需要将读取的GetIndex写入Acknowledge。

4.EB配置

        CAN配置分为常规配置、参数配置两部分,常规配置都是一些属性类的参数;参数配置包含了CanController配置和CanHardwareObject配置。通过上面的概念可以很轻松地理解这两个!

        CanController配置包含了接收、发送、BusOff中断还是轮询的处理方式、寄存器基地址、波特率设置和唤醒功能。

        CanHardwareObject包含了处理类型(Full、Basic)、Object类型(发送、接收)、CanId类型(标准、扩展)、HwFilter(过滤ID、Mask)、隶属哪个控制器。

4.1.CanGeneral

        常规配置:这部分主要是错误检查、主函数的周期、超时时间配置,具体看下图!

4.2.CanController

        CanController的配置参数不是很多,其中CanControllerId是控制器下标,当有多个控制器时,使用下标来区分;CanControllerBaseAddress是MCMCAN模块的起始地址;CanControllerBaudrateConfig这个参数决定着CanController波特率,并且也决定着是否使能CAN FD的功能。

CanControllerBaudrateConfig:有General、CanControllerFdBaudrateConfig组成。前者决定经典CAN的波特率;后者决定CANFD的波特率,设置参数即按照参数使能FD、配置波特率,不设置参数即关闭FD。

4.3.CanHardwareObject

        这个是重中之重,CanHardwareObject里主要看General、CanHwFilter两部分。

        CanHandleType:设置处理方式,是Full还是Basic。CanObjectType:是发送还是接收。CanIdType:标准帧还是扩展帧。ObjectIdType:是区分多个Object的下标,很重要。CanControllerRef:是指当前Object隶属哪个控制器。

        CanHwObjectCount:用于实现一个HOH的硬件对象数量。在HRH的情况下,这个参数定义了硬件FIFO中的元素数量或阴影缓冲区的数量,在HTH的情况下,它定义了用于多路传输或用于FullCAN HTH的硬件FIFO的硬件对象数量。

        CanHwFIFOThreshold:basic处理方式下接收FIFO触发中断的水印值。

        CanHwFliter:硬件过滤,有Code和Mask两部分组成;用于过滤CANID。

5.代码架构

        EB生成的代码粗涩难懂,全是结构体指针入参,很多的宏定义开关,变量过多,又要支持多核操作(给每个内核申请数组,存放数据),太难看了。其中结构体配置参数是总结了EB里的所有配置,哎,也不是很好看,下面是我自己手写的精简版代码,概括了EB配置的选项。

        CanConfig:包含了CanController、CanHardwareObject、HOHConfig三个指针。HOHConfig包含了发送、接收Object的个数和下标。

        下图是官方Autosar给的配置参数大纲图:大体上跟EB上一致;后面的每个配置请参考官方文档,写的很详细。

五、CAN的使用

        CAN的应用有很多,涉及在汽车、医疗、工业等等;根本还是在8个、64个字节处理数据,处理多了就会诞生不少标准协议,例如汽车领域的诊断、标定功能;

1.XCP

        XCP是一种标定的协议,这里介绍是基于XCP调试的方法。

        最近经常遇到程序卡住、死机的现象,又因为控制器已经装车了,导致无法使用调试器在线调试,无法快速分析问题。所以就想着另辟蹊径,能不能通过CAN线路来调试CPU及其寄存器。这样就可以实时定位程序,知道程序如何工作的;同时也可以监控其他系统数据,十分方便快捷。

        在网上查到可以使用VX1000设备,基于XCP协议对芯片调试。这种解决方案需要在硬件上嵌入一个POD芯片;通过这个POD芯片把数据上传给VX1000设备,再传递给PC端。似乎可行,又似乎多此一举。因为POD芯片也是需要接口才能连接上VX1000的,既然都增加了一个接口,这个接口直接是仿真调试口又如何?

        当前大多数的控制器只有两路CAN对外通信,分别是整车CAN、标定CAN。标定CAN使用率没有整车CAN高,所以可以基于标定CAN对外上传CPU等信息。

        这种方法算是伪debug,因为只能按照协议来查看变量、修改变量,没有其他在线调试的功能。所以这个的必要性有待商榷,算是个可行的方法。

2.UDS诊断

        这个内容算是入门知识了,UDS诊断功能挺简单的,根据协议来发送读取报文数据。

3.私有协议

        每个人都可以在8个字节上做一些协议处理,双方约定好即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值