AURIX™ TC397 MCMCAN解析demo(勘误)

该博客围绕嵌入式CAN通讯展开。项目初期用英飞凌示例程序两节点环回通讯,后参考例程实现CAN收发及报文解析时出现问题,通过打印寄存器确定CAN发送主动错误。经分析排除链路和控制器问题,最终依据Demo板手册找到问题,修改代码后通讯成功。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目场景:

学习CAN总线相关知识是每个汽电行业从业者的必修课之一,使用英飞凌TC397芯片作为MCU进行通讯中,首先进行CAN收发和解析实验,在自己的调试和学习中出现了一些问题,在此记录,望各位兄台少走弯路:

  • 此Demo初期是用英飞凌示例程序中的两节点通过环回模式通讯,当发送和接收到数据后点亮LED
    具体可参考:MCMCAN_1_KIT_TC397_TFT
  • 第二部分为了实现CAN收发功能,并在中断中解析报文,参考weifengdq的MCMCAN例程
  • 当我将大佬代码放到自己的板子上运行的时候出现了问题…

问题描述

*英飞凌MCMCAN模块和上位机无法通讯*
通过 AURIX Development Studio(当然HighTec也可以)打印关键的IR寄存器:
IR错误寄存器

可以看到BO位置1,总线关闭状态,说明CAN总线发生了错误。

继续查看ECR寄存器确定错误类型:
在这里插入图片描述

由寄存器说明可知,TEC和CEL置位,说明CAN发送出现主动错误。说明链路没有问题,是程序和板子本身的问题。

具体寄存器的详细描述我摘下来芯片手册,可以看一下

  • IR0
    在这里插入图片描述

  • ERC0
    在这里插入图片描述


原因分析:

问题分析如下:
1.数据链路的问题 CAN节点–CAN线–CAN卡–上位机(通过寄存器排除)
2.板载的CAN控制器问题(环回模式正常排除)
3.最后就是代码问题了,请看下面

CAN初始化部分

void initCAN0(void)
{
    /*******CAN module configuration and initialization*******/
    IfxCan_Can_initModuleConfig(&g_mcmcan.canConfig, &MODULE_CAN0);
    IfxCan_Can_initModule(&g_mcmcan.canModule, &g_mcmcan.canConfig);
    /*******CAN00 node configuration and initialization*******/
    IfxCan_Can_initNodeConfig(&g_mcmcan.canNodeConfig, &g_mcmcan.canModule);
    g_mcmcan.canNodeConfig.nodeId = IfxCan_NodeId_0;
    g_mcmcan.canNodeConfig.clockSource = IfxCan_ClockSource_both;
    g_mcmcan.canNodeConfig.frame.type = IfxCan_FrameType_transmitAndReceive;
    g_mcmcan.canNodeConfig.frame.mode = IfxCan_FrameMode_standard;  //Classic CAN

    g_mcmcan.canNodeConfig.txConfig.txMode = IfxCan_TxMode_dedicatedBuffers;
    g_mcmcan.canNodeConfig.txConfig.dedicatedTxBuffersNumber = 255;
    g_mcmcan.canNodeConfig.txConfig.txBufferDataFieldSize = IfxCan_DataFieldSize_8;

    g_mcmcan.canNodeConfig.rxConfig.rxMode = IfxCan_RxMode_dedicatedBuffers;
    g_mcmcan.canNodeConfig.rxConfig.rxBufferDataFieldSize = IfxCan_DataFieldSize_8;

    g_mcmcan.canNodeConfig.filterConfig.extendedListSize = 255; //Extended Frame
    g_mcmcan.canNodeConfig.filterConfig.messageIdLength = IfxCan_MessageIdLength_extended;
    g_mcmcan.canNodeConfig.baudRate.baudrate = 500000;   //500KBaud
    //transmit interrupt
    g_mcmcan.canNodeConfig.interruptConfig.transmissionCompletedEnabled = TRUE;
    g_mcmcan.canNodeConfig.interruptConfig.traco.priority = ISR_PRIORITY_CAN_TX;
    g_mcmcan.canNodeConfig.interruptConfig.traco.interruptLine = IfxCan_InterruptLine_0;
    g_mcmcan.canNodeConfig.interruptConfig.traco.typeOfService = IfxSrc_Tos_cpu0;
    //receive interrupt
    g_mcmcan.canNodeConfig.interruptConfig.messageStoredToDedicatedRxBufferEnabled = TRUE;
    g_mcmcan.canNodeConfig.interruptConfig.reint.priority = ISR_PRIORITY_CAN_RX;
    g_mcmcan.canNodeConfig.interruptConfig.reint.interruptLine = IfxCan_InterruptLine_1;
    g_mcmcan.canNodeConfig.interruptConfig.reint.typeOfService = IfxSrc_Tos_cpu0;
    //binding pin
    IFX_CONST IfxCan_Can_Pins Can00_pins = 
    {
       &IfxCan_TXD00_P20_8_OUT,   IfxPort_OutputMode_pushPull, // CAN00_TX
       &IfxCan_RXD00B_P20_7_IN,   IfxPort_InputMode_pullUp,    // CAN00_RX
       IfxPort_PadDriver_cmosAutomotiveSpeed4
    };
    g_mcmcan.canNodeConfig.pins = &can00_pins;
    IfxCan_Can_initNode(&g_mcmcan.can00Node, &g_mcmcan.canNodeConfig);
    /*******CAN filter configuration and initialization*******/
    g_mcmcan.canFilter.number = 0;
    g_mcmcan.canFilter.elementConfiguration = IfxCan_FilterElementConfiguration_storeInRxBuffer;
    g_mcmcan.canFilter.id1 = CAN_MESSAGE_RX_ID1;
    g_mcmcan.canFilter.rxBufferOffset = IfxCan_RxBufferId_0;
    IfxCan_Can_setExtendedFilter(&g_mcmcan.can02Node, &g_mcmcan.canFilter);
    g_mcmcan.canFilter.number = 1;
    g_mcmcan.canFilter.elementConfiguration = IfxCan_FilterElementConfiguration_storeInRxBuffer;
    g_mcmcan.canFilter.id1 = CAN_MESSAGE_RX_ID2;
    g_mcmcan.canFilter.rxBufferOffset = IfxCan_RxBufferId_0;
    IfxCan_Can_setExtendedFilter(&g_mcmcan.can02Node, &g_mcmcan.canFilter);
    g_mcmcan.canFilter.number = 2;
    g_mcmcan.canFilter.elementConfiguration = IfxCan_FilterElementConfiguration_storeInRxBuffer;
    g_mcmcan.canFilter.id1 = CAN_MESSAGE_RX_ID3;
    g_mcmcan.canFilter.rxBufferOffset = IfxCan_RxBufferId_0;
    IfxCan_Can_setExtendedFilter(&g_mcmcan.can02Node, &g_mcmcan.canFilter);

}

发送函数部分

void initMsg(void)
{
    IfxCan_Can_initMessage(&g_mcmcan.txMsg);
    g_mcmcan.txMsg.messageId = CAN_MESSAGE_TX_ID0;
    g_mcmcan.txMsg.bufferNumber = 0;
    g_mcmcan.txMsg.dataLengthCode = IfxCan_DataLengthCode_8;//8 bytes
    g_mcmcan.txMsg.frameMode = IfxCan_FrameMode_standard;   //Classic CAN
    g_mcmcan.txMsg.messageIdLength=IfxCan_MessageIdLength_extended;  //Extended Frame
    g_mcmcan.txData[0] = g_mcmcan.rxData[0];
    g_mcmcan.txData[1] = g_mcmcan.rxData[1];
    while(IfxCan_Status_notSentBusy ==
            IfxCan_Can_sendMessage(&g_mcmcan.can02Node, &g_mcmcan.txMsg, &g_mcmcan.txData[0]) )
    {
    }
}

看起来一切正常,环回模式中用的CAN0,CAN1实现收发,怎么把环回打开就不能用了,我百思不得其解。继续阅读芯片手册,改代码,求助大佬,翻论坛,无果。

直到我打开了在文件夹里尘封已久的TC397 demo板手册…


解决方案:

在Demo板3.10节MultiCAN中写道:

On the board is one CAN transceiver (CAN FD capable) connected to the CAN module 0 node 0 (P20.7 and P20.8)
on TC3X7. Optional the CAN transceiver can be connected to CAN module 0 node 2 (P10.2 and P10.3). To do this
remove resistor R269, R270 and assemble R257, R258 with 0R Resistor. For location of this resistors please see the
Top Layer assembling Figure 7-5.
Note: If the board is assembled with TC397 and TLF35584QVVS2 (3,3V version) then the SDMMC module is
connected directly to the SD card. In this case P20.7 and P20.8 are used by the SDMMC and the
transceiver is connected to P10.2 and P10.3.
The transceiver is connected to an IDC10 plug. For the pinout of IDC10 plug see Figure 6-4. You can use a IDC
female connector with crimpconnector, flat cable and SUB-D 9 plug with crimpconnector to have a 1:1 adapter
to SUB-D 9.

大概意思就是:在打板时将SD卡的SDMMC 使用 P20.7 和 P20.8 而CAN收发器连接到 P10.2 和 P10.3,因此要使用CAN2节点和P10.2 和,P10.3口。

太坑爹了!!!

知道问题后修改代码(CPU0全部代码附上):

#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include "Ifx_Types.h"
#include "IfxCan_Can.h"
#include "IfxCan.h"
#include "IfxCpu_Irq.h"
#include "IfxPort.h"
#include "Bsp.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"
#include "IfxStm.h"
#include "IfxAsclin_Asc.h"

//CPU同步
IFX_ALIGN(4) IfxCpu_syncEvent g_cpuSyncEvent = 0;

/******************************************LED define***********************************************************************/
#define LED0                     &MODULE_P13,0
#define LED1                     &MODULE_P13,1
#define LED2                     &MODULE_P13,2
#define LED3                     &MODULE_P13,3
/******************************************CAN define*************************************************************************/
#define MODULE_CAN0_RAM    0xF0200000
#define NODE0_RAM_OFFSET   0x0

#define CAN_MESSAGE_TX_ID0             (uint32)0xC6
#define CAN_MESSAGE_RX_ID1             (uint32)0xb4
#define CAN_MESSAGE_RX_ID2             (uint32)0x8C
#define CAN_MESSAGE_RX_ID3             (uint32)0x1A3

#define ISR_PRIORITY_CAN_TX         2                       /* Define the CAN TX interrupt priority                 */
#define ISR_PRIORITY_CAN_RX         1                       /* Define the CAN RX interrupt priority                 */
#define MAXIMUM_CAN_DATA_PAYLOAD    2                       /* Define maximum classical CAN payload in 4-byte words */

#define WAIT_TIME                1000


typedef struct
{
    IfxCan_Can_Config canConfig;                            /* CAN module configuration structure                   */
    IfxCan_Can canModule;                                   /* CAN module handle                                    */
    IfxCan_Can_Node can02Node;                             /* CAN source node handle data structure                */
    IfxCan_Can_NodeConfig canNodeConfig;                    /* CAN node configuration structure                     */
    IfxCan_Filter canFilter;                                /* CAN filter configuration structure                   */
    IfxCan_Message txMsg;                                   /* Transmitted CAN message structure                    */
    IfxCan_Message rxMsg;                                   /* Received CAN message structure                       */
    uint32 txData[MAXIMUM_CAN_DATA_PAYLOAD];                /* Transmitted CAN data array                           */
    uint32 rxData[MAXIMUM_CAN_DATA_PAYLOAD];                /* Received CAN data array                              */
} McmcanType;

McmcanType                  g_mcmcan;

/********************************************CAN Implement*************************************************************************************/
void initMsg(void);

IFX_INTERRUPT(canIsrTxHandler, 0, ISR_PRIORITY_CAN_TX);
void canIsrTxHandler(void)
{
    IfxCan_Node_clearInterruptFlag(g_mcmcan.can02Node.node, IfxCan_Interrupt_transmissionCompleted);
    IfxPort_togglePin(LED0);   
}

IFX_INTERRUPT(canIsrRxHandler, 0, ISR_PRIORITY_CAN_RX);
void canIsrRxHandler(void)
{
    /* Clear the "Message stored to Dedicated RX Buffer" interrupt flag */
    IfxCan_Node_clearInterruptFlag(g_mcmcan.can02Node.node, IfxCan_Interrupt_messageStoredToDedicatedRxBuffer);
    /* Clear the "New Data" flag; as long as the "New Data" flag is set, the respective Rx buffer is
     * locked against updates from received matching frames.
     */
    IfxCan_Node_clearRxBufferNewDataFlag(g_mcmcan.can02Node.node, g_mcmcan.canFilter.rxBufferOffset);
    /* Read the received CAN message */
    IfxCan_Can_readMessage(&g_mcmcan.can02Node, &g_mcmcan.rxMsg, g_mcmcan.rxData);

    /* Check if the received data matches with the transmitted one */
    if(g_mcmcan.rxMsg.messageId == CAN_MESSAGE_RX_ID1)
    {
            IfxPort_setPinState(LED1, IfxPort_State_low);   //LED ON

            uint8 Checksum = (g_mcmcan.rxData[1] >>24) & 0xFF;
            uint8 WheelSpeed_FR = (g_mcmcan.rxData[1] >> 16) & 0xFF;
            uint8 WheelSpeed_FL = (g_mcmcan.rxData[1] >> 8) & 0xFF;
            uint8 ABS_VehicleSpeed = g_mcmcan.rxData[1] & 0xFF;
            uint8 LiveConter = (g_mcmcan.rxData[0]>>24) & 0xFF ;
            uint8 ABS_DrivingDirection = (g_mcmcan.rxData[0] >> 16) & 0xFF;
            uint32 speedKmPerHour = ABS_VehicleSpeed;
            float speedMps = (float)speedKmPerHour * 1000.0 / 3600.0;

            printf("*********************************************************\n");
            printf("ABS_VehicleSpeed: %.2f m/s\n", speedMps);
            printf("WheelSpeed_FL: %u kmh\n", WheelSpeed_FL);
            printf("WheelSpeed_FR: %u kmh\n", WheelSpeed_FR);
            switch(ABS_DrivingDirection)
            {
                case 0 :  printf("front\n");
                    break;
                case 1 :  printf("back\n");
                    break;
                case 2 :  printf("left\n");
                    break;
                case 3 :  printf("right\n");
                    break;
            }
            printf("Checksum: %u\n", Checksum);
            printf("LiveConter: %u\n", LiveConter);
            printf("*********************************************************\n");
        }
        else
        {
            IfxPort_setPinState(LED1, IfxPort_State_high);  //LED OFF
        }
    if(g_mcmcan.rxMsg.messageId == CAN_MESSAGE_RX_ID2)
    {
        initMsg();
    }
    else
    {
        IfxPort_setPinState(LED2, IfxPort_State_high);
    }
    if(g_mcmcan.rxMsg.messageId == CAN_MESSAGE_RX_ID3)
    {
       IfxPort_setPinState(LED3, IfxPort_State_low);
    }
    else
    {
       IfxPort_setPinState(LED3, IfxPort_State_high);
    }
}

void initCAN0(void)
{
    /*******CAN module configuration and initialization*******/
    IfxCan_Can_initModuleConfig(&g_mcmcan.canConfig, &MODULE_CAN0);
    IfxCan_Can_initModule(&g_mcmcan.canModule, &g_mcmcan.canConfig);

    /*******CAN00 node configuration and initialization*******/
    IfxCan_Can_initNodeConfig(&g_mcmcan.canNodeConfig, &g_mcmcan.canModule);
    g_mcmcan.canNodeConfig.nodeId = IfxCan_NodeId_2;
    g_mcmcan.canNodeConfig.clockSource = IfxCan_ClockSource_both;
    g_mcmcan.canNodeConfig.frame.type = IfxCan_FrameType_transmitAndReceive;
    g_mcmcan.canNodeConfig.frame.mode = IfxCan_FrameMode_standard;  //Classic CAN
    g_mcmcan.canNodeConfig.txConfig.txMode = IfxCan_TxMode_dedicatedBuffers;
    g_mcmcan.canNodeConfig.txConfig.dedicatedTxBuffersNumber = 255;
    g_mcmcan.canNodeConfig.txConfig.txBufferDataFieldSize = IfxCan_DataFieldSize_8;
    g_mcmcan.canNodeConfig.rxConfig.rxMode = IfxCan_RxMode_dedicatedBuffers;
    g_mcmcan.canNodeConfig.rxConfig.rxBufferDataFieldSize = IfxCan_DataFieldSize_8;
    g_mcmcan.canNodeConfig.filterConfig.extendedListSize = 255; //Extended Frame
    g_mcmcan.canNodeConfig.filterConfig.messageIdLength = IfxCan_MessageIdLength_extended;
    g_mcmcan.canNodeConfig.messageRAM.extendedFilterListStartAddress = 0x100;   //Extended Frame
    g_mcmcan.canNodeConfig.messageRAM.rxBuffersStartAddress = 0x200;
    g_mcmcan.canNodeConfig.messageRAM.txBuffersStartAddress = 0x400;
    g_mcmcan.canNodeConfig.messageRAM.baseAddress = MODULE_CAN0_RAM + NODE0_RAM_OFFSET;
    g_mcmcan.canNodeConfig.baudRate.baudrate = 500000;   //500KBaud
    //transmit interrupt
    g_mcmcan.canNodeConfig.interruptConfig.transmissionCompletedEnabled = TRUE;
    g_mcmcan.canNodeConfig.interruptConfig.traco.priority = ISR_PRIORITY_CAN_TX;
    g_mcmcan.canNodeConfig.interruptConfig.traco.interruptLine = IfxCan_InterruptLine_0;
    g_mcmcan.canNodeConfig.interruptConfig.traco.typeOfService = IfxSrc_Tos_cpu0;
    //receive interrupt
    g_mcmcan.canNodeConfig.interruptConfig.messageStoredToDedicatedRxBufferEnabled = TRUE;
    g_mcmcan.canNodeConfig.interruptConfig.reint.priority = ISR_PRIORITY_CAN_RX;
    g_mcmcan.canNodeConfig.interruptConfig.reint.interruptLine = IfxCan_InterruptLine_1;
    g_mcmcan.canNodeConfig.interruptConfig.reint.typeOfService = IfxSrc_Tos_cpu0;
    //binding pin
    IFX_CONST IfxCan_Can_Pins can02_pins = {
           &IfxCan_TXD02_P10_3_OUT,   IfxPort_OutputMode_pushPull,
           &IfxCan_RXD02E_P10_2_IN,   IfxPort_InputMode_pullUp,
           IfxPort_PadDriver_cmosAutomotiveSpeed4
    };
    g_mcmcan.canNodeConfig.pins = &can02_pins;
    IfxCan_Can_initNode(&g_mcmcan.can02Node, &g_mcmcan.canNodeConfig);
    /*******CAN filter configuration and initialization*******/
    g_mcmcan.canFilter.number = 0;
    g_mcmcan.canFilter.elementConfiguration = IfxCan_FilterElementConfiguration_storeInRxBuffer;
    g_mcmcan.canFilter.id1 = CAN_MESSAGE_RX_ID1;
    g_mcmcan.canFilter.rxBufferOffset = IfxCan_RxBufferId_0;
    IfxCan_Can_setExtendedFilter(&g_mcmcan.can02Node, &g_mcmcan.canFilter);
    g_mcmcan.canFilter.number = 1;
    g_mcmcan.canFilter.elementConfiguration = IfxCan_FilterElementConfiguration_storeInRxBuffer;
    g_mcmcan.canFilter.id1 = CAN_MESSAGE_RX_ID2;
    g_mcmcan.canFilter.rxBufferOffset = IfxCan_RxBufferId_0;
    IfxCan_Can_setExtendedFilter(&g_mcmcan.can02Node, &g_mcmcan.canFilter);
    g_mcmcan.canFilter.number = 2;
    g_mcmcan.canFilter.elementConfiguration = IfxCan_FilterElementConfiguration_storeInRxBuffer;
    g_mcmcan.canFilter.id1 = CAN_MESSAGE_RX_ID3;
    g_mcmcan.canFilter.rxBufferOffset = IfxCan_RxBufferId_0;
    IfxCan_Can_setExtendedFilter(&g_mcmcan.can02Node, &g_mcmcan.canFilter);
}
void initLED(void)
{
    IfxPort_setPinMode(LED0, IfxPort_Mode_outputPushPullGeneral);    /* Initialize LED port pin                      */
    IfxPort_setPinMode(LED1, IfxPort_Mode_outputPushPullGeneral);
    IfxPort_setPinMode(LED2, IfxPort_Mode_outputPushPullGeneral);
    IfxPort_setPinMode(LED3, IfxPort_Mode_outputPushPullGeneral);
    IfxPort_setPinState(LED0, IfxPort_State_high);                   /* Turn off LED (LED is low-level active)       */
    IfxPort_setPinState(LED1, IfxPort_State_high);
    IfxPort_setPinState(LED2, IfxPort_State_high);
    IfxPort_setPinState(LED3, IfxPort_State_high);
}
void initMsg(void)
{
    IfxCan_Can_initMessage(&g_mcmcan.txMsg);
    g_mcmcan.txMsg.messageId = CAN_MESSAGE_TX_ID0;
    g_mcmcan.txMsg.bufferNumber = 0;
    g_mcmcan.txMsg.dataLengthCode = IfxCan_DataLengthCode_8;//8 bytes
    g_mcmcan.txMsg.frameMode = IfxCan_FrameMode_standard;   //Classic CAN
    g_mcmcan.txMsg.messageIdLength=IfxCan_MessageIdLength_extended;  //Extended Frame
    g_mcmcan.txData[0] = g_mcmcan.rxData[0];
    g_mcmcan.txData[1] = g_mcmcan.rxData[1];
    while(IfxCan_Status_notSentBusy ==
            IfxCan_Can_sendMessage(&g_mcmcan.can02Node, &g_mcmcan.txMsg, &g_mcmcan.txData[0]) )
    {
    }
}

void core0_main(void)
{
    IfxCpu_enableInterrupts();
    IfxScuWdt_disableCpuWatchdog(IfxScuWdt_getCpuWatchdogPassword());
    IfxScuWdt_disableSafetyWatchdog(IfxScuWdt_getSafetyWatchdogPassword());
    IfxCpu_emitEvent(&g_cpuSyncEvent);
    IfxCpu_waitEvent(&g_cpuSyncEvent, 1);
    initLED();
    initCAN0();

    while(1)
    {
        waitTime(IfxStm_getTicksFromMilliseconds(BSP_DEFAULT_TIMER, WAIT_TIME));
    }
}

代码编译运行正常,接上CAN卡发送数据

配置ID为0xb4的帧做报文解析,ID为0x8c直接转发,ID为0x1a3点灯
在这里插入图片描述

可以看到五帧报文全部发送成功!
在这里插入图片描述

AURIX Development Studio 模拟串口print如下:
在这里插入图片描述

到此为止,MCMCAN收发并解析问题解决,我也顺利完成了师父交给我的学习任务,加油汽电人!
在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炸弹气旋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值