本帖最后由 FPGA课程 于 2024-9-26 09:56 编辑
软件版本:VIVADO2021.1
操作系统:WIN10 64bit
硬件平台:适用 XILINX A7/K7/Z7/ZU/KU 系列 FPGA
实验平台:米联客-MLK-H3-CZ08-7100开发板
板卡获取平台:https://milianke.tmall.com/
登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑!
1概述
ZYNQ的PS中包含了2个CAN接口,兼容CAN 2.0A和CAN 2.0B,最高可支持1Mbps的波特率。CAN作为工业应用中的一个重要的总线标准,广泛应用于各行各业之中。本教程介绍了ZYNQ中PS端CAN接口的基本使用方法。 实验目的: 1:熟悉CAN总线协议 2:通过阅读ug585(ZYNQ) , ug1085 (MPSOC),熟悉ZYNQ CAN控制器的硬件资源 3:通过VITIS-SDK 实现CAN的收发测试程序 4:利用CAN分析仪以及配套的软件工具实现CAN协议的收发测试 5:能够修改不同的波特率进行CAN总线通信 2系统框图
3CAN总线介绍
3.1CAN的电气特性CAN总线采用差分驱动,CAN总线空闲或者默认状态输出隐性电平1,如下图所示,输出1的情况下, Vcan_H相比于中间电平,只是略高,Vcan_L比中间电平略低。当输出0的时候,Vcan_L远高于中间电平,而Vcan_H远低于中间电平。
3.2数据格式CAN总线中的数据以帧为单位,一共包含5种类型的帧,分别为:数据帧、远程帧、错误帧、过载帧和帧间隔。
- 数据帧:用于发送节点向接收节点传送数据的帧。
- 远程帧:用于接收节点向具有相同ID的发送节点请求数据的帧。
- 错误帧:用于当检测出错误时向其他节点通知错误的帧。
- 过载帧:用于接收节点通知其尚未做好接受准备的帧。
- 帧间隔:用于将数据帧及远程帧与前面的帧分离开来。
CAN帧格式如下图所示,CAN 2.0A中使用的是标准帧,CAN 2.0B中使用的是扩展帧。标准帧和扩展帧的区别在于扩展帧增加了18bit的扩展标识符。一般情况下,与用户直接相关的只有数据帧和远程帧。数据帧和远程帧都可以使用标准帧格式或者扩展帧格式。
以上对关键的概念解释如下: SOF代表CAN的起始位,显性显示0 RTR的全称为“远程发送请求(Remote TransmissionRequest)”,数据帧中位显性0,远程帧中位隐性1 IDE (Identifier Extension,标志符扩展)位如果是显性0代表是标准帧,否则隐性1代表是扩展帧。 SRR替代远程请求(Substitute Remote Request,SRR)位为隐性1 R0,R1保留位 DLC,数据长度最大8 数据域,最大64bits CRC校验 15 bits CRC分隔符1bit ACK 2 bits EOF 7 bits 3.3数据帧 一个数据帧由7个不同的部分组成,分别为:帧起始、仲裁段、控制段、数据段、 CRC段、ACK应答段、帧结尾。如下图所示。
1:帧起始和结尾帧起始和帧结尾说明如下图所示。 帧起始和帧结束用于界定一个数据帧,无论是标准数据帧或扩展数据帧都包含这两个段。
2:仲裁段仲裁段说明如下图所示。 CAN-bus是如何解决多个节点同时发送数据,即总线竞争的问题?该问题由仲裁段给出答案。
3:控制段控制段说明如下图所示。 控制段共6位,标准帧的控制段由扩展帧标志位IDE、保留位r0和数据长度代码DLC组成;扩展帧控制段则由IDE、r1、r0和DLC组成。
4:数据段数据段说明如下图所示。 一个数据帧传输的数据量为0~8个字节,这种短帧结构使得CAN-bus实时性很高,非常适合汽车和工控应用场合。
5:CRC段CRC段说明如下图所示。 CAN-bus使用CRC校验进行数据检错,CRC校验值存放于CRC段。CRC校验段由15位CRC值和1位CRC界定符构成。
6:ACK段ACK段说明如下图所示。 当一个接收节点接收的帧起始到CRC段之间的内容没发生错误时,它将在ACK段发送一个显性电平。
3.4远程帧远程帧结构如下图所示。与数据帧相比只缺少了数据段。 与数据帧相比,远程帧结构上无数据段,由6个段组成,同理分为标准格式和扩展格式,且RTR位为1(隐性电平)。
3.5数据帧与远程帧对比数据帧与远程帧的对比如下图所示。 比较内容 | 数据帧 | 远程帧 | ID | 发送节点的ID | 被请求发送节点的ID | SRR | 0(显性电平) | 1(隐性电平) | RTR | 0(显性电平) | 1(隐性电平) | DLC | 发送数据长度 | 请求的数据长度 | 是否有数据段 | 是 | 否 | CRC校验范围 | 帧起始+冲裁段+控制段+数据段 | 帧起始+仲裁段+控制段 |
3.6波特率
在CAN的底层协议里将CAN数据的每一位时间(TBit)分为许多的时间段(Tscl),这些时间段包括: A. 位同步时间(Tsync) B. 时间段1(Tseg1) C. 时间段2(Tseg2) 其中位同步时间占用1个Tscl;时间段1占用(Tseg1+1)个Tscl;时间段2占用(Tseg2+1)个Tscl,所以CAN控制器的位时间(TBit)就是:TBit=Tseg1+Tseg2+Tsync=(TSEG1+TSEG2+3)*Tscl,那么CAN的波特率 (CANbps)就是1/TBit。 但是这样计算出的值是一个理论值。在实际的网络通信中由于存在传输的延时、不同节点的晶体的误差等因素,使得网络CAN的波特率的计算变得复杂起来。CAN在技术上便引入了重同步的概念,以更好的解决这些问题。这样重同步带来的结果就是要么时间段1(Tseg1)增加TSJW(同步跳转宽度SJW+1),要么时间段减少TSJW CAN有波特率的值四以下几个元素决定: A. 最小时间段Tscl; B. 时间段1 TSEG1; C. 时间段2 TSEG2; D. 同步跳转宽度 SJW 那么Tscl又是怎么计算的呢?这是总总线时序寄存器中的预分频寄存器BRP派上了用场,Tscl=(BRP+1)/FVBP。FVBP为微处理器的外设时钟。 而TSEG1与TSEG2又是怎么划分的呢?TSEG1与TSEG2的长度决定了CAN数据的采样点,这种方式允许宽范围的数据传输延迟和晶体的误差。其中TSEG1用来调整数据传输延迟时间造成的误差,而TSEG2则用来调整不同点节点晶体频率的误差。但是他们由于过于灵活,而使初次接触CAN的人有点无所适从。TSEG1与TSEG2的是分大体遵循以下规则: Tseg2≥Tscl2,Tseg2≥2TSJW,Tseg1≥Tseg2 总的来说,对于CAN的波特率计算问题,把握一个大的方向就行了,其计算公式可了规结为: BitRate = Fpclk/( (BRP+1) * ((Tseg1+1)+(Tseg2+1)+ 1) 1:采样时间
除了波特率之外,CAN接口还有1个重要的参数就是单bit数据的采样时间。采样时间通常用采样点时间位于整个bit时间内的百分比来表示。 (Sync_Seg+ Prog_Seg+ Phase_Seg1)/( Sync_Seg+ Prog_Seg+ Phase_Seg1+ Phase_Seg2) 如下图所示,采样点位置为(1+1+4)/(1+1+4+2)=75%。
与采样时间相关的有如下几个重要参数。 参数 | 取值范围 | 说明 | Sync_Seg | 1 tq | 同步段。固定长度,总线输入与系统时钟同步,用于同步总线上不同的节点。在此段内期望有一个 CAN 总线电平边沿出现。如果边沿出现在 Sync_Seg 之外,那么它与 Sync_Seg 之间的长度叫做边沿相位误差 。 | Prog_Seg | 1~8 tq | 传播时间段。用于补偿信号在CAN网络内部的传输过程中的物理延时时间,与网络的拓补结构和长度有关。是信号在总线上的传播时间、接收电路延时及总线驱动器延时的总和的 2 倍。 | Phase_Seg1 | 1~8 tq | 相位缓冲段1。用于补偿跳变沿的相位误差,在重同步时可能被延长。 | Phase_Seg2 | 1~8 tq | 相位缓冲段2。用于补偿跳变沿的相位误差,在同步时可能被缩短。 | TSJW | 1~4 tq | (重)同步跳转宽度。决定重同步会时将采样点移动多远,移动距离的上限由用于补偿沿相位误差的相位缓冲段Phase_Seg1和Phase_Seg2给定。该参数不参与采样时间的计算。 这个参数也表示CAN总线对波特率范围的容差度,设置较大的值可以提高波特率的适应性。 | 信息处理时间 | 0~2 tq | 信息处理时间是一个以采样点作为起始的时间段。用于计算后续位的电平。该参数不参与采样时间的计算,与Phase_Seg2的取值相关。 |
确定Prog_Seg、Phase_Seg1、Phase_Seg2 、TSJW的值需要遵循如下几个原则:
- Sync_Seg、Prog_Seg、Phase_Seg1和 Phase_Seg2的总和在8~25之间。
- Phase_Seg2应该取Phase_Seg1和信息处理时间二者中的最大值。
- SJW取Phase_Seg1和4中的最小值。
- Phase_Seg2≥SJW,Phase_Seg1≥SJW。
- Phase_Seg1+Phase_Seg2为偶数时Phase_Seg1=Phase_Seg2 ,Phase_Seg1+ Phase_Seg2为奇数时Phase_Seg1+1=Phase_Seg2。
关于CAN采样时间点位置的选取,网上有很多不同的说法,有75%、80%、87.5%、80%~90%等等,CiA官网也没有给出标准值。那么CAN的采样时间应该设置为多少才算合理?对于这个问题并没有1个绝对固定的标准值。对于不同的行业,不同的CAN高层协议(CANopen、DeviceNet等),以及不同的国家都有不同的经验值。 以应用较为广泛的CANopen协议为例,在2002年的CANopen CiA301 v4.0.2版本规范中,对于采用时间的建议值如下图所示。500k及以下波特率,采样时间建议值为14/16=87.5%,800k为8/10=80%,1M为6/8=75%。
然而,在2011年的最新版本CiA301 v4.2.0中,对于采样时间作了细微调整,将建议值均统一成了87.5%。而且给出了有效采样时间的可选范围。如下图所示。
因此,采样时间的选择并没有1个绝对的标准值,针对不同应用和不同行业都会存在变化。但是要确保在同一个CAN网络中所有节点设备的采样时间均保持一致,这样才能保证CAN通信的稳定性。 广州周立功作为国内CAN产品的领先者,使用了CiA CANopen的建议值,即采样时间为87.5%,SJW=1 tq。因此,我们以此作为CAN接口的设计参考标准。 2:波特率及采样时间参数计算
波特率与采样时间的计算互相关联。计算步骤如下:
- 首先计算CAN接口参考时钟和波特率的比值,该值为分频系数BRP与总tq个数的乘积。
- 根据比值确定BRP和总tq的个数,两者必须都为整数,tq个数范围是8~25;
- 将总tq的个数减1(去掉Sync_Seg)后得到Prog_Seg、Phase_Seg1、Phase_Seg2三个参数的和;
- 然后派发Prog_Seg、Phase_Seg1、Phase_Seg2各占有的tq数。在计算时,一般将Prog_Seg与Phase_Seg1合为一个整体TS1进行计算,Phase_Seg2作为TS2进行计算。
如下图所示,CAN接口参考时钟为100M,TSJW=0+1时,计算500k波特率的参数。选择误差为0,87.5%采样率下的参数。TS1=5+1=6,TS2=0+1=1。
根据公式:BitRate = Fpclk/( (BRP+1) * ((Tseg1+1)+(Tseg2+1)+1) 其中BitRate=0.5MHZ, Fpclk=100MHZ,可以算出 Fpclk/ BitRate=( (BRP+1) * ((Tseg1+1)+( Tseg1+1)+ 1) 200=( (BRP+1) * ((5+1)+( 0+1)+(0+1)) BRP=24
若所需要的波特率计算结果无法满足误差为0时获得87.5%的采样点,则可以取相对较近的值,且适当增大SJW,以提高波特率的适应性。例如,800k波特率计算结果,如下图所示。取80%(满足75%~90%)采样点时的参数,TS1=2+1=3,TS2=0+1=1,BRP=24+1=25。
4CAN控制器介绍ZYNQ包含2个CAN控制器,分别是CAN0和CAN1,可以引出到MIO上,也可以引出到PL的EMIO。对应的全局中断号分别是IRQ #ID 60 和IRQ #ID 83,CAN的参考时钟可以通过内部PLL设置也可以外部提供。波特率计算公式如下,其中BRP是预分频寄存器的分频系数。
CAN控制器的功能模块包括了对象层(用于缓存数据和过滤数据),以及数据协议层。数据协议层主要依据CAN协议格式完成数据bitstream 流的收发。 对象层主要包括了发送数据通道、接收数据通道、配置寄存器。 其中发送数据通道包含了TX FIFO、TX HPB、TX 极性逻辑;接收数据通道包含了RX接收过滤器、RX FIFO。
4.1:数据缓存过滤层
1:FIFOCAN控制器有一个发送TXFIFO和一个接收RXFIFO,每个FIFO具有缓存64条消息。从TXFIFO发送数据的总延迟是2倍的TX驱动器延迟+传播延迟+ RX驱动器延迟。 2:TX HPB每个控制器还具有一个传输高优先级缓冲区(TXHPB),该缓冲区为一条发送消息提供存储。写入此缓冲区的消息具有最大的传输优先级。 它们在当前传输完成后立即排队等待传输,从而抢占了TXFIFO中的任何消息。 3:TX Priority Logic TX发送优先权控制逻辑 4:RX过滤器接收过滤器使用用户定义的接收掩码和ID寄存器对传入的消息进行排序,以确定是将消息存储在RXFIFO中,还是确认并丢弃它们。通过接收过滤器传递的消息存储在RXFIFO中。 5:CAN的工作模式配置寄存器用于对CAN的工作模式当执行以下任何操作时,无论运行模式如何,CAN控制器都会进入配置模式。 •向SRR寄存器的[CEN]位写入0。 •向SRR寄存器的[SRST]位写入1。 重置软件后,控制器立即进入配置模式。 •在复位输入上驱动0。 只要复位为0,控制器就将继续处于复位状态。在将复位取反为1后,控制器将进入配置模式。
以下对CAN的工作模式做简单介绍 5-1:普通模式
根据Bosch和IEEE规范定义的TX和RX I / O信号发送和接收消息。 5-2:睡眠模式
睡眠模式可用于在空闲时间节省少量电量。在睡眠模式下,控制器可以转换到正常模式或配置模式。睡眠模式包括以下操作。 •当另一个节点发送消息时,控制器接收到该消息并退出睡眠模式。 •当有新的TX请求时,控制器将切换到正常模式并为该请求提供服务。 •当控制器进入睡眠模式时,可能会产生中断。 •控制器唤醒时可能会产生中断。 当CAN总线活动或TXFIFO或TXHPB中有请求时,硬件会退出睡眠模式。当控制器退出睡眠模式时,硬件会将can.MSR [SLEEP]设置为0,并且会产生中断。 当[MSR]中的[LBACK]位为0,MSR寄存器中的[SLEEP]位为1,SRR寄存器中的[CEN]位为1时,CAN控制器将从配置模式进入睡眠模式。CAN 仅当没有来自TXFIFO或TX高优先级缓冲器的未决发送请求时,控制器才进入睡眠模式。 仅当[SLEEP]位为1,CAN总线空闲,并且没有来自TXFIFO或TX高优先级缓冲器(TXHPB)的挂起传输请求时,CAN控制器才从正常模式进入睡眠模式。 当另一个节点发送消息时,CAN控制器接收到发送的消息并退出睡眠模式。当控制器处于睡眠模式时,如果有来自TXFIFO或TXHPB的新传输请求,这些请求将得到处理,并且CAN控制器将退出睡眠模式。当CAN控制器进入睡眠模式或从睡眠模式唤醒时,将产生中断。从睡眠模式,CAN控制器可以进入配置模式或正常模式。 5-3:回环模式(诊断)
回送模式用于诊断目的。在环回模式下,必须将控制器编程为进入配置模式或发出一个复位信号。在环回模式下,将发生以下操作。 •控制器将隐性位流传输到CAN_PHY_TX总线信号上。 •TX消息在内部循环回到RX线路并得到确认。 •TX消息不在CAN_PHY_TX总线信号上发送。 控制器接收其发送的所有消息。 •控制器未收到其他CAN节点发送的任何消息。 5-4:侦听模式(诊断)
监听模式用于诊断目的。在侦听模式下,必须将控制器编程为进入配置模式或保持复位状态。 在监听模式下,将发生以下操作。 •控制器将隐性位流传输到CAN总线上。 •控制器不参与正常的总线通讯。 •控制器接收其他CAN节点发送的消息。 •软件可以对验收过滤器进行编程,以动态启用/禁用和更改标准。 错误计数器被禁用并清除为0。读取错误计数器寄存器将返回0。 5-5:模式转换
支持的模式转换如图20-3所示。 转换主要由复位,[CEN]位,MSR寄存器设置和硬件唤醒机制控制。 要从配置模式进入普通模式,必须执行以下步骤。 •清除can.MSR [LBACK,SNOOP,SLEEP] = 0。 •设置can.SRR [CEN] = 1。 要从正常模式进入睡眠模式(产生中断),请设置can.MSR [SLEEP] = 1。 导致控制器退出睡眠模式(产生中断)的事件包括以下步骤。 •RX信号活动(硬件设置can.MSR [SLEEP] = 0)。 •TXFIFO或TXHPB活动(硬件集can.MSR [SLEEP] = 0)。 •软件将0写入can.MSR [SLEEP]。 4.2CAN协议引擎层CAN协议引擎主要由位定时逻辑(BTL)和位流处理器(BSP)模块组成。下图给出了CAN协议引擎的框图。
1:RX / TX位时序逻辑位定时逻辑(BTL)模块的主要功能如下。 •为位流处理器(BSP)生成RX采样时钟。 •使CAN控制器与总线上的CAN通信同步。 •在接收期间对总线进行采样并从总线中提取数据流。 •在传输过程中将传输位流插入总线。
位时间时钟周期的标称长度基于CAN_REF_CLK时钟频率,波特率发生器分频器(can.BRPR寄存器)和段长度(can.BTR寄存器)。 位定时逻辑模块使用can.BTR [SJW]位字段中的同步宽度参数来管理CAN的重新同步功能。 CAN位时序如下图所示。 同步段计数始终等于一个时间量子周期。可使用can.BTR [TS1,TS2]位字段对TS 1和TS 2周期计数进行编程。 当控制器处于配置模式时,将写入这些寄存器。 传播段的宽度(PROP_SEG)必须小于实际传播延迟。
2:时间量子时钟时间量子时钟(TQ_CLK)由控制器参考时钟(CAN_REF_CLK)除以波特率预分频器(BRP)得到。 tTQ_CLK = tCAN_REF_CLK * (can.BRPR[BRP] + 1) freqTQ_CLK = freqCAN_REF_CLK / (can.BRPR[BRP] + 1)
tSYNC_SEGMENT = 1 * tTQ_CLK tTIME_SEGMENT1 = tTQ_CLK * (can.BPR[TS1] + 1) tTIME_SEGMENT2 = tTQ_CLK * (can.BPR[TS2] + 1) tBIT_RATE = tSYNC_SEGMENT + tTIME_SEGMENT1 + tTIME_SEGMENT2 freqBIT_RATE = freqCAN_REF_CLK / ((can.BRPR[BRP] + 1) * (3 + can.BTR[TS1] + can.BTR[TS2])) 3:比特流处理器比特流处理器(BSP)模块在发送和接收CAN消息时执行多种功能。BSP从TXFIFO或TXHPB获得要发送的消息,并在将比特流传递给BTL之前执行以下功能。 在传输期间,BSP同时监视RX数据并执行总线仲裁任务。然后,当赢得仲裁时,它将发送完整的帧;当仲裁丢失时,将重试。 •序列化消息。 •在传输过程中插入填充位,CRC位和其他协议定义的字段。 在传输期间,BSP同时监视RX数据并执行总线仲裁任务。当赢得仲裁时,它将发送完整的帧;当仲裁丢失时,将重试。 在接收期间,BSP从接收到的比特流中删除填充位,CRC比特和其他协议字段。BSP状态机还在发送和接收期间分析总线通信量和接收格式以及CRC、ACK、填充和位冲突。然后,状态机执行错误信号和错误限制任务。CAN控制器不会自动生成过载帧,但会响应总线上检测到的过载标志。 该模块确定CAN控制器的错误状态:主动错误,被动错误或总线关闭。当在总线上观察到TX或RX错误时,BSP将根据CAN 2.0A,CAN 2.0B和ISO 11898-1标准中定义的规则更新发送和接收错误计数器。基于这些计数器的值,BSP将更新CAN控制器的错误状态。 4.3消息格式RXFIFO,TXFIFO和TXHPB使用相同的消息格式,每个消息包括四个字(16个字节), 无论消息中的数据字节和有效字段的实际数量如何,软件都必须读写所有四个字。
写入:如果不需要位字段或数据字节,则写入零。 读取:数据从字节0开始,并持续DLC中的计数数。 4.4CAN的中断每个CAN控制器都有一个向通用中断控制器(GIC)发出的中断信号。 CAN 0连接到IRQ ID#55,CAN 1连接到ID#56。 中断源可以分为以下之一。 •TXFIFO和TXHPB •RXFIFO •消息传递和仲裁 •睡眠模式和总线关闭状态 使用can.IER寄存器启用和禁用中断。使用can.ISR寄存器检查中断的初始状态。通过向can.ICR寄存器写入1来清除中断。
4.5编程模型
5硬件电路分析
6搭建SOC系统工程详细的搭建过程这里不再重复,对于初学读者如果还不清楚如何创建SOC工程的,请学习“01Vitis Soc开发入门”这篇文章。 6.1SOC系统工程
ZYNQ IP中设置CAN0
ZYNQ IP中设置CAN的参考时钟,不同的参考时钟波特率计算方法不一样.
6.2编译并导出平台文件以下步骤简写,有不清楚的看第一篇文章。 1:单击Block文件à右键àGenerate the Output ProductsàGlobalàGenerate。 2:单击Block文件à右键à Create a HDL wrapper(生成HDL顶层文件)àLet vivado manager wrapper and auto-update(自动更新)。 3:添加配套工程路径下uisrc/04_pin/fpga_pin.xdc约束文件 4:生成Bit文件。 5:导出到硬件: FileàExport HardwareàInclude bitstream 6:导出完成后,对应工程路径的soc_hw路径下有硬件平台文件:system_wrapper.xsa的文件。根据硬件平台文件system_wrapper.xsa来创建需要Platform平台。
7搭建Vitis-sdk工程创建soc_base sdk platform和APP工程的过程不再重复,如果不清楚请参考本章节第一个demo。 7.1创建SDK Platform工程
右击soc_base编译,编译的时间可能会有点长 7.2创建APP工程
8程序分析8.1Init_CanPsIntr(&CanInstance, CAN_DEVICE_ID)函数1:XCanPs_LookupConfig(DeviceId)
首先依然是通过查找配置程序来获取CAN控制器的硬件配置。我们跟踪这个程序,看看他获取的配置是什么。
这个结构体中定义了CAN的ID 以及CAN的基地址,可以看到我们这里使用的是PS 的CAN1
进一步跟踪,可以在xparameters.h中查到CAN基地址的具体定义,以及CAN的参考时钟,这里和我们MPSOC IP中设置一样,参考时钟100M
2:XCanPs_CfgInitialize(CanInstPtr,ConfigPtr,ConfigPtr->BaseAddr)这个函数用于初始化回调函数的函数指针,为中断部分设置回调函数,做好准备。可以看到CAN的部分中断回调函数根据不同的状态信息,调用了不同的函数。
在这个函数的最后,调用了XCanPs_Reset(InstancePtr);函数复位CAN控制器,我们看下这个函数操作的寄存器.
CAN的软件复位寄存器:地址偏移XCANPS_SRR_OFFSET=x00000000
bit0:写1复位CAN控制器 bit1:写0 CAN处于配置模式,写1可以处于环路模式,休眠模式,或者正常模式
3:Can_Config(CanInstPtr,rate_500kbps)这个函数中设置CAN的波特率
3.1:XCanPs_EnterMode(CanInstPtr, XCANPS_MODE_CONFIG)函数 首先根据输入的参数XCANPS_MODE_CONFIG,对寄存器进行设置。
以上代码首先通过XCanPs_GetMode(InstancePtr)函数读取模式状态:
这个函数通过XCanPs_GetStatus(InstancePtr)函数读取CAN状态寄存器的状态:
CAN状态寄存器的偏移地址XCANPS_SR_OFFSET= 0x00000018
之后通过判断当然模式和需要的配置模式参数进行状态的切换,分三种情况: 1需要设置的配置模式为休眠模式&当前的模式为正常模式,则切换到休眠模式 2需要设置的配置模式为正常模式&当前的模式为休眠模式,则切换到正常模式 3以上两种情况都是,则执行else分支代码设置复位寄存器,并且继续执行:
以上代码中对软件复位寄存器,以及模式选择选择寄存器进行设置。这里介绍下模式选择寄存器。 模式选择寄存器的偏移地址XCANPS_MSR_OFFSET= 0x00000004
3.2:can_bit_timing_config参数列表
can_bit_timing结构体定义了CAN控制的: 1) BaudRate-波特率 2) BaudRatePrescaler-波特率预分频系数 3) TimeSegment1-时间段1 4) TimeSegment2-时间段2 5) SyncJumpWidth-同步跳转宽度
关于波特率分频系数的计算在3小节有介绍。 3.3: XCanPs_SetBaudRatePrescaler(CanInstPtr, can_bit_timing_config.BaudRatePrescaler)
这个函数中,对波特率寄存器进行设置。 波特率寄存器的偏移地址XCANPS_BRPR_OFFSET = 0x00000008
3.4:XCanPs_SetBitTiming(XCanPs *InstancePtr, u8 SyncJumpWidth,u8 TimeSegment2, u8 TimeSegment1) 设个函数用于设置CAN控制器的时间段1、时间段2、以及同步跳转宽度
如果需要设置这些参数,首先确保CAN处于配置模式。 位时间寄存器的偏移地址XCANPS_BTR_OFFSET=0x0000000C
4:配置正常模式当配置完成后,将CAN配置为正常模式
8.2CanPs_Setup_IntrSystem(&Intc, &CanInstance, CAN_INTR_VEC_ID)
1:XScuGic_Connect(IntcInstancePtr, CanIntrId, (Xil_InterruptHandler)XCanPs_IntrHandler, (void *)CanInstancePtr)函数
这个函数负责把对应中断号从回调函数,以及回调参数,连接到之前在Init_Intr_System(&Intc)函数中定义的回调函数。 2:设置用户回调函数
当CAN的中断产生后,通过以上设置的函数指针会调用对应的函数,分析的最后部分我再介绍每个中断函数。 3:XScuGic_Enable(IntcInstancePtr, CanIntrId)在以下代码中,首先绑定中断号,CPU号,我们也可以进一步分中断
XScuGic_InterruptMaptoCpu(InstancePtr, Cpu_Id, Int_Id)函数 在这个函数中具体中断和CPU如何关联,如何设置SPI(共享外设中断)中断寄存器的相关位我们无法进一步分分析,到此为止。
4:XCanPs_IntrEnable(CanInstancePtr, XCANPS_IXR_ALL)
CAN的中断使能寄存器偏移地址:XCANPS_IER_OFFSET= 0x00000020
5:void can_SendHandler(void *CallBackRef)函数CAN帧发送成功后回调
6:void can_RecvHandler(void *CallBackRef)函数接收到正确数据后回调,在接收中断中打印帧信息。
7:void can_ErrorHandler(void *CallBackRef, u32 ErrorMask)函数当发生ACK错误、bit错误、帧错误、CRC错误、填充错误,错误回调函数执行
8:void can_EventHandler(void *CallBackRef, u32 IntrMask) 当发生bus_off状态、RX FIFO溢出、RX FIFO 满、TX FIFO满、TX优先缓存满、从睡眠唤醒、总线仲裁丢失,会回调以下函数。
8:Can_send(&CanInstance, &msg)函数
以上函数中首先填写帧信息 然后通过调用函数XCanPs_IsTxFifoFull(InstancePtr)获取发送FIFO的状态。
最后调用XCanPs_Send(InstancePtr, TxFrame)函数发送帧
以上函数中,帧信息需要写入以下寄存器:
- TX的FIFO ID寄存器 偏移地址XCANPS_TXFIFO_ID_OFFSET= 0x00000030
2)TX FIFO 数据长度寄存器偏移地址:XCANPS_TXFIFO_DLC_OFFSET=0x00000034
3) TX FIFO的数据字1寄存器偏移地址:XCANPS_TXFIFO_DW1_OFFSET= 0x00000038
4) TX FIFO的数据字2寄存器偏移地址:XCANPS_TXFIFO_DW2_OFFSET= 0x0000003C
9方案演示
9.1硬件准备
9.2实验结果
1:软件安装根据安装说明安装软件,CAN分析仪软件为“USB_CAN TOOLSetup(V9.05).exe”
2:CAN分析仪的使用
将main.c中的宏定义:#define TEST_RX_ONLY注释。重新编译工程。
将CAN分析仪与电脑连接,使用CAN分析仪连接CAN模块,再将CAN模块连接开发板。
打开USB-CAN Tool,选择500kbps的波特率连接CAN分析仪。
通过SDK将程序下载至开发板运行,此时,在USB-CAN Tool软件中便可抓取开发板每隔1s向外发送的CAN数据帧,如下图所示。数据帧,每个数据帧的第1个字节数据不断递增。
3:数据接收测试还原main.c中的宏定义:#define TEST_RX_ONLY。重新编译工程。将程序下载到开发板中运行。 4:数据帧接收打开USB-CAN Tool软件的数据发送功能,设置如下图所示。通过软件向开发板发送数据长度为8字节的数据帧。发送的第一个字节的数据不断递增。然后,点击立即发送。
同时,开发板通过串口将每次接收到的数据帧信息在SDK中打印出来,如下图所示。可以看到第一个字节的数据在递增。
5:远程帧接收
6:数据收发同时进行将main.c中的宏定义:#define TEST_RX_ONLY注释,重新编译工程。然后将程序下载到开发板中运行。同时,通过软件向开发板连续发送数据长度为8字节的数据帧。如下图所示。
|