Part Number: TMS320F280049C
Hi team,
Here's an issue from the customer may need your help:
Function: The main control board issues a query command via CANA to query the current and voltage of the other two boards, which is then sent to the display panel via CANB.
Problem: There is no problem with communication to the main control board, but one of the two subboards (sometimes board1, sometimes board2) suddenly fails to communicate. Using the simulator with breakpoints, the can interrupt is no longer triggered.
Frequency of query: Queries are posted in a 1 kHz interrupt generated by ECAP, and between the two boards are polled to check for interrupts, first board1, and then board2.
The three boards use the same set of codes.
Initializers:
//初始化函数
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,位时序20Tq
CAN_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 replenish
Interrupt_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 program:
// 中断处理函数
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]);
// 队列计数+1
CAN_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]);
// 队列计数+1
CANA_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);
}
Could you help check this case? Thanks.
Best Regards,
Cherry