TI中文支持网
TI专业的中文技术问题搜集分享网站

TMS320F280049C: 三板间的CAN通信

Part Number:TMS320F280049C

我的功能是主控板通过CANA下发查询命令查询另外两块板的电流和电压,然后通过CANB发送到显示面板上,我遇到的问题是:我的主控板的通信没有出过问题,但是我两个副板总会有一个(比较随机有时是1号有时是2号)突然无法通信,我用仿真器加断点发现它已经无法触发CAN的中断了。

查询的频率是在一个由ECAP产生的1Khz的中断中发布查询,而且两块板之间是轮询查的中断第一次查1号板,第二次查2号板这样循环

三个板子我用的是同一套代码

初始化程序:

//初始化函数
void HAL_setupCAN()
{//配置IO 30、31引脚GPIO_setPinConfig(CANRXA_GPIO_CFG);GPIO_setPinConfig(CANTXA_GPIO_CFG);GPIO_setPinConfig(CANRXB_GPIO_CFG);GPIO_setPinConfig(CANTXB_GPIO_CFG);// 初始化CAN控制器CAN_initModule(CANA_BASE);CAN_initModule(CANB_BASE);// 设置CAN,使用CANA,系统时钟,波特率500KHz,位时序20TqCAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 1000000, 20);CAN_setBitRate(CANB_BASE, DEVICE_SYSCLK_FREQ, 500000, 20);// 使能CAN中断CAN_enableInterrupt(CANA_BASE, CAN_INT_ERROR|CAN_INT_STATUS|CAN_INT_IE0);CAN_enableInterrupt(CANB_BASE, CAN_INT_ERROR|CAN_INT_STATUS|CAN_INT_IE0);
//CAN_enableInterrupt(CANA_BASE, CAN_INT_STATUS|CAN_INT_IE0);
//CAN_enableInterrupt(CANB_BASE, CAN_INT_STATUS|CAN_INT_IE0);CAN_enableRetry(CANA_BASE);CAN_enableRetry(CANB_BASE);// 配置CANA0中断Interrupt_register(INT_CANA0, &canAISR);//wait replenishInterrupt_register(INT_CANB0, &canISR);// 使能CANA0中断Interrupt_enable(INT_CANA0);Interrupt_enable(INT_CANB0);CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT0);CAN_enableGlobalInterrupt(CANB_BASE, CAN_GLOBAL_INT_CANINT0);//// Initialize the transmit message object used for sending CAN messages.// Message Object Parameters://Message Object ID Number: 邮箱ID//Message Identifier: CAN_ID//Message Frame: 数标准格式//Message Type: 非远程发送//Message ID Mask: 无消息拓展//Message Object Flags: 发送中断标志位使能//Message Data Length: 数据长度8字节//CAN_setupMessageObject(CANA_BASE, TX_MSG_OBJ_ID, CAN_ID, CAN_MSG_FRAME_STD,CAN_MSG_OBJ_TYPE_TX, 0, CAN_MSG_OBJ_TX_INT_ENABLE,Can_DATA_LENGTH);CAN_setupMessageObject(CANB_BASE, TX_MSG_OBJ_ID, CAN_ID, CAN_MSG_FRAME_STD,CAN_MSG_OBJ_TYPE_TX, 0, CAN_MSG_OBJ_TX_INT_ENABLE,Can_DATA_LENGTH);//// Initialize the receive message object used for receiving CAN messages.// Message Object Parameters://Message Object ID Number: 邮箱ID//Message Identifier: CAN_ID//Message Frame: 数据标准格式//Message Type: 非远程接收//Message ID Mask: 无消息拓展//Message Object Flags: 接收中断使能//Message Data Length: 8 Bytes//CAN_setupMessageObject(CANA_BASE, RX_MSG_OBJ_ID, CAN_ID, CAN_MSG_FRAME_STD,CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_RX_INT_ENABLE,Can_DATA_LENGTH);CAN_setupMessageObject(CANB_BASE, RX_MSG_OBJ_ID, CAN_ID, CAN_MSG_FRAME_STD,CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_RX_INT_ENABLE,Can_DATA_LENGTH);// 启动CAN模块CAN_startModule(CANA_BASE);CAN_startModule(CANB_BASE);
}

中断程序:

// 中断处理函数
interrupt void canISR(void)
{uint32_t status;// 读取CAN中断状态,获得中断标志位status = CAN_getInterruptCause(CANB_BASE);if(status == CAN_INT_INT0ID_STATUS){// 读取控制器状态。这将返回一个状态错误位字段,该字段可以指示各种错误。// 为了简单起见,本例中没有进行错误处理。// 有关错误状态位的详细信息,请参考API文档。// 读取此状态的行为将清除中断。status = CAN_getStatus(CANB_BASE);// 检查是否发生错误。if (((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 7)&& ((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 0)){// Set a flag to indicate some errors may have occurred.CAN_clearInterruptStatus(CANB_BASE,CAN_INT_INT0ID_STATUS);CAN_clearInterruptStatus(CANB_BASE, TX_MSG_OBJ_ID);CAN_clearInterruptStatus(CANB_BASE, RX_MSG_OBJ_ID);}}else if (status == TX_MSG_OBJ_ID) // 为发送中断{// 到达这一点意味着TX中断发生// 并且消息TX已经完成// 清除中断标志CAN_clearInterruptStatus(CANB_BASE, TX_MSG_OBJ_ID);}else if (status == RX_MSG_OBJ_ID) // 为接收中断{CAN_List_FLAG[CAN_List_Num] = 1;//改变队列标志位// 获取接收到的信息CAN_readMessage(CANB_BASE, RX_MSG_OBJ_ID, CanMsgData[CAN_List_Num]);// 队列计数+1CAN_List_Num++;if(CAN_List_Num >= CAN_DATA_LIST)CAN_List_Num = 0;// 到达这一点意味着RX中断发生在消息对象2上,消息RX完成了。// 清除消息对象中断。CAN_clearInterruptStatus(CANB_BASE, RX_MSG_OBJ_ID);}else  { // 如果意外的事情导致中断,这将处理它。CAN_clearInterruptStatus(CANB_BASE, RX_MSG_OBJ_ID);CAN_clearInterruptStatus(CANB_BASE, TX_MSG_OBJ_ID);}// 清除CAN中断线路的全局中断标志CAN_clearGlobalInterruptStatus(CANB_BASE, CAN_GLOBAL_INT_CANINT0);// 这个位于第9组的中断Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
interrupt void canAISR(void)
{uint32_t status;// 读取CAN中断状态,获得中断标志位status = CAN_getInterruptCause(CANA_BASE);if(status == CAN_INT_INT0ID_STATUS){// 读取控制器状态。这将返回一个状态错误位字段,该字段可以指示各种错误。// 为了简单起见,本例中没有进行错误处理。// 有关错误状态位的详细信息,请参考API文档。// 读取此状态的行为将清除中断。status = CAN_getStatus(CANA_BASE);// 检查是否发生错误。if (((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 7)&& ((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 0)){// Set a flag to indicate some errors may have occurred.CAN_clearInterruptStatus(CANA_BASE,CAN_INT_INT0ID_STATUS);}}else if (status == TX_MSG_OBJ_ID) // 为发送中断{// 到达这一点意味着TX中断发生// 并且消息TX已经完成// 清除中断标志CAN_clearInterruptStatus(CANA_BASE, TX_MSG_OBJ_ID);}else if (status == RX_MSG_OBJ_ID) // 为接收中断{CANA_List_FLAG[CANA_List_Num] = 1;//改变队列标志位// 获取接收到的信息CAN_readMessage(CANA_BASE, RX_MSG_OBJ_ID, CanAMsgData[CANA_List_Num]);// 队列计数+1CANA_List_Num++;if(CANA_List_Num >= CAN_DATA_LIST)CANA_List_Num = 0;// 到达这一点意味着RX中断发生在消息对象2上,消息RX完成了。// 清除消息对象中断。CAN_clearInterruptStatus(CANA_BASE, RX_MSG_OBJ_ID);}else  { // 如果意外的事情导致中断,这将处理它。CAN_clearInterruptStatus(CANA_BASE, RX_MSG_OBJ_ID);CAN_clearInterruptStatus(CANA_BASE, TX_MSG_OBJ_ID);}// 清除CAN中断线路的全局中断标志CAN_clearGlobalInterruptStatus(CANA_BASE, CAN_GLOBAL_INT_CANINT0);// 这个位于第9组的中断Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}

我在TI的例程中没有看到具体的CAN错误处理,我有看到他有查询错误,但是最多就是记录出错次数,想问一下如果遇到这种出错的正常你们是怎么做的?

Cherry Zhou:

您好,我们已收到您的问题并升级到英文论坛寻求帮助,由于明天假期,我们可能无法及时将回复转达给您,您可以自行查看以下链接来获取最新进展:

e2e.ti.com/…/tms320f280049c-can-communication-between-3-boards

,

Cherry Zhou:

您好,

很明显由于3个节点之间的通信没问题,那么硬件是没有问题的。应该是您代码间歇性的问题。 很抱歉我们无法帮忙debug此类问题。 唯一可以给出的建议是去除代码中的所有其他内容,仅保留 CAN 部分并测试通信。 然后您可以逐步将模块添加到您的代码中,来识别问题在哪里。

,

YingJed Ying:

虽然不确定是不是这个问题造成的,但我在初始化添加了

CAN_enableAutoBusOn(CANA_BASE);//当出现总线关闭的情况时,能够自动重启 CAN_enableAutoBusOn(CANB_BASE);//当出现总线关闭的情况时,能够自动重启 CAN_setAutoBusOnTime(CANA_BASE,100);//1MS CAN_setAutoBusOnTime(CANB_BASE,100);//1MS

这段话后好像就没有再出现这种情况了

,

Aiden zhang:

应该还是有问题存在,只是你让CAN总线自动重启了。

1、不需要定时发送查询帧,只需要另外两块板定时将你需要的信息发到CAN总线上就可以,主控板按照协议进行解析

2、你的目前主控板板发送CAN报文的频率太快了(1ms一帧),你放到10ms或者20模式试试,把上面添加的代码屏蔽掉应该也可以

赞(0)
未经允许不得转载:TI中文支持网 » TMS320F280049C: 三板间的CAN通信
分享到: 更多 (0)