主题中讨论的其他器件: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 ()函数有什么关系吗?
- 如果发生错误、您能建议我们采取任何纠正措施、以便将总线恢复到无错误状态吗?