ECU在实车上can通讯失败或不稳定

1,使用mcu nxp imx rt1176 flexcan3,进行can通讯,波特率500k,使用can ,非canfd;
2,单机测试,报文收发均正常;
3,ecu接入实车后,(负载率在50%左右)报文收发异常,通过log发现,报文需要多次发送才能被ecu接受,ecu往总线发的周期报文也存在丢失或者发送不成功的情况,帧率直接掉到0;
4,按照要求修改can时钟位8Mhz,位数16tq,采样点75%,问题未解决;
5,正常报文及uds诊断报文均存在问题,诊断仪发送诊断请求,ecu偶尔或正常或不及时;
6,设置了接受报文过滤;问题仍存在;

该回答引用ChatGPT
检查硬件连接
首先,您应该仔细检查硬件连接是否正确。如果连接不良或者存在电磁干扰等问题,会导致通信出现问题。确保所有线缆和连接器都正确连接并牢固。

检查ECU配置
其次,您需要检查ECU的CAN配置是否正确。确保ECU配置的波特率、采样点和位宽等参数与您的MCU配置相匹配。如果配置不正确,会导致通信出现问题。

检查总线负载
在实车测试中,总线负载是一个非常重要的因素。如果总线负载过高,可能会导致通信出现问题。您可以使用CAN分析仪监视总线负载,并尝试降低负载以改善通信稳定性。

调整CAN时钟参数
您已经尝试将CAN时钟调整为8MHz,并且位数设置为16tq,采样点为75%。如果问题仍然存在,您可以尝试调整这些参数,例如尝试增加采样点的值或调整位数的数量。

更换CAN收发器
如果以上方法都没有解决问题,您可以考虑更换CAN收发器。有时,收发器可能存在故障或不兼容性,导致通信出现问题。尝试更换收发器,可能会解决您的问题。

联系厂商技术支持
如果您尝试了上述所有方法,仍然无法解决问题,建议您联系MCU和ECU的厂商技术支持部门。他们可能会提供更详细的调试建议,以帮助您解决问题。

回答引用ChatGPT:
针对您的情况,以下是可能的解决方案:

1 确认电缆连接和电源质量。 确保CAN总线连接良好,所有连接插头紧固。 在实车上测试时,应该检查ECU的电源和地线,并确保它们的电源质量稳定。

2 调整CAN控制器的波特率。 如果报文需要多次发送才能被ECU接受,可能需要将波特率降低或提高一些。 尝试不同的波特率设置,看看哪个设置能够在实车上实现稳定的通信。

3 调整CAN总线的抑制电容。 抑制电容的值应根据所使用的CAN总线电缆长度和电缆阻抗而定。 如果抑制电容值不正确,则可能会导致报文发送不成功或丢失。

4 确认总线负载。 在实车上进行CAN通信时,应该检查总线负载是否过高。 如果负载率过高,可以考虑添加一个CAN总线分离器来减少负载。

5 检查CAN节点的硬件设计。 确认CAN节点的硬件设计是否符合CAN标准。 如果硬件设计存在问题,则可能会导致通信不稳定。

6 检查CAN控制器的中断处理程序。 如果中断处理程序存在问题,则可能会导致报文丢失或发送不成功。

7 在实车上使用示波器或逻辑分析仪。 这些工具可以帮助您诊断问题并找出通信不稳定的原因。 使用示波器可以检查CAN总线上的信号质量,并查看信号噪声或其他干扰。 使用逻辑分析仪可以查看CAN节点之间的通信和时序。

希望这些解决方案可以帮助您解决问题。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
根据您的描述,可以初步断定问题出现在ECU的CAN通讯上。可以尝试以下几种方法解决:

1.检查CAN总线的物理连接。检查线缆是否牢固连接,是否有损坏或者接触不良等问题。

2.检查电源电压和电源质量。在实车上,ECU可能会遭受到电磁干扰等原因导致CAN通讯不稳定。通过添加滤波器或使用稳压器降低电源噪声,可以帮助解决这个问题。

3.检查CAN控制器的位时序设置。参考控制器手册设置正确的位时序可以对CAN通讯进行优化,提高稳定性。

4.优化CAN程序代码。可以针对CAN的高实时性和精确度,优化CAN程序代码以提高通讯稳定性。比如使用中断驱动等方式。

以下是一个基于FlexCAN库实现的CAN发送和接受代码示例。可以根据实际需求进行修改:

#include "fsl_flexcan.h"已黑化的小白 
flexcan_handle_t flexcanHandle;
flexcan_mb_transfer_t txXfer, rxXfer;
flexcan_frame_t txFrame, rxFrame;

void CAN_Init(void)
{
    flexcan_config_t flexcanConfig;
    flexcan_timing_config_t timingConfig;
    uint32_t baudRate = 500000U;
    uint8_t loopCount = 0U;

    FLEXCAN_GetDefaultConfig(&flexcanConfig);
    flexcanConfig.baudRate = baudRate;

    /* Initialize FlexCAN module */
    FLEXCAN_Init(EXAMPLE_CAN, &flexcanConfig, EXAMPLE_CAN_CLK_FREQ);

    /* Setup FlexCAN timing. */
    FLEXCAN_SetBitTiming(EXAMPLE_CAN, &timingConfig, EXAMPLE_CAN_CLK_FREQ, baudRate);

    /* Create FlexCAN handle structure and set callback function(s). */
    FLEXCAN_TransferCreateHandle(EXAMPLE_CAN, &flexcanHandle, flexcan_callback, NULL);

    /* Setup Rx Message Buffers. */
    rxXfer.frame = rxFrame;
    rxXfer.mbIdx = EXAMPLE_CAN_RX_MESSAGE_BUFFER_NUM;
    FLEXCAN_TransferReceiveNonBlocking(EXAMPLE_CAN, &flexcanHandle, &rxXfer);

    /* Start CAN reception */
    FLEXCAN_SetTransferConfig(EXAMPLE_CAN, &flexcanHandle, EXAMPLE_CAN_RX_MESSAGE_BUFFER_NUM, true);

    /* Wait for receive MB full. */
    while (kStatus_FLEXCAN_RxFifoIdle != FLEXCAN_GetTransferStatusFlags(EXAMPLE_CAN, &flexcanHandle));

    /* Print received data. */
    printf("Received message 0x%x from MB%d\r\n", rxFrame.dataWord0, EXAMPLE_CAN_RX_MESSAGE_BUFFER_NUM);
}

void CAN_Send(void)
{
    /* Prepare Tx Frame */
    txFrame.format = kFLEXCAN_FrameFormatStandard;
    txFrame.type = kFLEXCAN_FrameTypeData;
    txFrame.id = EXAMPLE_CAN_STANDARD_ID;
    txFrame.length = 8;
    txFrame.dataWord0 = 0x12345678;

    /* Prepare Tx transfer */
    txXfer.frame = txFrame;
    txXfer.mbIdx = EXAMPLE_CAN_TX_MESSAGE_BUFFER_NUM;

    /* Await message buffer empty and send message. */
    while (FLEXCAN_GetMbStatusFlags(EXAMPLE_CAN, EXAMPLE_CAN_TX_MESSAGE_BUFFER_NUM) & 0x80UL)
        loopCount++;
    FLEXCAN_TransferSendNonBlocking(EXAMPLE_CAN, &flexcanHandle, &txXfer);
    while ((kStatus_FLEXCAN_TxIdle != FLEXCAN_GetTransferStatusFlags(EXAMPLE_CAN, &flexcanHandle)) &&
           (loopCount <= MAX_WAIT_COUNT))
        loopCount++;

    if (MAX_WAIT_COUNT < loopCount)
    {
        printf("Failed to receive message from MB%d\r\n", rxXfer.mbIdx);
    }
    else
    {
        printf("Message sent from MB%d\r\n", txXfer.mbIdx);
    }
}

void flexcan_callback(CAN_Type *base, flexcan_handle_t *handle, status_t status, uint32_t result, void *userData)
{
    switch (status)
    {
        case kStatus_FLEXCAN_RxIdle:
            break;
        case kStatus_FLEXCAN_RxFrame:
            /* Process received frames. */
            printf("Received message 0x%x from MB%d\r\n", rxFrame.dataWord0, result);
            break;
        case kStatus_FLEXCAN_TxIdle:
            break;
        case kStatus_FLEXCAN_TxFrame:
            break;
        default:
            printf("Error: %d\r\n", status);
            break;
    }
}

以上代码基于Freescale的FlexCAN库进行实现,可以根据不同的MCU和CAN库进行相应的修改。
如果我的回答解决了您的问题,请采纳!

引用chatGPT作答,根据您提供的信息,可能存在以下一些问题:

1.噪声:在实际的车辆环境中,可能会有一些噪声干扰CAN总线,从而导致报文的丢失或发送不成功。建议在车辆环境中使用CAN总线噪声抑制器等相关的设备,以尽量减小噪声对CAN总线的影响。

2.稳定性问题:您提到在负载率在50%左右的情况下出现了问题,这可能是因为CAN总线的带宽不足,从而导致报文发送和接收的不稳定。可以尝试减少CAN总线上的负载,或者使用其他更高带宽的通讯方式。

3.CAN总线通讯参数:您提到已经尝试过调整CAN时钟等参数,但问题未解决。还可以尝试调整CAN总线上其他的参数,比如位宽、采样点等,以尽可能减小误码率和干扰等问题。

4.软件问题:还可能存在软件方面的问题,比如驱动程序、应用程序等。建议检查代码,排除相关的软件问题。

5.硬件问题:最后,也可能存在硬件方面的问题,比如线路连接、电源噪声等。建议检查CAN总线的线路连接和电源供应,确保没有问题。

需要进一步排查以上可能的问题,以解决CAN通讯的异常情况。

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^

根据你的描述,大概分析如下,可作为参考:

  1. 由于有通讯成功的现象出现,只是不稳定,因此排除线路连接错误问题;
  2. 问题表现主要为通讯不稳定,主要有两种原因:1)接触不稳定;2)设计不合理
  • 关于接触不稳定:

    • 建议仔细检查线缆的连接,特别各个连接处,甚至可以用力拉扯或者震动实验试下
  • 关于设计:

    • 你虽然有调整采样点,但不是单独调一个就行,你要把总线上所有设备的采样点尽可能设置差不多,推荐70-90之间
    • 终端电阻设计不合理,can总线网络并不是每个节点都需要终端电阻的,而且终端电阻也不是都是120欧姆,需要根据你实际的拓扑网络情况来,建议你先梳理下你整机的拓扑网络,推荐采用手牵手方案拓扑网络,并在两个终端节点设置采样电阻
    • 抓波形,调这东西要稳定,波形必须得抓的,信号质量心里要有底的!!!

最后附上我之前简单总结过的can有关的调试记录吧,希望对你有用:CAN通讯注意事项汇总

该回答引用ChatGPT
首先需要进行一些排查工作:

1. 确认实车上CAN总线是否正常,是否有其他ECU导致CAN总线干扰;
2. 确认使用的CAN总线是否为高可靠性的CAN总线;
3. 确认CAN总线的终端电阻是否正确接入。

在确认以上问题没有明显异常后,可以针对代码进行分析:

1. 检查CAN发送函数是否正常。由于在单机测试中没有问题,因此可以考虑ECU发送的频率是否过高,导致总线负载过大,应该增加发送报文的延时时间或降低发送报文的频率,避免总线负载过大导致的通讯异常;
2. 检查CAN接收函数是否正常,是否正确处理了CAN总线抢占和数据丢失的情况。如果ECU接收的频率过高,会有多个ECU同时竞争总线,导致抢占和数据丢失。此时应该增加接收报文的延时时间或降低接收报文的频率,避免总线抢占和数据丢失导致的通讯异常;
3. 检查计算CAN波特率的参数是否正确。使用CAN工具(例如CANoe)进行波特率计算,确认计算结果和代码中的参数是否一致;
4. 检查CAN总线的过滤器设置是否正确。过滤器的设置不正确会导致ECU接收到不属于自己的报文,从而造成通讯异常。

代码方面,可以参考以下示例进行检查和调整:
c
/* CAN初始化函数 */
void InitCAN()
{
/* 确认总线是否空闲 */
if (CAN1->TSR & CAN_TSR_TME0)
{
/* 初始化CAN控制器 */
CAN1->MCR |= CAN_MCR_RESET; // 复位CAN控制器
while((CAN1->MCR & CAN_MCR_RESET) != 0); // 等待控制器复位完成

/* 配置CAN控制器 */
CAN1->MCR &= ~CAN_MCR_ABOM; // 禁止自动总线关闭
CAN1->MCR |= CAN_MCR_TTCM; // 启用时间戳计数器
CAN1->MCR &= ~CAN_MCR_AWUM; // 禁止自动唤醒模式
CAN1->MCR &= ~CAN_MCR_SLEEP; // 停止睡眠模式
CAN1->MCR &= ~CAN_MCR_INRQ; // 中止CAN初始化进程
while((CAN1->MSR & CAN_MSR_INAK) != 0); // 等待控制器退出初始化模式

/* 配置CAN波特率 */
CAN1->BTR &= ~(CAN_BTR_SILM | CAN_BTR_LBKM | CAN_BTR_TS1 | CAN_BTR_TS2 | CAN_BTR_BRP);
CAN1->BTR |= CAN_BTR_TS1_6TQ | CAN_BTR_TS2_7TQ | CAN_BTR_BRP_6; // 波特率500Kbps

/* 配置CAN过滤器 */
CAN1->FA1R &= ~CAN_FA1R_FACT0; // 禁用过滤器 0
CAN1->FM1R &= ~CAN_FM1R_FBM0; // 设置过滤器 0 为标准 ID
CAN1->FS1R &= ~CAN_FS1R_FSC0; // 设置过滤器 0 为单个 16 位过滤器
CAN1->FFA1R &= ~CAN_FFA1R_FFA0; // 过滤器 0 指向FIFO 0
CAN1->sFilterRegister[0].FR1 = (0x123 << 5) | CAN_FIR_IDE; // 过滤器 0 指定 ID 为 0x123 的标准帧
CAN1->FA1R |= CAN_FA1R_FACT0; // 启用过滤器 0

/* 启用CAN控制器 */
CAN1->MCR &= ~CAN_MCR_INRQ; // 退出初始化进程
while((CAN1->MSR & CAN_MSR_INAK) != 0); // 等待控制器退出初始化模式

/* 注册CAN中断 */
NVIC_EnableIRQ(CAN1_TX_IRQn);
NVIC_EnableIRQ(CAN1_RX0_IRQn);
}
}

/* CAN发送函数 */
void SendCANMessage(uint8_t* pData, uint32_t len, uint32_t id)
{
uint32_t transmitMailbox = 0;
uint32_t transmissionPending = 1;
uint32_t timeout = 0;
CanTxMsgTypeDef TxMessage;

/* 填充CAN发送报文 */
TxMessage.StdId = id;
TxMessage.IDE = CAN_ID_STD;
TxMessage.RTR = CAN_RTR_DATA;
TxMessage.DLC = len;
memcpy(&(TxMessage.Data), pData, len);

/* 在FIFO 0 检查 MAILBOX 是否有效并开始传输 */
transmitMailbox = (CAN1->TSR & CAN_TSR_TME0);
if (transmitMailbox != 0)
{
CAN1->sTxMailBox[transmitMailbox - 1].TIR &= ~CAN_TI0R_TXRQ; // 禁止发送请求

/* 填充发送邮箱 */
CAN1->sTxMailBox[transmitMailbox - 1].TIR &= ~(CAN_TI0R_IDE | CAN_TI0R_RTR | CAN_TI0R_TXRQ);
if (TxMessage.IDE == CAN_ID_STD)
{
CAN1->sTxMailBox[transmitMailbox - 1].TIR |= (TxMessage.StdId << 21) | CAN_TI0R_TXRQ;
}
else
{
CAN1->sTxMailBox[transmitMailbox - 1].TIR |= ((TxMessage.StdId << 21) | CAN_TI0R_IDE | CAN_TI0R_RTR | CAN_TI0R_TXRQ);
}

/* 填充发送数据 */
CAN1->sTxMailBox[transmitMailbox - 1].TDLR = ((uint32_t)TxMessage.Data[3] << 24) | ((uint32_t)TxMessage.Data[2] << 16) | ((uint32_t)TxMessage.Data[1] << 8) | ((uint32_t)TxMessage.Data[0]);
CAN1->sTxMailBox[transmitMailbox - 1].TDHR = ((uint32_t)TxMessage.Data[7] << 24) | ((uint32_t)TxMessage.Data[6] << 16) | ((uint32_t)TxMessage.Data[5] << 8) | ((uint32_t)TxMessage.Data[4]);

/* 等待传输完成 */
timeout = 0;
while (transmissionPending != 0)
{
transmissionPending = (CAN1->TSR & (CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2)) == 0;
timeout++;
if (timeout > CAN_TIMEOUT) {
break;
}
}
}
}

/* CAN接收函数 */
void ReceiveCANMessage(CanRxMsgTypeDef* RxMessage)
{
if ((CAN1->RF0R & CAN_RF0R_FMP0) != 0)
{
/* 读取接收到的报文 */
RxMessage->StdId = (CAN1->sFIFOMailBox[0].RIR & CAN_RI0R_STID) >> CAN_TI0R_STID_Pos;
RxMessage->RTR = (CAN1->sFIFOMailBox[0].RIR & CAN_RI0R_RTR) >> CAN_TI0R_RTR_Pos;
RxMessage->DLC = (CAN1->sFIFOMailBox[0].RDTR & CAN_RDT0R_DLC);
RxMessage->FMI = (CAN1->sFIFOMailBox[0].RDTR & CAN_RDT0R_FMI) >> CAN_RDT0R_FMI_Pos;
memcpy(&(RxMessage->Data), &(CAN1->sFIFOMailBox[0].RDLR), sizeof(CAN_TypeDef));
memcpy(&(RxMessage->Data + 4), &(CAN1->sFIFOMailBox[0].RDHR), sizeof(CAN_TypeDef));

/* 释放接收到的空间 */
CAN1->RF0R |= CAN_RF0R_RFOM0;
}
}