This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TCAN4551-Q1:CAN 数据接收数据包丢失

Guru**** 2466550 points
Other Parts Discussed in Thread: TCAN4550

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1474535/tcan4551-q1-can-data-receive-packet-loss

器件型号:TCAN4551-Q1
主题中讨论的其他器件:TCAN4550

工具与软件:

团队成员、您好!

我们正在开发 TCAN4551、并使用了以下链接中的 CAN 堆栈:

https://github.com/TexasInstruments/CC26XX-TCAN4550-EXAMPLES/tree/master/source/ti/can/tcan4x5x

我们使用了水线功能、其中配置了水线位60、并且在接收到60个数据包并进行以下配置时得到水线中断:

静态空 TCAN4550_SetConfiguration (void)

uint8_t TX_param_size;
uint8_t rx_param_size;

//清除由于 MCU 启动期间引脚多路复用发生变化而可能设置的任何 SPI ERR 标志
TCAN4x5x_IERR Device_Clear ();

/*第一步尝试清除所有中断*/
/*初始化为0以使所有位都设置为0 */
TCAN4x5x_TCANDEV_IE Device_Interrupt_Enable ={0};

/*为简单起见、禁用所有非 MCAN 相关中断*/
TCAN4x5x_TCAN74ruptEnable Device_Configure (&DEV_ie);

/*设置一个新的 MCAN IR 对象以便轻松执行中断检查*/
TCAN4x5x_TCANDev_ir Device_Interrupts ={0};

/*请求使用当前器件(非 MCAN)中断值更新结构*/
TCAN4x5x_TCAN45nrupts Device_Read (&DEV_ir);

/*如果设置了上电中断标志*/
if (dev_ir.PWRON)

/*清除它,因为如果它没有在~4分钟内清除,它进入睡眠*/
TCAN4x5x_TCAN45nrupts Device_Clear (&DEV_ir);
}

/*配置 CAN 总线速度*/
/*采用40 MHz 晶振的500k 仲裁(40E6 /(57 + 22 + 1 (同步))=)*/
/* TCAN_Timing =((40E6 / BitRatePrescaler)/(TqBeforeSamplePoint + TqAfterSamplePoint)*/
/*配置 CAN 总线速度*/
/*采用40 MHz 晶振的500k 仲裁(40E6 /(57 + 22 + 1 (同步))= 500E3)*/
TCAN4x5x_MCAN_TCANNomTiming Nominal_Timing_Simple ={0};
TCANNomTiming.NominalBitRatePrescaler = 2;
TCANNomTiming.NominalTqBeforeSamplePoint = 32;
TCANNomTiming.NominalTqAfterSamplePoint = 8;

//带有40 MHz 晶体的2Mbps CAN FD (40E6/(15 + 5)= 2E6)*
TCAN4x5x_MCAN_TCANDataTiming Data_Timing_Simple ={0};
TCANDataTiming.DataBitRatePrescaler = 1;
TCANDataTiming.DataTqBeforeSamplePoint = 15;
TCANDataTiming.DataTqAfterSamplePoint = 5;

/*配置 MCAN 内核设置*/
/*记住要初始化为0,否则你会得到随机的垃圾! */
TCAN4x5x_MCAN_CCCR_Config cccrConfig ={0};

/* CAN FD 模式启用*/
// cccrConfig.FDOE = 0;
cccrConfig.FDOE = 0;

/* CAN FD 比特率切换启用*/
cccrConfig.BRSE = 1;

/*配置默认的 CAN 数据包过滤设置*/
TCAN4x5x_MCAN_GFC Global_Filter_Configuration ={0};

/*拒绝远程帧(TCAN4x5x 不支持此功能)*/
GFC.RRFE = 1;

/*拒绝远程帧(TCAN4x5x 不支持此功能)*/
GFC.RRFS = 1;

/*传入消息与过滤器不匹配时的默认行为是接受 RXFIO0以接收扩展 ID 消息(29位 ID)*/
GFC.ANFE = TCAN4x5x_GFC_REJECT;//TCAN4x5x_GFC_ACCEP_INTO_RXFIFO0;

/*传入消息与标准 ID 消息(11位 ID)的 RXFIO0接收过滤器时的默认行为*/
GFC.ANFS = TCAN4x5x_GFC_REJECT;//TCAN4x5x_GFC_ACCEP_INTO_RXFIFO0;


RX_PARAM_SIZE = 60;
TX_PARAM_SIZE = 0;

TCAN4x5x_MRAM_Config MRAMConfiguration ={0};
//标准 ID 元素数量、必须为定义的每个元素向 MRAM 写入过滤器
MRAMConfiguration.SIDNumElements = 3;
//扩展 ID 元素数量、必须为定义的每个元素向 MRAM 写入过滤器
MRAMConfiguration.XIDNumElements = 16;
// RX0元素数量
MRAMConfiguration.Rx0NumElements = Rx_PARAM_SIZE;
// RX0数据有效载荷大小(使用定义)
MRAMConfiguration.Rx0ElementSize = MRAM_8_MRAM Byte_Data;
// MRAMConfiguration.Rx0ElementSize = MRAM_64_MRAM Byte_Data;
// Rx1单元数
MRAMConfiguration.Rx1NumElements = 0;
// Rx1数据有效载荷大小(使用定义)
MRAMConfiguration.Rx1ElementSize = MRAM_64_MRAM Byte_Data;
// RX 缓冲区元素数量
MRAMConfiguration.RxBufNumElements = 0;
// RX 缓冲区数据有效载荷大小(使用定义)
MRAMConfiguration.RxBufElementSize = MRAM_64_MRAM Byte_Data;
// TX 事件 FIFO 元素数量
MRAMConfiguration.TxEventFIFONumElements = 0;
// TX 缓冲区元素数量
MRAMConfiguration.TxBufferNumElements = TX_PARAM_SIZE;
// TX 缓冲区数据有效载荷大小(使用定义)
MRAMConfiguration.TxBufferElementSize = MRAM_64_MRAM Byte_Data;

/*使用上述设置配置 MCAN 内核、该块中的更改是写保护寄存器、
*因此,一次性完成这些任务最有意义,因此我们只需解锁和锁定一次*/
//开始访问受保护的寄存器
TCAN4x5x_MCAN_EnableProtectedRegisters ();
//启用 FD 模式和比特率切换
TCAN4x5x_MCAN_ConfigureCCCRRegister (&cccrConfig);
//配置全局过滤器配置(默认 CAN 消息行为)
TCAN4x5x_MCAN_ConfigureGlobalFilter (&GFC);
//设置标称/仲裁位时序
TCAN4x5x_MCAN_ConfigureNomin52I Timing_Simple (&TCANNomTiming);
//设置 CAN FD 时序
TCAN4x5x_MCAN_ConfigureCLA Timing_Simple (&TCANDataTiming);
//清除全部 MRAM (将0写入全部 MRAM)
TCAN4x5x_MRAM_CLEAR ();
//设置与 MRAM 配置相关的适用寄存器
TCAN4x5x_MRAM_Configure (&MRAMConfiguration);
//禁用受保护的写入并使器件退出 INIT 模式
TCAN4x5x_MCAN_DisableProtectedRegisters ();

/*为 MCAN 设置我们要启用的中断*/
/*记住要初始化为0,否则你会得到随机的垃圾! */
TCAN4x5x_MCAN_TCAN_IE Interrupt_Enable mcan_ie ={0};


/* RX FIFO 0新水印中断启用*/
mcan_ie.RF0WE = 1;

/*启用适当的寄存器*/
TCAN4x5x_MCAN_ConfigureInterruptEnable (&mcan_ie);

//初始化接收和发送缓冲区
TCAN4550_SetRxTxMessageBuffers (CAN_RX_ID_MSG、CAN_RX_ID_MSG_TYPE);

/*配置 TCAN4550非 CAN 相关功能*/
///记住要初始化为0,否则你会得到随机的垃圾!
TCAN4x5x_DEV_CONFIG devConfig ={0};
//保持启用睡眠唤醒错误(它是禁用位、而不是启用位)
devConfig.SWE_DIS = 0;
//不请求软件复位
devConfig.device_reset = 0;
//禁用看门狗
devConfig.WD_EN = 0;
//镜像 INH 功能(默认)
devConfig.nWKRQ_CONFIG = 0;
//已启用 INH (默认)
devConfig.INH_DIS = 0;
// MCAN nINT 1 (默认值)
devConfig.GPIO1_GPO_CONFIG = TCAN4x5x_DEV_CONFIG_GPO1_MCAN_INT1;
//失效防护已禁用(默认)
devConfig.FAIL_SAFE_EN = 0;
// GPIO 设置为 GPO (默认)
devConfig.GPIO1_CONFIG = TCAN4x5x_DEV_CONFIG_GPIO1_CONFIG_GPO;
//看门狗设置中断(默认)
devConfig.WD_ACTION = TCAN4x5x_DEV_CONFIG_WDT_ACTION_nINT;
//不要重置看门狗
devConfig.WD_BIT_RESET = 0;
//将 nWKRQ 设置为内部电压轨(默认值)
devConfig.nWKRQ_voltage = 0;
// GPO2没有行为(默认)
devConfig.GPO2_CONFIG = TCAN4x5x_DEV_CONFIG_GPO2_NO_ACTION;
//输入晶体为40 MHz 晶体(默认)
devConfig.CLK_REF = 0;
// Wake 引脚可由任一边沿触发(默认)
devConfig.WAKE_CONFIG = TCAN4x5x_DEV_CONFIG_WAKE_Both_EDGE;
//使用上述配置配置设备
TCAN4x5x_TCAN1042 Device_Configure (&devConfig);
}

以下是接收中断函数:

void hw_isr_Rx (uint32_t * msg_ID、uint8_t * msg_Payload、uint8_t * msg_dlc)


//设置一个新的 MCAN IR 对象、以便于进行中断检查
TCAN4x5x_MCAN_INTERRUPT mcan_ir ={0};
//读取中断寄存器
TCAN4x5x_MCAN_ReadInterrupts (&M);

//如果 RX FIFO 0中有一条新的消息
// if (mcan_ir.RF0N){//新消息中断
 中频(mcan_ir.RF0W)
 {
  TCAN4x5x_MCAN_ClearInterrupts (&M);

  /*设置接收标志*/

  rxrcvd = true;
 }
}

在下面的函数中、我们检查是否设置了接收标志、如果设置了、则我们将从 FIFO 读取数据。


void execute()

if (rxrcvd == true)

rxrcvd = false;

uint32_t RF1W_reg_1 = AHB_READ_32 (0x10A4);
cntlp = RF1W_reg_1;

for (uint8_t i = 0;i<cntlp;i++)

numBytes = TCAN4x5x_MCAN_ReadNextFIFO (RXFIFO0、&MsgHeader、dataPayload);

tcan_store_data_q[i].canId = MsgHeader.ID;
memcpy (tcan_store_data_q[i].dataBytes、dataPayload、sizeof (tcan_store_data_q[i].dataBytes));
tcan_store_data_q[i].dlc = MsgHeader.dlc;
}

}

在上述配置中、我们观察到接收数据时出现数据包丢失、即接收到的数据包数比发送的数据包少。

您能指导我们解决这个问题吗?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Amit、您好!

    您将丢失 RX 消息、因为水线位设置为 RX FIFO 的最大大小。  当触发水线中断时、MCU 将开始从 FIFO 元素读取 RX 消息、并将其释放以便接收新消息。  但是、由于您在开始读取过程之前正在等待 RX FIFO 完全填满(由于水印和 RX FIFO 的大小都等于60)、因此在 RX 已满时接收到的任何消息都将被拒绝、或者最早的消息将被覆盖(取决于器件的配置)。  

    应将水线位设置为较低的级别、以便 MCU 有足够的时间在 FIFO 中读出已满的 RX 消息并防止数据丢失。  例如、尝试将水线位设置为30、以便器件使用30个 RX 缓冲器元素在 MCU 读取已接收到的消息到 RX FIFO 中时接收和存储消息。  只要 RX FIFO 未满、MCU 就会通过 SPI 读取旧消息、同时 CAN 总线上可以接收到新消息。

    此致、

    Jonathan