问题描述:CAN总线离线后无法再次上线
CAN配置代码如下:
void CAN_Config_Init(void)
{
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_CAN);
CAN_Config_T canConfig;
CAN_FilterConfig_T FilterStruct;
CAN_Reset();//复位
CAN_ConfigStructInit(&canConfig);
/* CAN init */
canConfig.autoBusOffManage = DISABLE;
canConfig.autoWakeUpMode = DISABLE;
canConfig.nonAutoRetran = DISABLE;
canConfig.rxFIFOLockMode = DISABLE;
canConfig.txFIFOPriority = ENABLE;
canConfig.mode = CAN_MODE_NORMAL;
canConfig.syncJumpWidth = CAN_SJW_1;
//配置波特率 125kbps
canConfig.timeSegment1 = CAN_TIME_SEGMENT1_4;
canConfig.timeSegment2 = CAN_TIME_SEGMENT2_3;
canConfig.prescaler = 48;
CAN_Config(&canConfig);
FilterStruct.filterNumber = CAN_FILTER_NUMBER_1;
FilterStruct.filterMode = CAN_FILTER_MODE_IDMASK;
FilterStruct.filterScale = CAN_FILTER_SCALE_32BIT;
FilterStruct.filterIdHigh = (uint16_t)((u32RevCan_Id0>>13)&0xffff);
FilterStruct.filterIdLow = ((uint16_t)u32RevCan_Id0<<3&0xffff)|CAN_TYPEID_EXT;
FilterStruct.filterMaskIdHigh = 0xffff;
FilterStruct.filterMaskIdLow = 0x0000;
FilterStruct.filterFIFO = CAN_FIFO_0;
FilterStruct.filterActivation = ENABLE;
CAN_ConfigFilter(&FilterStruct);
FilterStruct.filterNumber = CAN_FILTER_NUMBER_0;
FilterStruct.filterMode = CAN_FILTER_MODE_IDMASK;
FilterStruct.filterScale = CAN_FILTER_SCALE_32BIT;
FilterStruct.filterIdHigh = (uint16_t)((u32RevCan_Id1>>13)&0xffff);
FilterStruct.filterIdLow = ((uint16_t)u32RevCan_Id1<<3&0xffff)|CAN_TYPEID_EXT;
FilterStruct.filterMaskIdHigh = 0xffff;
FilterStruct.filterMaskIdLow = 0x0000;
FilterStruct.filterFIFO = CAN_FIFO_0;
FilterStruct.filterActivation = ENABLE;
CAN_ConfigFilter(&FilterStruct);
CAN_EnableInterrupt(CAN_INT_F0MP);//使能中断 FIFO 0 message pending Interrupt
}
查看代码无果,跑个调试,发现掉线后发送程序总会进入到发送邮箱满的标志中,这就导致无法发送数据。
这个时候就往CAN模块出错这个方向上查找问题。查询手册中的出错管理:
从手册中的描述中我们可以发现,发送出错会导致CAN总线控制器离线,离线之后不能接收和发送报文。
调试模式下,查看相应的标志位,此时发现发送错误计数就会一直增加,最后导致离线。
此时就可以得出结论:设备离线的原因就是发送错误计数超过了255,导致了CAN总线控制器离线,无法再次发送CAN报文。
手册中也提到了离线恢复的机制:
查询离线标志位BOFLG,当检测到离线后,重新初始化CAN即可重新上线。
if(BOFLG==1)//如果检测到CAN控制器离线
{
CAN_init();//执行一遍初始化代码
}