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通讯的异常情况。
不知道你这个问题是否已经解决, 如果还没有解决的话:根据你的描述,大概分析如下,可作为参考:
关于接触不稳定:
关于设计:
最后附上我之前简单总结过的can有关的调试记录吧,希望对你有用:CAN通讯注意事项汇总
该回答引用ChatGPTc
/* 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;
}
}