主题中讨论的其他器件:C2000WARE
我目前正在查看 driverlib 示例代码 can_ex3_external_transmit (\C2000Ware_4_01_00_00\driverlib\f2837xd\examples\cpu1\can)
其中 CAN-A 用于传输数据、CAN-B 用于接收数据
这就是 ISR 函数
//
// CAN B ISR - The interrupt service routine is called when an interrupt is
// triggered on CAN module B. It will be executed twice for every
// frame received.
// First time for status-change; second time for Mailbox receive.
//
__interrupt void
canbISR(void)
{
uint32_t status;
//
// Read the CAN-B interrupt status (in the CAN_INT register) to find the
// cause of the interrupt
//
status = CAN_getInterruptCause(CANB_BASE);
//
// If the cause is a controller status interrupt, then get the status.
// During first iteration of every ISR execution, status = 0x8000,
// which simply means CAN_ES != 0x07.
//
if(status == CAN_INT_INT0ID_STATUS)
{
//
// Read the controller status. This will return a field of status
// error bits that can indicate various errors. Error processing
// is not done in this example for simplicity. Refer to the
// API documentation for details about the error status bits.
// The act of reading this status will clear the interrupt.
//
status = CAN_getStatus(CANB_BASE); // Return CAN_ES value.
//
// Now status = 0x00000010, indicating RxOK.
//
//
// Check to see if an error occurred.
//
if(((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
{
//
// Set a flag to indicate some errors may have occurred.
//
errorFlag = 1;
}
}
//
// Check if the cause is the CAN-B receive message object 1. Will be skipped
// in the first iteration of every ISR execution
//
else if(status == RX_MSG_OBJ_ID)
{
//
// Get the received message
//
CAN_readMessage(CANB_BASE, RX_MSG_OBJ_ID, rxMsgData);
//
// Getting to this point means that the RX interrupt occurred on
// message object 1, and the message RX is complete. Clear the
// message object interrupt.
//
CAN_clearInterruptStatus(CANB_BASE, RX_MSG_OBJ_ID);
//
// Increment a counter to keep track of how many messages have been
// received. In a real application this could be used to set flags to
// indicate when a message is received.
//
rxMsgCount++;
//
// Since the message was received, clear any error flags.
//
errorFlag = 0;
}
//
// If something unexpected caused the interrupt, this would handle it.
//
else
{
//
// Spurious interrupt handling can go here.
//
}
//
// Clear the global interrupt flag for the CAN interrupt line
//
CAN_clearGlobalInterruptStatus(CANB_BASE, CAN_GLOBAL_INT_CANINT0);
//
// Acknowledge this interrupt located in group 9
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
基于上述,我 为我的应用程序创建了这个 ISR 框架,我们在其中检查是否接收到任何帧,传输或是否有任何错误。
#define CTRL_BRD_CAN CANA_BASE
#define CTRL_BRD_CAN_INT INT_CANA0
#define CTRL_BRD_CAN_TX_MSG_OBJ_ID_1 1
#define CTRL_BRD_CAN_TX_MSG_OBJ_ID_1_LEN 1
#define CTRL_BRD_CAN_RX_MSG_OBJ_ID_1 1
#define CTRL_BRD_CAN_RX_MSG_OBJ_ID_1_LEN 2
#define CTRL_BRD_CAN_MSG_ID 0x01
__interrupt void INT_CAN_CTRL_ISR(void)
{
uint32_t status;
//
// Read the interrupt cause
//
status = CAN_getInterruptCause(CTRL_BRD_CAN);
if (status == CAN_INT_INT0ID_STATUS)
{
status = CAN_getStatus(CTRL_BRD_CAN); // Return CAN_ES value.
//
// Check to see if an error occurred.
//
if (((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK)
&& ((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
{
//
// Set a flag to indicate some errors may have occurred.
//
//errorFlag = 1;
//
// TODO: Do error handling in here
;
}
}
//
// Check if the cause is the CAN receive message object 1. Will be skipped
// in the first iteration of every ISR execution
//
else if(status == CTRL_BRD_CAN_RX_MSG_OBJ_ID_1)
{
//TODO: Do something
//
//Clear the RX message object interrupt.
//
CAN_clearInterruptStatus(CTRL_BRD_CAN, CTRL_BRD_CAN_RX_MSG_OBJ_ID_1);
}
//
// Check if the cause is the transmit message object 1
//
else if (status == CTRL_BRD_CAN_TX_MSG_OBJ_ID_1)
{
//TODO: Do something
//
//Clear the TX message object interrupt.
//
CAN_clearInterruptStatus(CTRL_BRD_CAN, CTRL_BRD_CAN_TX_MSG_OBJ_ID_1);
}
//
// Clear the global interrupt flag for the CAN interrupt line
//
CAN_clearGlobalInterruptStatus(CTRL_BRD_CAN, CAN_GLOBAL_INT_CANINT0);
//
// Acknowledge this interrupt located in group 9
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
我的问题是,如果发生错误(从 CAN_ES 读取),
- CAN 总线是自动再次重新传输数据、还是我们必须手动重新传输数据? 这与 CAN_enableRetry ()函数有什么关系吗?
- 如果发生错误、您能建议我们采取任何纠正措施、以便将总线恢复到无错误状态吗?