用户工具

站点工具


icore4t_57

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

后一修订版
前一修订版
icore4t_57 [2020/03/28 11:30]
zgf 创建
icore4t_57 [2022/04/01 10:57] (当前版本)
sean
行 3: 行 3:
 |技术支持电话|**0379-69926675-801**||| |技术支持电话|**0379-69926675-801**|||
 |技术支持邮件|Gingko@vip.163.com||| |技术支持邮件|Gingko@vip.163.com|||
-|技术论坛|http://​www.eeschool.org||| 
 ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^ ^  版本 ​ ^  日期 ​ ^  作者 ​ ^  修改内容 ​ ^
 |  V1.0  |  2020-03-28 ​ |  gingko ​ |  初次建立 ​ |  |  V1.0  |  2020-03-28 ​ |  gingko ​ |  初次建立 ​ | 
-\\ 
-\\ 
-\\ 
 \\ \\
 \\ \\
行 22: 行 18:
 {{ :​icore4t:​icore4t_cube_57_3.png?​direct |}} {{ :​icore4t:​icore4t_cube_57_3.png?​direct |}}
 4.时基源选择SysTick 4.时基源选择SysTick
-{{ :icore4t:icore4t_cube_57_4png?direct |}}+{{ :icore4t:icore4t_cube_57_4.png?direct |}}
 5.将PA10,​PB7,​PB8设置为GPIO_Output 5.将PA10,​PB7,​PB8设置为GPIO_Output
 {{ :​icore4t:​icore4t_cube_57_5.png?​direct |}} {{ :​icore4t:​icore4t_cube_57_5.png?​direct |}}
行 70: 行 66:
 \\ \\
 \\ \\
 +===== 实验五十七:CAN通信实验——回环测试 =====
 +
 +==== 一、 实验目的与意义 ====
 +
 +  - 了解STM32的CAN结构。
 +  - 了解STM32的CAN特征。
 +  - 掌握STM32的CAN的使用方法。
 +  - 掌握KEIL MDK 集成开发环境使用方法。
 +==== 二、 实验设备及平台 ====
 +
 +  - iCore4T 双核心板。[[https://​item.taobao.com/​item.htm?​spm=a1z10.1-c.w137644-251734891.3.5923532fDrMDOe&​id=610595120319|点击购买]]
 +  - iCore4T 扩展底板。
 +  - JLINK(或相同功能)仿真器。[[https://​item.taobao.com/​item.htm?​id=554869837940|点击购买]]
 +  - Micro USB线缆。
 +  - Keil MDK 开发平台。
 +  - STM32CubeMX开发平台。
 +  - 装有WIN XP(及更高版本)系统的计算机。
 +==== 三、 实验原理 ====
 +
 +=== 1.CAN简介 ===
 +  * CAN是Controller Area Network的缩写(简称为CAN),是由以研发和生产汽车电子产品著称的德国BOSCH公司开发的,并最终成为国际标准(ISO 11898),是国际上应用最广泛的现场总线之一。
 +  * CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。
 +  * CAN的可靠性已经得到广泛认可,被应用于工业自动化、船舶、医疗设备、工业设备等方面。
 +  * **CAN 协议具有以下特点:**
 +    * 1)多主控制。 在总线空闲时,所有单元都可以发送消息(多主控制),而两个以上的单元同时开始发送消息时, 根据标识符( Identifier 以下称为 ID)决定优先级。 ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。
 +    * 2)系统的柔软性。 与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。
 +    * 3)通信速度较快,通信距离远。 最高 1Mbps(距离小于 40M),最远可达 10KM(速率低于 5Kbps)。
 +    * 4)具有错误检测、错误通知和错误恢复功能。 所有单元都可以检测错误(错误检测功能),检测出错误的单元会立即同时通知其他所有单元(错误通知功能), 正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。
 +    * 5) 故障封闭功能。 CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。
 +    * 6) 连接节点多。 CAN 总线是可同时连接多个单元的总线。可连接的单元总数理论上是没有限制的。但实际上可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。
 +  * **CAN物理层:**
 +  * CAN是一种异步通讯,只有CAN_High和CAN_Low两条信号线,共同构成一组差分信号线,以差分信号的形式进行通讯。
 +  * **闭环总线网络:**
 +  * CAN物理层的形式主要有两种,如下图是其中的一种“闭环网络”,它允许总线最大长度为40m,最高速度为1Mbps,可以看到总线的两端各有一个120欧的电阻,这是规定。节点就是不同的设备,连接到一个闭环总线上面。
 +{{ :​icore4t:​icore4t_arm_hal_57_1.png?​direct&​600 |}}
 +  * **开环总线网络:​**
 +{{ :​icore4t:​icore4t_arm_hal_57_2.png?​direct&​600 |}}
 +  * **通讯节点:**
 +  * CAN节点是指能够挂接在CAN总线上的单元,并能通过CAN总线实现各个节点间的通信,以实现复杂的控制过程。理论上CAN总线连接的节点可达110个,但实际上收到总线上的时间延迟及电气负载的限制。当连接多节点时,降低通信速率,可连接的节点增加;提高通信速率,则可连接的节点数减少。
 +  * CAN通讯节点由一个CAN控制器及CAN收发器,CAN控制器用于实现实现CAN总线的协议底层以及数据链路层,用于生成CAN帧并以二进制码流的方式发送,在此过程中进行位填充、添加CRC校验、应答检测等操作;将接收到的二进制码流进行解析并接收,在此过程中进行收发比对、去位填充、执行CRC校验等操作。此外还需要进行冲突判断、错误处理等诸多任务。
 +  * CAN收发器(有时也叫做驱动器),用于将二进制码流转换为差分信号发送,将差分信号转换为二进制码流接收。
 +  * 我们已经知道CAN控制器和收发器的概念,观察上面2张图,为接线方式,控制器和收发器通过普通的类似TTL逻辑信号来连接,CAN_Low和CAN_High是一对差分信号线。
 +  * 当CAN节点需要发送数据时,控制器把要发送的二进制编码通过通过CAN_Tx线发送到收发器,然后由收发器把这个普通的逻辑电平信号转换成差分信号,通过差分线CAN_High和CAN_Low线输出到CAN总线网络。而通过收发器接收总线上的数据的到控制器时,是相反的过程。
 +  * **CAN协议中的差分信号:**
 +  * 差分信号又称为差模信号,具体的含义这里不多介绍了。CAN协议中对它使用的CAN_High以及CAN_Low表示的差分信号做了规定,如下图,可以看到,显性电平对应逻辑“0”,隐性电平对应逻辑“1”。当表示为隐性电平(逻辑“1”)时,CAN_High和CAN_Low的电压均为2.5V,此时它们的电压差为0V;当表示显性电平(逻辑“0”)时,CAN_High的电压为3.5V,CAN_Low的电压为1.5V,它们的电压差为2V。举个例子:当CAN收发器从CAN_Tx线接收到来自CAN控制器的低电平信号(逻辑“0”)时,它会使CAN_High输出3.5V,同时CAN_Low输出1.5V。在总线上显性电平具有优先权,只要有一个单元(也就是节点)输出显性电平,总线上即为显性电平。而隐性电平则具有包容的含义,只有所有的单元都输出隐性电平,总线上才为隐性电平。那么可以知道,CAN通讯是半双工的,收发数据需要分开来进行,由于是公用总线,在整个网络中,同一时刻只能由一个通讯节点发送信号,其余的节点在该时刻只能接收。
 +{{ :​icore4t:​icore4t_arm_hal_57_3.png?​direct&​400 |}}
 +=== 2.协议层:​ ===
 +
 +  * **CAN的位时序以及同步:​**
 +  * 由于CAN属于异步通讯,没有时钟信号线,那么节点间就需要约定好波特率进行通讯。同时,为实现正确的总线电平采样,确保通讯正常,由此引出“位时序”的概念。
 +  * **位时序的组成:​**
 +  * CAN协议将每一个数据位的时序分解成4段,即:SS段、PTS段、PBS1段、PBS2段,这4段加起来就是一个CAN数据位的长度。而分解后的最小时间单位是Tq,一个完整的位由8~25个Tq组成。如下图是总线电平下每个位分解。
 +{{ :​icore4t:​icore4t_arm_hal_57_4.png?​direct |}}
 +  * SS段:称为同步段,用于使总线上的各个节点同步,要求有一个跳变沿位于此段内,该段的长度为1Tq;
 +  * PTS段,称为传播时间段,用于补偿网络内的物理延时,它是信号在总线上传播时间,输入比较器延时和输出驱动器延时之和的两倍,该段长可以为1~8Tq;
 +  * PBS1段,称为相位缓冲段,主要用来补偿变压阶段的误差,它的实际长度在重新同步的时候可以加长,该段大小可以为1~8Tq;
 +  * PBS2段,称为另一个相位缓冲段,也是用来补偿边沿阶段的误差,它的时间长度在重新同步的时候可以加长,该段大小可以为2~8Tq。
 +  * **通讯的波特率:**
 +  * 总线上的各个通讯节点只要约好1个Tq的时间长度以及每一个数据位占据多少个Tq,就可以确定CAN通讯的波特率。
 +  * 假设图30-4中1Tq=1us,而有19个Tq,则传输一位数据需要的实际为19us。
 +  * 这样每秒可以传输的数据位个数为:1*106/​19=52631.6(bps),即为波特率。
 +  * **CAN同步机制:**
 +  * CAN规范定义了自己独有的同步方式:硬同步和重同步。同步与位时序密切相关。同步是由节点自身完成的,节点将检测到来自总线的沿与其自身的位时序相比较,并通过硬同步或重同步适配(调整)位时序。
 +  * CAN总线的位同步只有在节点检测到“隐性位(逻辑1)”到“显性位(逻辑0)”的跳变时才会产生,我们知道在同步段需要跳变沿,当跳变沿不处于此同步段内时,那么就会产生相位误差,该相位误差就是跳变沿与同步段结束位置直接的距离,产生误差的原因有多种,那么针对此种误差,也就是上面说到的硬同步和重同步。
 +  * 硬同步只在总线空闲时通过一个下降沿(下面将讲到的帧起始)来完成,此时不管有没有相位误差,所有节点的位时序将重新开始。强迫引起硬同步的跳变沿位于重新开始的位时间的同步段之内。
 +  * 重同步,在消息帧的随后位中,每当有从“隐性位”到“显性位”的跳变,并且该跳变段落在了同步段之外,就会引起一次重同步。重同步机制可以根据跳变沿增长或者缩短位时序以调整采样点的位置,保证正确采样。
 +  * **CAN报文:**
 +  * 和SPI和串口协议不同的是,CAN使用两条差分信号线,因而只能表示一个信号,于是为了实现完整的传输信号功能,CAN协议便对数据、操作命令以及同步信号进行打包,打包后的内容便称为报文。
 +  * **CAN报文格式:**
 +  * CAN一共规定了5种类型的帧,分别是:数据帧、遥控帧、错误帧、过载帧、帧间隔,作用见下表。另外,数据帧和遥控帧有标准格式和扩展格式两个,唯一的区别是标识符(ID)不同,在下面数据帧的结构讲解中,我们会对两个格式进行介绍。
 +{{ :​icore4t:​icore4t_arm_hal_57_5.png?​direct |}}
 +  * **数据帧的结构**
 +  * 数据帧是CAN通信中最中意、最复杂的报文,以一个显性位(逻辑0)开始,以一个7个连续隐性位(逻辑1)结束。在它们之间分为仲裁段、控制段、数据段、CRC段和ACK段,加上起始和结束总共有7个段。
 +  * 在下图中,在标准帧和扩展帧除了ID和DLC之外,还有RTR、IDE、SRR位。首先是RTR位,翻译为远程传输请求位,用显性电平和隐性电平来区分数据帧和遥控帧。然后是IDE位,为标识符扩展位,用显性电平和隐性电平来区分标准格式还是扩展格式。最后是SRR位,只存在于扩展格式,它用于替代标准格式中的RTR位,由于扩展帧中的SRR位为隐性位,RTR是数据帧为显性位,所以在两个ID相同的标准格式报文与扩展格式报文中,标准格式的优先级更高。
 +{{ :​icore4t:​icore4t_arm_hal_57_6.png?​direct |}}
 +  * **帧起始**
 +  * SOF段(Start Of Frame),翻译为帧起始,标准帧和扩展帧都是通过一个显性电平表示帧起始。它用于通知各个节点将有数据传输,其它节点通过帧起始信号的电平跳变沿来进行硬同步。
 +  * **仲裁段**
 +  * 简单来说就是表示优先级的段。仲裁段的内容主要为本数据帧的ID信息,数据帧具有标志格式和扩展格式两种,具体的区别就是ID信息的长度,标准格式的ID为11位,扩展格式的ID为29位,观察图30-5应该也发现了。
 +  * 在CAN协议中,ID起着重要的作用,它决定着数据帧发送的优先级,也决定着其它节点是否会接收到这个数据帧。CAN的数据通信没有主从之分,任意一个节点可以向其他(一个或多个)节点发起数据通信,而对总线的占有权是由信息的重要性决定的,也就是说重要的信息,对它打包上一个优先级高的ID,使它能够及时地发送出去,也正是由于这样优先级的分配原则,使CAN的扩展性大大加强,在总线上增加或减少节点并不会影响其它的设备。
 +  * 那么怎么仲裁呢?让我们联系前面的内容,显性电平的优先权和隐性电平的包容性,CAN正是利用这个特性进行仲裁。若两个节点同时竞争CAN总线的占有权,当它们发送报文时,若首先出现隐性电平,则会失去对总线的占有权,进入接收状态。
 +  * **控制段**
 +  * r1和r0为保留位,默认置为显性,它最主要的是由4位组成的DLC段,MSB先行,DLC段表示的数字为0~8。
 +  * **数据段**
 +  * 为数据帧的核心内容,它是节点要发送的原始信息,由0~8个字节组成,MSB先行。
 +  * **CRC段**
 +  * 为保证报文的正确传输,CAN的报文包含了一段15位的CRC校验码,若检验出错则向发送节点反馈出错信息,利用错误帧请求它重新发送。CRC计算一般由CAN控制器硬件完成,而出错时处理由软件控制最大的重发数。在CRC校验码之后,有一个CRC界定符,为隐性,将CRC校验码与后面的ACK段分隔开。
 +  * **ACK段**
 +  * 包括一个ACK槽位和ACK界定符,在ACK槽位中,发送端发送的为隐性位,接收端在这一位中发送显性位以表示应答,在ACK界定槽和帧结束之间由ACK界定符分隔开。
 +  * **帧结束段**
 +  * 由发送节点发送7个隐性位表示结束。
 +
 +=== 3.STM32的CAN外设简介:​ ===
 +  * STM32具有bxCAN,是基本扩展CAN,它支持CAN协议2.0A和2.0B。它的设计目标是以最小的CPU负荷来高效处理大量接收到的报文。也支持报文发送的优先级要求(通过软件配置)。bxCAN提供所有支持时间触发通信模式所需的硬件功能。
 +  * 该CAN控制器支持最高的通讯速率为1Mb/​s;它可以自动地接收和发送CAN报文,支持使用标准ID和扩展ID的报文;外设中具有3个发送邮箱;具有2个3级深度的接收FIFO,可使用过滤功能只接收或不接收某些ID号的报文。具有双CAN,CAN1是主bxCAN,CAN2为从bxCAN。
 +  * STM32有两组CAN控制器,其中CAN1为主设备,负责管理bxCAN和512字节的SRAM存储器之间的通信;CAN2为从设备,它不能直接访问SRAM存储器。在使用CAN2的时候必须先使能CAN1外设的时钟。
 +{{ :​icore4t:​icore4t_arm_hal_57_7.png?​direct |}}
 +**CAN控制内核:​**
 +  * 框图中标号①处的CAN控制内核包含了各种控制器及状态寄存器,通过这些寄存器可以配置CAN的参数,如波特率;请求发送报文;处理报文的接收;管理相关中断、获取诊断信息等。由于篇幅原因,这里主要讲解的是主控制器寄存器和位时序控制器。
 +  * 主控制寄存器(CAN_MCR)
 +  * DBF调试冻结(DBF)
 +  * 可设置为调试时的工作状态或者禁止收发的状态,禁止收发时仍然可以访问接收FIFO的中的数据。
 +  * 时间触发通信模式(TTCM)
 +  * 用于运行和禁止时间触发通信模式。在该模式下,CAN硬件的内部定时器被激活,并且产生时间戳,分别存储在CAN_RDTxR/​CAN_TDTxR寄存器中。内部定时器在接收和发送的帧起始位的采样点位置被采样,并生成时间戳。
 +  * 自动离线管理(ABOM)
 +  * 该位决定CAN硬件在什么条件下可以退出离线状态,为“1”时,一旦硬件检测到128次11位的连续隐性位,则自动退出离线状态;为“0”时,软件对CAN_MCR寄存器的INRQ位进行置‘1’随后清‘0’后,一旦硬件检测到128次11位连续的隐性位,则退出离线状态。
 +  * 自动唤醒(AWUM)
 +  * CAN外设可以使用软件进入低功耗的睡眠模式,使能此功能后,当CAN检测到总线活动的时候,会自动唤醒。
 +  * 自动重传(NART)
 +  * 设置为“0”时,CAN硬件发送报文时会一直重传,直达成功为止;为“1”时,CAN报文只被发送一次,不管有没成功。
 +  * 接收FIFO锁定模式(RFLM)
 +  * 该功能用于锁定接收FIFO,锁定时,接收FIFO溢出时,会丢弃下一个接收到的报文;不锁定,则下一个接收到的报文会覆盖原报文。
 +  * 发送FIFO优先级(TXFP)
 +  * 当发送邮箱中有多个报文同时在等待发送时,该位控制是报文的ID来决定还是发送请求的顺序来决定。
 +  * CAN位时序寄存器(CAN_BTR)
 +  * 为了方便用于调试,CAN通过设置SILM和LBKM位可以将模式设置为正常模式、静默模式、回环模式和禁止回环模式。
 +{{ :​icore4t:​icore4t_arm_hal_57_8.png?​direct |}}
 +  * **CAN发送邮箱**
 +  * 在上图中的标号②是CAN外设的发送邮箱,它一共有3个发送邮箱,即可以缓存3个待发送的报文。由发送跳段根据优先级决定哪个邮箱的报文先被发送。
 +  * 每个发送邮箱含有标记符寄存器(CAN_TIxR)、数据长度控制寄存器(CAN_TDTxR)和两个数据寄存器CAN_TDLxR、CAN_TDHxR。
 +  * 当我们要发送报文时,把报文的各个段分解,按位置写入到这些寄存器中,并将CAN_TIxR中的发送请求寄存器位TMIDxR_TXRQ置1,即可完成发送。
 +  * CAN接收FIFO
 +  * CAN外设有2个接收FIFO,每个FIFO有3个邮箱,即可以缓存6个接收到的报文。当接收到报文时,FIFO的报文计数器会自增,而STM32内部读取FIFO数据之后,报文计数器会自减,我们便可以通过状态寄存器获知报文计数器的值。
 +  * 和发送邮箱类似,也有4个寄存器,类型也是一样的。通过中断或者状态寄存器知道接收FIFO有数据后,再读取这些寄存器的值即可把接收到的报文加载到STM32的内存中。
 +  * 接收过滤器
 +  * 在CAN协议中,消息的标识符与节点地址无关,但是和消息的内容有关。因此,接收节点会根据标识符的值来确定软件是否需要该消息。STM32在的CAN外设接收报文前会嫌使用接收过滤器进行检查,只接收需要的报文到FIFO中。
 +  * CAN过滤器的寄存器有多个,可以自己看手册进行相应的配置,这里就不多讲解了。过滤的方法有两种模式分别是ID列表模式和掩码模式。
 +  * 在本实验中,iCore4T使用SN65HVD230作为CAN驱动,通过CAN助手发送数据并能接收数据。
 +  * 原理图:
 +{{ :​icore4t:​icore4t_arm_hal_57_9.png?​direct&​700 |}}
 +==== 四、 实验程序 ====
 +=== 1.主函数 ===
 +<code c>
 +int main(void)
 +{
 +  int i;
 +  HAL_Init();
 +  SystemClock_Config();​
 +  i2c.initialize();​
 +  axp152.initialize();​
 +  axp152.set_dcdc1(3500);//​[ARM & FPGA BK1/2/6 &OTHER]
 +  axp152.set_dcdc2(1200);//​[FPGA INT & PLL D]
 +  axp152.set_aldo1(2500);//​[FPGA PLL A]
 +  axp152.set_dcdc4(3300);//​[POWER_OUTPUT]
 +  axp152.set_dcdc3(3300);//​[FPGA BK4][Adjustable]
 +  axp152.set_aldo2(3300);//​[FPGA BK3][Adjustable]
 +  axp152.set_dldo1(3300);//​[FPGA BK7][Adjustable]
 +  axp152.set_dldo2(3300);//​[FPGA BK5][Adjustable]
 +  HAL_Delay(100);​
 +
 +  MX_GPIO_Init();​
 +  MX_FDCAN1_Init();​
 +
 +  LED_ON;
 +  can.initialize();​
 +  for(i = 0;i < 8;i++){
 +    TxData[i] = i;
 +  }
 +  while (1)
 +  {
 +    //​将接收到数据发送出去
 +    if(can.receive_ok_flag == 1){
 +      can.receive_ok_flag = 0;
 +      HAL_FDCAN_AddMessageToTxFifoQ(&​hfdcan1,​ &​TxHeader,​ RxData);
 +    }     
 +  }
 +}
 +
 +</​code> ​
 +=== 2.CAN初始化 ===
 +<code c>
 +  /* Bit time configuration:​
 +    fdcan_ker_ck ​              = 40 MHz
 +    Time_quantum (tq)          = 25 ns
 +    Synchronization_segment ​   = 1 tq
 +    Propagation_segment ​       = 23 tq
 +    Phase_segment_1 ​           = 8 tq
 +    Phase_segment_2 ​           = 8 tq
 +    Synchronization_Jump_width = 8 tq
 +    Bit_length ​                = 40 tq = 1 祍
 +    Bit_rate ​                  = 1 MBit/s
 +  */
 +FDCAN_HandleTypeDef hfdcan1;
 +
 +/* FDCAN1 init function */
 +void MX_FDCAN1_Init(void)
 +{
 +  hfdcan1.Instance = FDCAN1;
 +  hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;//​传统帧格式
 +  hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;//​普通模式
 +  hfdcan1.Init.AutoRetransmission = ENABLE;//​打开自动重传
 +  hfdcan1.Init.TransmitPause = DISABLE;//​关闭传输暂停
 +  hfdcan1.Init.ProtocolException = ENABLE;//​打开协议异常处理
 +  hfdcan1.Init.NominalPrescaler = 1;//​分频系数
 +  hfdcan1.Init.NominalSyncJumpWidth = 8;//​重新同步跳跃宽度
 +  hfdcan1.Init.NominalTimeSeg1 = 31;//​tsg1范围
 +  hfdcan1.Init.NominalTimeSeg2 = 8;//​tsg2范围
 +  hfdcan1.Init.DataPrescaler = 1;//​分频系数
 +  hfdcan1.Init.DataSyncJumpWidth = 1;//​重新同步跳跃宽度
 +  hfdcan1.Init.DataTimeSeg1 = 1;//​seg1范围
 +  hfdcan1.Init.DataTimeSeg2 = 1;//​seg2范围
 +  hfdcan1.Init.MessageRAMOffset = 0;//​信息RAM偏移
 +  hfdcan1.Init.StdFiltersNbr = 1;//​标准信息ID滤波器编号
 +  hfdcan1.Init.ExtFiltersNbr = 0;//​扩展信息ID滤波器编号
 +  hfdcan1.Init.RxFifo0ElmtsNbr = 1;//​接收FIFO0元素编号
 +  hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;//​接收FIFO0元素大小
 +  hfdcan1.Init.RxFifo1ElmtsNbr = 0;//​接收FIFO1元素编号
 +  hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;//​接收FIFO1元素大小
 +  hfdcan1.Init.RxBuffersNbr = 1;//​接收缓冲编号
 +  hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;//​接收缓冲大小
 +  hfdcan1.Init.TxEventsNbr = 0;//​发送事件编号
 +  hfdcan1.Init.TxBuffersNbr = 0;//​发送缓冲编号
 +  hfdcan1.Init.TxFifoQueueElmtsNbr = 1;//​发送FIFO序列元素编号
 +  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;//​发送FIFO序列模式
 +  hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;//​发送元素大小
 +  if (HAL_FDCAN_Init(&​hfdcan1) != HAL_OK)
 +  {
 +    Error_Handler();​
 +  }
 +}
 +
 +</​code>  ​
 +=== 3.HAL_FDCAN_RxFifo0Callback函数 ===
 +<code c>
 +void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
 +{
 +  if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
 +  {
 +    ​
 +    /* Retreive Rx messages from RX FIFO0 */
 +    if (HAL_FDCAN_GetRxMessage(hfdcan,​ FDCAN_RX_FIFO0,​ &​RxHeader,​ RxData) != HAL_OK)
 +    {
 +    /* Reception Error */
 +    Error_Handler();​
 +    }
 +    ​
 +    if (HAL_FDCAN_ActivateNotification(hfdcan,​ FDCAN_IT_RX_FIFO0_NEW_MESSAGE,​ 0) != HAL_OK)
 +    {
 +      /* Notification Error */
 +      Error_Handler();​
 +    }
 +    ​
 +    /* Receive OK */
 +    can.receive_ok_flag = 1;
 +  }
 +}
  
 +</​code> ​
 +==== 五、 实验步骤 ====
 +  - 把仿真器与iCore4T的SWD调试口相连(直接相连或者通过转接器相连);
 +  - 把iCore4T通过Micro USB线与计算机相连,为iCore4T供电;
 +  - 打开 Keil MDK 开发环境,并打开本实验工程;
 +  - 烧写程序到 iCore4T 上;
 +  - 也可以进入Debug 模式,单步运行或设置断点验证程序逻辑。
 +  - CAN 接口需要安装自带的 CANtest 测试工具,安装完毕后,打开并选择设备 USBCANE-U,波特率设置为 1000K,并启动。
 +==== 六、 实验现象 ====
 +  * 通过CAN助手,点击发送能够接收到数据说明测试通过。
 +{{ :​icore4t:​icore4t_arm_hal_57_10.png?​direct&​700 |}}
 +{{ :​icore4t:​icore4t_arm_hal_57_11.png?​direct&​700 |}}
 +{{ :​icore4t:​icore4t_arm_hal_57_12.png?​direct&​700 |}}
icore4t_57.1585366256.txt.gz · 最后更改: 2020/03/28 11:30 由 zgf