请教一下,我用3块以上的STM32G0B1CC单片机支持的CAN从板,使用电脑发送广播帧给到每一块从板,让每一块从板回复一帧响应帧给电脑端,在这期间就会出现从板接收帧丢失和从板接收后发送帧丢失的情况,相同发送速度单块板的情况就不会丢帧。(附上CAN的配置代码)
/*=============================================================================================
** @Name : void HAL_FDCAN_RxFifo0Callback(void)
** @Input : void
** @Output : void
** @Function : CAN接收中断处理函数
** @The notes : 底层CAN中断调用
**===========================================================================================*/
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
u8 i = 0;
if ((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != 0)//fifo有新数据
{
HAL_FDCAN_GetRxMessage(&hfdcan1, FDCAN_RX_FIFO0, &RxHeader, canRxData);
CANWriteRcvCyBuf(eCAN0, &RxHeader);
for(i = 0; i < 8; i++)
{
canRxData[i] = 0;
}
}
}/*=============================================================================================
** @Name : u8 BSPCANInit(e_CANNUM canNum, u8 osc, u16 rate)
** @Input : canNum:CAN通道号 osc:晶振频率 rate:CAN波特率
** @Output : 初始化结果 TRUE:成功 FALSE:失败
** @Function : CAN驱动模块初始化
** @The notes : BSP调用
**===========================================================================================*/
u8 BSPCANInit(e_CANNUM canNum, u8 osc, u16 rate)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
FDCAN_FilterTypeDef sFilterConfig;
if(canNum >= eCANNUM)
{
return(FALSE);
}
//模块未使能不进行初始化
if(((eCAN0 == canNum) && (1 != gBSPFunCfg.Bits.CAN0En))
|| ((eCAN1 == canNum) && (1 != gBSPFunCfg.Bits.CAN1En)))
{
return(FALSE);
}
switch(canNum)
{
case eCAN0:
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = ENABLE;
hfdcan1.Init.TransmitPause = ENABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.DataPrescaler = 8;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 10;
hfdcan1.Init.DataTimeSeg2 = 5;
hfdcan1.Init.StdFiltersNbr = 28;
hfdcan1.Init.ExtFiltersNbr = 8;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if(rate == 125)
{
hfdcan1.Init.NominalPrescaler = 64; //8:1000k 16:500k 32:250k 64:125k
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 4;
hfdcan1.Init.NominalTimeSeg2 = 3;
}
else if(rate == 250)
{
hfdcan1.Init.NominalPrescaler = 32; //8:1000k 16:500k 32:250k 64:125k
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 4;
hfdcan1.Init.NominalTimeSeg2 = 3;
}
else if(rate == 500)
{
hfdcan1.Init.NominalPrescaler = 16; //8:1000k 16:500k 32:250k 64:125k
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 4;
hfdcan1.Init.NominalTimeSeg2 = 3;
}
else if(rate == 1000)
{
hfdcan1.Init.NominalPrescaler = 8; //8:1000k 16:500k 32:250k 64:125k
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 4;
hfdcan1.Init.NominalTimeSeg2 = 3;
}
else
{
hfdcan1.Init.NominalPrescaler = 16; //8:1000k 16:500k 32:250k 64:125k
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 4;
hfdcan1.Init.NominalTimeSeg2 = 3;
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_FDCAN;
PeriphClkInit.FdcanClockSelection = RCC_FDCANCLKSOURCE_PCLK1;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
/* Peripheral clock enable */
__HAL_RCC_FDCAN_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**FDCAN1 GPIO Configuration
PD0 ------> FDCAN1_RX
PD1 ------> FDCAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF3_FDCAN1;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
HAL_NVIC_SetPriority(TIM16_FDCAN_IT0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM16_FDCAN_IT0_IRQn);
HAL_FDCAN_Init(&hfdcan1);
sFilterConfig.IdType = FDCAN_EXTENDED_ID; // 配置为过滤扩展帧
sFilterConfig.FilterIndex = 0; // 过滤器的索引号
sFilterConfig.FilterType = FDCAN_FILTER_RANGE_NO_EIDM; // 过滤方式为范围,即从FilterID1~FilterID2之间的ID
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x00000000;
sFilterConfig.FilterID2 = 0x1fffffff; // 扩展帧为29位ID,即0x1fffffff,配置为接收所有帧
HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE);
HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
/* Start the FDCAN module */
HAL_FDCAN_Start(&hfdcan1);
break;
case eCAN1:
break;
default:
break;
}
return(TRUE);
}
/*=============================================================================================
** @Name : u8 BSPCANSendMsg(e_CANNUM canNum, t_CANMSG *msg)
** @Input : canNum:通道号 *msg:发送信息结构体
** @Output : 发送结果:TRUE-成功 FALSE-失败
** @Function : CAN发送信息(直接发送)
** @The notes : 用户调用(尽量少用,会丢帧)
**===========================================================================================*/
u8 BSPCANSendMsg(e_CANNUM canNum, t_CANMSG *msg)
{
FDCAN_TxHeaderTypeDef TxHeader;
u8 data[8] = {0};
TxHeader.Identifier = msg->ID;
TxHeader.IdType = FDCAN_EXTENDED_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = msg->Len;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0x00;
data[0] = msg->Data[0];//缓冲区
data[1] = msg->Data[1];
data[2] = msg->Data[2];
data[3] = msg->Data[3];
data[4] = msg->Data[4];
data[5] = msg->Data[5];
data[6] = msg->Data[6];
data[7] = msg->Data[7];
HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, data);
return(TRUE);
}
|
多测试下,看看到底跟板本身有关系,还是说只是跟板回复的先后有关,慢慢找原因。
[md]有点奇怪。
感觉你硬件上好像也没啥问题。
这将从板的发回复间隔拉大点,稍微夸张点无妨,比方20ms,甚至更多,再行验证下。
对于从板,可以让他们在不同时间段回复,避免同时发送导致总线负荷过高。
[color=var(--md-box-samantha-normal-text-color) !important]总之,是否需要 120 欧姆匹配电阻取决于具体的 FDCAN 总线应用环境和要求
总线两端都加了一个120欧姆的电阻,can的波形也打了,差分信号也很标准😕
尝试过了,500k的波特率情况下总线占用率在20%以内,并且还进行过5ms-50ms发送查询帧的测试,从控板同样会出现接收丢帧;还测试过查询帧发出后,从板1会延时1ms回复、从板2会延时2ms回复、从板3会延时3ms回复这样,没有改善效果,该丢还是丢
因为这个现象导致我的boot程序升级多块从板app程序的功能出现数据传输丢帧的故障,我用nxp的k128mcu就不会出现这样的问题
测试了一下,A1~A4四块从板,A1从板延时10ms发送响应帧累加到A4从板40ms发送,错开时间发送,查询帧周期为50ms,实验结果只有A1满帧回复