【S32K3 RTD LLD系列教程篇】FlexCAN外部Loopback功能详解

【S32K3 RTD LLD篇2】K344 FlexCAN 外部loopback

  • 一,代码实现与配置
  • 1.1 S32DS3.5导入CAN工程
  • 1.2 添加CAN使用的引脚
  • 1.3 添加外设模块
  • 1.4 时钟检查
  • 1.5 加入代码
  • 二,测试结果
  • 三,坑位标点排雷
  • 3.1 Siul2_Port报错
  • 3.2 S32K3X4EVB-T172板载的CAN收发器
  • 写本篇文章的用意,没有别的意思,单纯表达对RTD400自带CAN代码的不满,因为RTD400自带的CAN代码是loopback,而且还是一个internal loopback。所以本文也作为CAN模块的切入点,使用外部loopback,功能是发送一帧标准帧的CAN数据之后,进入接收状态,收到什么数据,回什么数据出来。本文代码就是基于现有的RTD400的internal loopback例子,添加引脚,对CAN模块做配置,然后添加循环收发功能,测试板子是官方的S32K3X4EVB-T172,并且借助PEAK的PCAN-USB Pro去做测试。

    一,代码实现与配置

    本文主要讲解如何在S32K344上实现具体的功能,关于CAN的理论知识,建议详细阅读K344RM,写的非常的好,足以掌握K344 FlexCAN的特性了。

    1.1 S32DS3.5导入CAN工程

    File-》S32DS Project from example
    选择下图中的FlexCAN代码,并且给工程取一个你自己认为最闪亮的名字。

    图1

    然后就可以导入例程中对应的FlexCAN工程了,双击FlexCAN_example_CT.mex进入到对应的CT工具界面,可以先生成下代码,回来编译下,然后下载了直接体验loopback功能,这个main函数写的也是相当的任性,不过有总比没有好,总归还是提供了点参考。

    1.2 添加CAN使用的引脚

    为了实现和外部CAN节点的交互,还是需要配置相关的引脚的,查看S32K3X4EVB-T172原理图,发现对应的CAN外部收发器情况如下图,并且CAN0_TX=PTA7, CAN0_RX=PTA6.

    图2

    这里一定要特别注意下自己的板子上的CAN收发器的型号,如果是TJA1153,那个是加密的HS-CAN收发器,需要先解密再去做通讯,如果是TJA1443,没问题,可以直接用,我这边连外部的收发器控制引脚都没有控制,直接借助于外部上下拉去实现了。如果实际使用中没有这样的上下拉电路,还是需要去配置对应的控制引脚,在代码中给定相应的电平。
    打开CT工具,选择Pins,然后把package改成172脚的封装,并且在peripheral signals里面选择CAN0,添加两个脚为PTA6,PTA7.

    图3

    这里要注意,会发现右边的problems有报错,然后鼠标选中问题,右击,选中add sdk components “pins”to xxx project.

    图 4

    1.3 添加外设模块

    下面开始添加本文章需要的外设模块,CT切到peripherals,在Drivers里面添加Siul2_Port.
    打开Siul2_Port,在PortConfigSet中添加两个CAN的引脚,主要要选对mscr号。

    图5

    图6

    点击FlexCAN模块,配置如下:

    图7

    主要修改FlexCAN operation modes为normal mode or user mode.
    然后还要检查下FlexCAN protocol clock,这里是24000000,因为不是自动获取,而是手动填入,一定要和clock界面配置的CAN0的时钟源一致,否则会通讯出问题。

    1.4 时钟检查

    CT工具打开时钟界面clock,检查FLEXCAN0的时钟如下,正好是24Mhz,所以没有问题

    图 8

    到目前为止,所有的配置都成功了,点击update code生成代码。

    1.5 加入代码

    正如上面所说,本文的目的是实现外部循环,首先发一帧数据出去,然后接受外部的CAN总线节点发来的数据并且循环出去,main.c代码添加如下:

    #include "Mcal.h"
    #include "Clock_Ip.h"
    #include "FlexCAN_Ip.h"
    #include "IntCtrl_Ip.h"
    #include "Siul2_Port_Ip.h"
    
    #define MSG_ID 20u
    #define RX_MB_IDX 1U
    #define TX_MB_IDX 0U
    volatile int exit_code = 0;
    /* User includes */
    uint8 dummyData[8] = {1,2,3,4,5,6,7,8};
    /*!
      \brief The main function for the project.
      \details The startup initialization sequence is the following:
     * - startup asm routine
     * - main()
    */
    extern void CAN0_ORED_0_31_MB_IRQHandler(void);
    
    int main(void)
    {
        /* Write your code here */
        Clock_Ip_Init(&Clock_Ip_aClockConfig[0]);
    
        Siul2_Port_Ip_Init(NUM_OF_CONFIGURED_PINS_PortContainer_0_BOARD_InitPeripherals, g_pin_mux_InitConfigArr_PortContainer_0_BOARD_InitPeripherals);
    
        IntCtrl_Ip_EnableIrq(FlexCAN0_1_IRQn);
        IntCtrl_Ip_InstallHandler(FlexCAN0_1_IRQn, CAN0_ORED_0_31_MB_IRQHandler, NULL_PTR);
    
        Flexcan_Ip_DataInfoType rx_info = {
                .msg_id_type = FLEXCAN_MSG_ID_STD,
                .data_length = 8u,
                .is_polling = TRUE,
                .is_remote = FALSE
        };
        Flexcan_Ip_MsgBuffType rxData;
           FlexCAN_Ip_Init(INST_FLEXCAN_0, &FlexCAN_State0, &FlexCAN_Config0);
           FlexCAN_Ip_SetStartMode(INST_FLEXCAN_0);
           FlexCAN_Ip_ConfigRxMb(INST_FLEXCAN_0, RX_MB_IDX, &rx_info, MSG_ID);
           rx_info.is_polling = FALSE;
           FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &rx_info, MSG_ID, (uint8 *)&dummyData);
    	    // Polling
    	    while(FlexCAN_Ip_GetTransferStatus(INST_FLEXCAN_0, TX_MB_IDX) != FLEXCAN_STATUS_SUCCESS)
    	    {
    	    	FlexCAN_Ip_MainFunctionWrite(INST_FLEXCAN_0, TX_MB_IDX);
    	    }
    
        for(;;)
        {
    
                FlexCAN_Ip_Receive(INST_FLEXCAN_0, RX_MB_IDX, &rxData, TRUE);
                while(FlexCAN_Ip_GetTransferStatus(INST_FLEXCAN_0, RX_MB_IDX) != FLEXCAN_STATUS_SUCCESS)
                {
                	FlexCAN_Ip_MainFunctionRead(INST_FLEXCAN_0, RX_MB_IDX);
                }
    
        	   // dummyData[7] = tx_cnt++;
        	   // FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &rx_info, MSG_ID, (uint8 *)&dummyData);
                FlexCAN_Ip_Send(INST_FLEXCAN_0, TX_MB_IDX, &rx_info, MSG_ID, (uint8 *)&rxData.data);
        	    // Polling
        	    while(FlexCAN_Ip_GetTransferStatus(INST_FLEXCAN_0, TX_MB_IDX) != FLEXCAN_STATUS_SUCCESS)
        	    {
        	    	FlexCAN_Ip_MainFunctionWrite(INST_FLEXCAN_0, TX_MB_IDX);
        	    }
    
        }
        FlexCAN_Ip_SetStopMode(INST_FLEXCAN_0);
        FlexCAN_Ip_Deinit(INST_FLEXCAN_0);
        return 0;
    }
    

    编译工程,并且下载到S32K344板子中去。

    二,测试结果

    测试使用PEAKCAN PCAN-USB PRO,结合PCAN-View实现。注意CAN分析仪和板子的接线一定要接对了,主要涉及3根线:CAN_H,CAN_L,GND

    图9

    本文的实物连接情况如上。打开PCAN-view,需要配置下CAN连接波特率,CAN类型。

    图 10

    按下板子上的复位按键,可以看到PCAN-View能接收到CAN数据:

    图11

    然后在发送窗口,多次改变发送数据发送,能看到接受窗口也是能接收到回环数据。

    图12

    由此可见,代码最初的外部回环功能完全实现了。

    三,坑位标点排雷

    3.1 Siul2_Port报错

    这一个坑点,也就在RTD4.0.0上遇到,RTD3.0.0上没有这个问题,所以小编一度想放弃4.0.0去搞3.0.0,实际上也这么干了,但是后面不服气,还是自己尝试出了解决方法。报错情况如下:

    图13

    解决方案:因为报错提到container,所以回到pins那边,把Function group的名字重新添加了一个新的:PortContainer_0_BOARD_InitPeripherals
    删掉了老的名字,当然这个时候你添加的pin引脚需要重新添加下,添加之后,你的port报错就不存在了。

    图14

    3.2 S32K3X4EVB-T172板载的CAN收发器

    不同版本的EVB的CAN收发器不一样,老的板子的是TJA1153 Secure HS-CAN Transiver,新的板子是TJA1443,如果是老的,那么需要先刷下收发器固件,具体可以参考这个文章:

    https://community.nxp.com/t5/S32K-Knowledge-Base/Example-S32K344-FlexCAN-Ip-TX-RX-EnhanceRXFIFO-test-S32DS3-4/ta-p/1536225

    作者:嵌联驰

    物联沃分享整理
    物联沃-IOTWORD物联网 » 【S32K3 RTD LLD系列教程篇】FlexCAN外部Loopback功能详解

    发表回复