Other Parts Discussed in Thread: C2000WARE
Master&Slave devices: F28377S
baudrate: 500kHz
The master sends a frame of data to the slave every 1ms, with a length of 5 bytes.
The slave uses interrupt method to receive data from the master. At the beginning, the slave received normally. After a period of time, the slave cannot receive data(only specified ID) from the master. The interval is not fixed, and the slave sometimes works normally for a long time.
The connection between master and slave is normal.
After the error occurs, use the CAN tool to send data of other frame IDs to the slave, and the slave can receive it normally.
It can also be detected that the data sent by the master with this specified frame ID comes out.
Use the CAN tool to send data with this specified ID, and the slave cannot receive it.
// ==================================================================== // === 1. 主函数初始化部分 ============================================ // ==================================================================== void main(void) { // // Initialize the CAN controllers // CANInit(CANA_BASE); // // Setup CAN to be clocked off the PLL output clock // CANClkSourceSelect(CANA_BASE, 0); // // Set up the CAN bus bit rate to 500kHz for each module // This function sets up the CAN bus timing for a nominal configuration. // You can achieve more control over the CAN bus timing by using the // function CANBitTimingSet() instead of this one, if needed. // Additionally, consult the device data sheet for more information about // the CAN module clocking. // CANBitRateSet(CANA_BASE, 200000000, 500000); // CANBitRateSet(CANA_BASE, 200000000, 1000000); // // Enable interrupts on the CAN A peripheral. // // CANIntEnable(CANA_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); CANIntEnable(CANA_BASE, CAN_INT_MASTER | CAN_INT_ERROR); // Enable AutoBusOn CAN_enableAutoBusOn(CANA_BASE); CAN_setAutoBusOnTime(CANA_BASE, 100000); CAN_disableRetry(CANA_BASE); // // Enable the CAN-A interrupt signal // CANGlobalIntEnable(CANA_BASE, CAN_GLB_INT_CANINT0); CanObjInit(); // // Start CAN module A operations // CANEnable(CANA_BASE); } // ==================================================================== // === 2. 主机DSP CanObjInit()初始化配置邮箱,及发送程序 ============= // ==================================================================== void CanObjInit() { // 两DSP CAN通信,发送 sTXCANMsgDspComm01.ui32MsgID = 0x0C100201; sTXCANMsgDspComm01.ui32MsgIDMask = 0; sTXCANMsgDspComm01.ui32Flags = 0; sTXCANMsgDspComm01.ui32MsgLen = 5; sTXCANMsgDspComm01.pucMsgData = TxMsgDspCommData01; } // ====== 发送部分程序,1ms发送1次 ===================================== // 发送给从机电流设定值 TxMsgDspCommData01[0] = ((int)(onGridCloseLoopIdref * 100) & 0x00FF); TxMsgDspCommData01[1] = ((int)(onGridCloseLoopIdref * 100) & 0xFF00) >> 8; TxMsgDspCommData01[2] = ((int)(onGridCloseLoopIqref * 100) & 0x00FF); TxMsgDspCommData01[3] = ((int)(onGridCloseLoopIqref * 100) & 0xFF00) >> 8; TxMsgDspCommData01[4] = 0; CANMessageSet(CANA_BASE, 4, &sTXCANMsgDspComm01, MSG_OBJ_TYPE_TX); // ==================================================================== // === 3. 从机DSP CanObjInit()初始化配置邮箱,及接收程序 ============= // ==================================================================== void CanObjInit() { // 两DSP CAN通信,接收 sRXCANMsgDspComm01.ui32MsgID = 0x0C100201; sRXCANMsgDspComm01.ui32MsgIDMask = 0; sRXCANMsgDspComm01.ui32Flags = MSG_OBJ_RX_INT_ENABLE; sRXCANMsgDspComm01.ui32MsgLen = 5; sRXCANMsgDspComm01.pucMsgData = RxMsgDspCommData01; CANMessageSet(CANA_BASE, 15, &sRXCANMsgDspComm01, MSG_OBJ_TYPE_RX); } // ======== 在中断中接收主机发送过来的数据(status = 15时接收该帧 ) ============================ #if (G9_5PL != 0) __interrupt void CANA0_ISR(void) // CAN-A { // Set interrupt priority: volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER9.all; IER |= M_INT9; IER &= MINT9; // Set "global" priority PieCtrlRegs.PIEIER9.all &= MG9_5; // Set "group" priority PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts __asm(" NOP"); EINT; uint32_t status; // // Read the CAN-A interrupt status to find the cause of the interrupt // status = CANIntStatus(CANA_BASE, CAN_INT_STS_CAUSE); // // If the cause is a controller status interrupt, then get the status // if(status == CAN_INT_INT0ID_STATUS) { // DSP_OUT1_TOGGLE; // // 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 = CANStatusGet(CANA_BASE, CAN_STS_CONTROL); // // Check to see if an error occurred. // // if(((status & ~(CAN_ES_RXOK)) != 7) && // ((status & ~(CAN_ES_RXOK)) != 0)) // if(((status & ~(CAN_ES_RXOK | CAN_ES_TXOK | CAN_ES_BOFF)) != 7) && // ((status & ~(CAN_ES_RXOK | CAN_ES_TXOK | CAN_ES_BOFF)) != 0)) if(((status & ~(CAN_ES_RXOK | CAN_ES_TXOK)) != 7) && ((status & ~(CAN_ES_RXOK | CAN_ES_TXOK)) != 0)) { // // Set a flag to indicate some errors may have occurred. // errorFlag = 1; // 调试 CanConfigInit(); // DSP_OUT1_TOGGLE; // 调试 } } else if(status == 15) { DSP_OUT1_TOGGLE; errorFlag = 0; CanReceiveDsp01(); CANIntClear(CANA_BASE, 15); } else if(status == 16) { CanReceiveDsp02(); CANIntClear(CANA_BASE, 16); } else if(status == 17) { // DSP_OUT1_TOGGLE; // 调试 CanReceiveDsp03(); CANIntClear(CANA_BASE, 17); } // // Check if the cause is the CAN-A receive message object 1 // else if(status == 25) { // // Get the received message // // CANMessageGet(CANA_BASE, 2, &sRXCANMsgChkInfo, true); CanReceiveSrhInfo(); // // 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. // CANIntClear(CANA_BASE, 25); // // 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; } else if(status == 26) { CanReceiveRdSet(); CANIntClear(CANA_BASE, 26); } else if(status == 27) { CanReceiveCtlSet(); CANIntClear(CANA_BASE, 27); } else if(status == 28) { CanReceiveParaSet(); CANIntClear(CANA_BASE, 28); } // // If something unexpected caused the interrupt, this would handle it. // else { // // Spurious interrupt handling can go here. // // errorFlag = 2; // 调试 } // // Clear the global interrupt flag for the CAN interrupt line // CANGlobalIntClear(CANA_BASE, CAN_GLB_INT_CANINT0); // // Restore registers saved: // DINT; PieCtrlRegs.PIEIER9.all = TempPIEIER; } #endif
--
Thanks & Regards