Part Number:TMS320F28377S
问题描述:。
主从机均为TMS320F28377S,通过CAN通信交互数据,波特率500kHz。
主机每1ms发送一帧数据给从机,长度5个字节。
从机采用中断方式接收主机数据,开始一段时间接收正常,过一段时间后,从机接收不到主机的数据,间隔时间不固定,有时很长时间也没有接收不到的现象。
另:从机接收不到主机数据现象发生后,通过Can工具给从机DSP发送其他帧ID数据,从机还能成功接收。
请问:
该现象是怎么产生的?应该如何解决呢?
Yale Li:
有单步调过吗?主从机的程序分别停在哪里?
,
Yanyi Xing:
没有,逆变器跑的大功率。主机的数据还在发送,通过CANTest工具可以看到,从机接收不到了。
,
Yanyi Xing:
从机接收不到主机的数据时,从机程序也没进入上面CAN通信错误中断中。会是因为我程序还有个1ms中断,把CAN接收中断影响了吗?
,
Yale Li:
总结一下就是,异常发生时,主机还可以发送该帧ID的数据,从机还可以接收其它帧ID的数据。
Yanyi Xing said:另:从机接收不到主机数据现象发生后,通过Can工具给从机DSP发送其他帧ID数据,从机还能成功接收。
如果用Can工具给从机发送该帧ID的数据,从机能接收到吗?
Yanyi Xing said:会是因为我程序还有个1ms中断,把CAN接收中断影响了吗?
这个是什么中断?
,
Yanyi Xing:
(1)如果用Can工具给从机发送该帧ID的数据,从机能接收到吗?
==== 从机也接收不到。
(2)这个是什么中断?
==== 这个是定时器中断,用来处理其他任务的,1ms中断中程序的执行时间测试最长有70us。
,
Yale Li:
有检查过中间的连接正常吗?
可以分享下can的配置吗?
,
Yanyi Xing:
(1)有检查过中间的连接正常吗?
==== 中间连接是正常的。
(2)can的相关配置如下:
// ==================================================================== // === 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 AutoBusOnCAN_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" priorityPieCtrlRegs.PIEIER9.all &= MG9_5;// Set "group"priorityPieCtrlRegs.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
,
Yale Li:
我已经咨询了相关工程师:
https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1288845/tms320f28377s-can-slave-cannot-receive-the-specified-id-data
,
Yanyi Xing:
What could be happening is that the interrupts are not being serviced promptly leading to the impression that messages are being lost.
===== 什么会导致中断程序没有被及时服务呢?
If masking is not used and the message object is retaining the correct MSGID (ARBID), it will receive a transmitted message. It cannot suddenly stop receiving messages.
===== 程序中掩码没有用,MSGID (ARBID)也没有更改。
怎么去进一步定位到问题呢?
,
Yale Li:
好的,我跟进过去了
,
Yanyi Xing:
麻烦再帮忙问一下:
If a message was indeed over-written (because it was not read in time by the software), this bit would be set.
===== 消息被重写丢失后,出错的消息对象会一直收不到数据吗?
The application could either configure more message objects for receive or otherwise ensure that CAN interrupts are serviced on time.
===== 我可以使用两个不同的消息对象接收同一个ID的数据吗?
谢谢!
,
Yale Li:
好的