我的功能是主控板通过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,位时序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 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);
}
我在TI的例程中没有看到具体的CAN错误处理,我有看到他有查询错误,但是最多就是记录出错次数,想问一下如果遇到这种出错的正常你们是怎么做的?