航顺芯片HK32F103系列是一款功能强大的32bit MCU,内部集成多个通信模块,其中CAN模块支持CAN协议2.0A和2.0B。目前广泛应用的是CAN 2.0B协议,其收发数据速度高达1Mbps,有两种不同长度的ID标识符,一种是11位的,一种是29位的。该CAN协议的主要特点为: (1) 多主控制: 在总线空闲时,所有的单元都可开始发送消息。 (2) 消息的发送: 在 CAN 协议中,所有的消息都以固定的格式发送。总线空闲时,所有与总线相连的单元都可以开始发送新消息。两个以上的单元同时开始发送消息时,根据标识符( Identifier 以下称为 ID)决定优先级。 ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息ID的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。即多个单元同时开始发送时,发送高优先级 ID 消息的单元可获得发送权。 (3) 系统的柔软性: 与总线相连的CAN节点没有类似于“地址”的信息。因此在总线上增加CAN节点时,连接在总线上的其它CAN节点的软硬件及应用层都不需要改变。 (4) 通信速度: 根据整个网络的规模,可设定适合的通信速度。在同一网络中,所有CAN节点必须设定成统一的通信速度。即使有一个CAN节点的通信速度与其它的不一样,此CAN节点也会输出错误信号,妨碍整个网络的通信。不同网络间则可以有不同的通信速度。 (5) 远程数据请求: 可通过发送“遥控帧” 请求其他CAN节点发送数据。 (6) 错误检测功能·错误通知功能·错误恢复功能: 所有的CAN节点都可以检测错误(错误检测功能)。 检测出错误的CAN节点会立即同时通知其他所有CAN节点(错误通知功能)。 正在发送消息的CAN节点一旦检测出错误,会强制结束当前的发送。强制结束发送的CAN 节点会不断反复重新发送此消息直到成功发送为止(错误恢复功能)。 (7) 故障封闭: CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的CAN节点从总线上隔离出去。 (8) 位填充: CAN通信的同步信息包含于传输数据中,电平的跳转提供了同步信息,如果连续多个相同的总线值出现,这将影响到同步信息的提取。为此CAN采用位填充规则,即在一帧中的帧起始,仲裁场,控制场,数据场和CRC场部分( CRC界定符,应答帧和帧结束除外),当发送器检测到5个具有相同数值的连续位时,将自动插入一个补码位。接收节点收到5个连续位后下一位自动删除。 (9) 连接: CAN 总线是可同时连接多个CAN节点的总线。可连接的节点总数理论上是没有限制的。但实际上可连接的节点数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的CAN节点数增加;提高通信速度,则可连接的CAN节点数减少。如下是CAN通信速度和距离对应图: (9) CAN总线物理框架可以抽象为: MCU(微处理器) <--> CAN控制器 <--> CAN收发器 <--> CAN数据传输总线(CAN-H,CAN-L)。如下图示: CAN总线的数据传输线——>两条双向数据线,分为高位﹝CAN-H﹞和低位﹝CAN-L﹞数据线, 为了防止外界电磁波干扰和向外辐射,两条数据线缠绕在一起,要求至少每 2.5cm 就要扭绞一次,两条线上的电位是相反的,电压的和总等于常值。 CAN总线的终端电阻——>防止数据在到达线路终端后象回声一样返回,并因此而干扰原始数据,从而保证了数据的正确传送,终端电阻装在控制单元内。 CAN总线帧类型: 数据帧-Data frame 携带数据从发送节点到接收节点。 分为标准帧(11位标识符)和扩展帧(29位标识符)。 远程帧-Remote frame 向其他节点请求发送具有同一标识符的数据帧, 远程帧也有标准帧和扩展帧两种格式。 例如CAN节点A需要知道CAN节点B的油温温度,CAN节点A发送一个远程帧给节点B,节点B收到该远程帧后发送一个带油温数据的数据帧给节点A。
错误帧-Error frame 节点检测到错误之后发送错误帧。 错误标志: 主动错误标志(000000)和被动错误标志(111111)。 错误界定符:11111111。 过载帧-Overload frame 接收节点通知其尚未做好接收准备, 过载标志(过载标志重叠部分)+过载标志界定符。 以下是关于CAN帧/报文中各个部分的说明: 帧起始:SOF 0,占用1位。当总线空闲时发送,用于CAN总线上的每个节点的信息同步。 仲裁段:ID+RTR ID: 表示数据帧的优先级,先发送高位再发送低位。 11位或29位长度。 RTR(Remote Transmit Request): 0: 表示该CAN帧是数据帧。 1: 表示该CAN帧是远程帧。 控制段:IDE+r0+DLC IDE(IDentifier Extension): 0: 标准格式。 1: 扩展格式。 保留位r0: 0。 保留位r1: 0。 DLC(Data Length Code): 表示数据域中的字节数,范围0~8. 数据段:Data CRC段:CRC Sequence+CRC界定符 CRC polynomial: x15+x14+x10+x8+x7+x4+x3+1 CRC界定符: 1. ACK段:ACK Slot+ACK界定符 接收到匹配CRC序列的节点会在应答位期间,写0在发送器的隐性位作为回应。 ACK界定符: 1. 帧结束:EOF 1111111,表示数据帧或远程帧的结束。 SRR(Substitute Remote Request): 1, 扩展帧中代替RTR位. CAN总线通信机制—报文发送 -载波侦听和带冲突检测协议的多路访问( CSMA/CD) -发送节点:回读; 接收节点:监听 -线与机制: 所有节点发送1,总线上才是1;有一个节点发送0,总线上就是0,即高电平是隐性位,低电平是显性位。 -总线仲裁:如果有两个或两个以上的节点同时向总线上发送数据,标识符小的获得仲裁,标识符大的退出仲裁(回读和线与)。 例如: ID1:00000000010
ID2:00000000001 CAN总线通信机制—报文接收 如果总线上有数据正在发送,所有节点都会接收总线数据,只有通过接收节点的报文过滤规则才能被节点接收进控制器。 CAN的错误状态: 主动错误状态:主动错误状态是可以正常参加总线通信的状态。处于主动错误状态的单元检测出错误时,输出主动错误标志。
被动错误状态: 被动错误状态是易引起错误的状态。 处于被动错误状态的单元检测出错误时,输出被动错误标志。处于被动错误状态的单元即使检测出错误,而其它处于主动错误状态的单元如果没发现错误,整个总线也被认为是没有错误的。
总线关闭状态:总线关闭态是不能参加总线上通信的状态。信息的接收和发送均被禁止。 错误类型: 现在,我们以航顺芯片的HK32F103VET6(LQFP-100)为例来说明CAN通信的驱动实现。HK32F103VET6是航顺芯片的一款功能强大的32位MCU,内部集成CAN控制器,因此进行CAN通信时,只需要外接一个CAN收发器。 由HK32F103芯片的datasheet,如下截图我们得知,CAN的发送引脚为PA12,接收引脚为PA11。 由HK32F103芯片的用户手册,如下截图,得知需要把CAN的发送引脚PA12设置为推挽复用输出,CAN的接收引脚PA11设置为浮空输入或上拉输入。 详细的GPIO配置,依据该芯片的用户手册的表8-1: 因此,软件中对引脚的设置如下: 这里,我们使用TJA1050作为CAN收发器,原理示意图如下: 将CAN_D连接HK32F103VET6芯片的引脚PA12,CAN_R连接HK32F103VET6芯片的引脚PA11,CANL和CANH接外部CAN总线(即前文提到的CAN-L和CAN-H)。 软件驱动方面,首先应该使能CAN模块的时钟,如下: HK32F103VET6芯片CAN模块(后续我们简称其为bxCAN)有3个主要的工作模式:初始化、正常和睡眠模式。在硬件复位后,bxCAN 工作在睡眠模式以节省电能,同时 CANTX 引脚的内部上拉电阻被激活。软件通过对 CAN_MCR 寄存器的INRQ或SLEEP 位置’1’,可以请求 bxCAN 进入初始化或睡眠模式。一旦进入了初始化或睡眠模式,bxCAN 就对 CAN_MSR 寄存器的 INAK 或 SLAK 位置’1’来进行确认,同时内部上拉电阻被禁用。当INAK 和 SLAK 位都为’0’时,bxCAN 就处于正常模式。在进入正常模式前,bxCAN 必须跟 CAN 总线取得同步;为取得同步,bxCAN 要等待 CAN 总线达到空闲状态,即在 CANRX 引脚上监测到 11 个连续的隐性位。 因此我们需要把CAN模块设置为初始化模式,如下: 在初始化模式设置成功之后,根据具体应用的要求,设置自动离线(Bus-Off)管理、自动唤醒模式、是否禁止报文自动重传、接收FIFO锁定模式、发送 FIFO 优先级等,如下示例: CAN通信过程中,很重要的一点是设置通信速率,bxCAN的通信速率设置依据HK32F103VET6用户手册中的: 我们现在要设置500Kbps的通信速度,那么需要设置APB时钟频率为36MHz,还需要设置位BRP=3,TS1=8,TS2=7,如下: 至此,CAN初始化中几个重要特性已经设置好,可以把CAN模块设置位正常模式,以便正常地发送报文。从初始化模式切换为正常模式的设置,如下: 报文的发送,其核心在于正确操作CAN_TIxR、CAN_TDTxR、CAN_TDLxR、CAN_TDHxR寄存器,如下为例,发送标准格式的ID=0x12的8字节长度的CAN数据帧报文。 并通过对应的状态寄存器检查发送成功与否: 某个CAN节点要接收哪些CAN报文,由其CAN接收规则(或者称为接收过滤器)设定。在接收到有效的报文之前,应该先设置好其接收规则。为此,HK32F103VET6的bxCAN 控制器为应用程序提供了 14 个位宽可变的、可配置的过滤器组(13~0),以便只接收那些软件需要的报文。硬件过滤的做法节省了 CPU 开销,否则就必须由软件过滤从而占用很大的 CPU开销。每个过滤器组x由2个32位寄存器,CAN_FiR1和CAN_FiR2【(CAN_FiRx) (i=0..13; x=1..2)】,组成。 每个过滤器组的位宽都可以独立配置,以满足应用程序的不同需求。根据位宽的不同,每个过滤器组可提供: • 1 个 32 位过滤器,包括:STDID[10:0]、EXTID[17:0]、IDE 和 RTR 位 • 2 个 16 位过滤器,包括:STDID[10:0]、IDE、RTR 和 EXTID[17:15]位 此外过滤器可配置为,屏蔽位模式和标识符列表模式。 在屏蔽位模式下,标识符寄存器和屏蔽寄存器一起,指定报文标识符的任何一位,应该按照“必须匹配”或“不用关心”处理。 在标识符列表模式下,屏蔽寄存器也被当作标识符寄存器用。因此,不是采用一个标识符加一个屏蔽位的方式,而是使用 2 个标识符寄存器。接收报文标识符的每一位都必须跟过滤器标识符相同。 过滤器组可以通过相应的 CAN_FM1R 寄存器配置。在配置一个过滤器组前,必须通过清除 CAN_FAR寄存器的 FACT 位,把它设置为禁用状态。通过设置 CAN_FS1R 的相应 FSCx 位,可以配置一个过滤器组的位宽,请参见下图。通过 CAN_FM1R 的 FBMx 位,可以配置对应的屏蔽/标识符寄存器的标识符列表模式或屏蔽位模式。 我们以常用的一个32位过滤器+标识符屏蔽的方式为例进行说明。 如上图,“映像”行中,RTR对应CAN_FiRx的bit1,IDE对应CAN_FiRx的bit2,EXID对应CAN_FiRx的bit3-bit20,STID对应CAN_FiRx的bit21-bit31。结合前文仲裁段和控制段所述,RTR为0时表示该CAN帧是数据帧,为1时表示该CAN帧是远程帧;IDE为0时表示该CAN帧是标准格式,为1时表示该CAN帧是扩展格式。标准格式下只用到STID位,扩展格式下还会用到EXID位。在32位过滤器+标识符屏蔽的方式应用中,“ID”行中,即CAN_FiR1寄存器用于设置CAN报文的ID、IDE、RTR。“屏蔽”行中,即CAN_FiR2寄存器用于设置接收报文过程中,是否比较ID、IDE、RTR这些对应的各个位,为0时表示“不用关心”,为1时表示“必须匹配”。以RTR为例,当设置CAN_FiR2的RTR为1“必须匹配”,且CAN_FiR1时RTR为0时,表示只接收数据帧,不接收远程帧;而当设置CAN_FiR2的RTR为0时“不用关心”,表示无论是数据帧还是远程帧,都会进行接收。 下面,我们开始说明过滤器的具体设置。 首先应该设置过滤器组工作在初始化模式并暂时禁用过滤器,如下: 接着设置过滤器的位宽是单个32位,及工作在标识符屏蔽位模式下,如下: 假设我们现在只需要接收两条CAN标准数据帧,且其ID分别为00000000000和00000000001,那么应该设置IDE为0,RTR为0,CAN_FiR1为0,CAN_FiR2为0xFFC00006,如下: 接着设置接收到的报文存放于哪个FIFO,这里我们存放到FIFO 0,如下: 最后重新激活过滤器和设置过滤器工作在正常模式: 现在,该CAN节点就可以接收CAN ID分别为00000000000和00000000001的标准数据帧,收到后CAN报文是存储于FIFO 0中,CPU从FIFO 0 中读取数据,供上层应用使用。
|