Thread 中讨论的其他器件:C2000WARE
工具与软件:
您好!
我目前使用 F28002x 微控制器、并使用 C2000Ware driverlib 中提供的 CAN 驱动程序函数。 我遇到 CAN_readMessage
与和 CAN_clearMessage
功能有关的问题。
该 CAN_readMessage
函数似乎从 IF2寄存器读取数据、而该 CAN_clearMessage
函数 NewDat
使用 IF1寄存器清除该位。 这种差异似乎会导致错误、即 NewDat
该位未被正确清除、从而导致邮箱在第一个消息之后无法接收新消息。
我在曾尝试过的两个版本的 C2000Ware 中找到此实现: C2000Ware_4_03_00_00和 C2000Ware_521_SDK_5_04_00_00 Ware_Digital。
以下是 can.c
该文件中的相关代码片段:
// CAN_readMessage function bool CAN_readMessage(uint32_t base, uint32_t objID, uint16_t *msgData) { bool status; uint16_t msgCtrl = 0U; // Check the arguments. ASSERT(CAN_isBaseValid(base)); ASSERT((objID <= 32U) && (objID != 0U)); // Set the Message Data A, Data B, and control values to be read // on request for data from the message object. HWREG_BP(base + CAN_O_IF2CMD) = ((uint32_t)CAN_IF2CMD_DATA_A | (uint32_t)CAN_IF2CMD_DATA_B | (uint32_t)CAN_IF2CMD_CONTROL | (objID & CAN_IF2CMD_MSG_NUM_M) | (uint32_t)CAN_IF2CMD_ARB); // Wait for busy bit to clear while((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY) { } // Read out the IF control Register. msgCtrl = HWREGH(base + CAN_O_IF2MCTL); // See if there is new data available. if((msgCtrl & CAN_IF2MCTL_NEWDAT) == CAN_IF2MCTL_NEWDAT) { // Read out the data from the CAN registers. CAN_readDataReg(msgData, (base + CAN_O_IF2DATA), ((uint32_t)msgCtrl & CAN_IF2MCTL_DLC_M)); status = true; // Now clear out the new data flag HWREG_BP(base + CAN_O_IF2CMD) = ((uint32_t)CAN_IF2CMD_TXRQST | (objID & CAN_IF2CMD_MSG_NUM_M)); // Wait for busy bit to clear while((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY) { } } else { status = false; } return(status); } // CAN_clearMessage function void CAN_clearMessage(uint32_t base, uint32_t objID) { // Check the arguments. ASSERT(CAN_isBaseValid(base)); ASSERT((objID >= 1U) && (objID <= 32U)); // Wait for busy bit to clear while((HWREGH(base + CAN_O_IF1CMD) & CAN_IF1CMD_BUSY) == CAN_IF1CMD_BUSY) { } // Clear the message valid bit in the arbitration register. This disables // the mailbox. HWREG_BP(base + CAN_O_IF1ARB) = 0U; // Initiate programming the message object HWREG_BP(base + CAN_O_IF1CMD) = (((uint32_t)CAN_IF1CMD_DIR | (uint32_t)CAN_IF1CMD_ARB) | (objID & CAN_IF1CMD_MSG_NUM_M)); }
下面的代码片段显示了 CAN 模块的配置和用于读取接收数据的例程:
// Initialize the CAN-A module CAN_initModule(CANA_BASE); // Set up the CAN bus bit rate CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 500000, 20); // Enable loopback mode CAN_enableTestMode(CANA_BASE, CAN_TEST_EXL); // Enable the CAN module CAN_startModule(CANA_BASE); // Configure the CAN message object for transmission CAN_setupMessageObject(CANA_BASE, SEND_MAILBOX_1 + 1, SEND_MSG_ID_1, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0, CAN_MSG_OBJ_NO_FLAGS, MSG_LEN); // Configure the CAN message object for reception CAN_setupMessageObject(CANA_BASE, RECEIVE_MAILBOX_1 + 1, RECEIVE_MSG_ID_2, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_NO_FLAGS, MSG_LEN); // Configure the CAN message object for receiving PLC requests CAN_setupMessageObject(CANA_BASE, RECEIVE_MAILBOX_2 + 1, RECEIVE_MSG_ID_2, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_NO_FLAGS, MSG_LEN); // Configure the CAN message object for sending diagnostics data CAN_setupMessageObject(CANA_BASE, SEND_MAILBOX_2 + 1, SEND_MSG_ID_2, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_TX, 0, CAN_MSG_OBJ_NO_FLAGS, MSG_LEN); // Configure the Loopback mailboxes // Configure the CAN message object for receiving PVL messages CAN_setupMessageObject(CANA_BASE, RECEIVE_LOOPBACK_MAILBOX_1 + 1, SEND_MSG_ID_1, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_NO_FLAGS, MSG_LEN); // Configure the CAN message object for receiving PLC requests CAN_setupMessageObject(CANA_BASE, RECEIVE_LOOPBACK_MAILBOX_2 + 1, SEND_MSG_ID_2, CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_NO_FLAGS, MSG_LEN); // Enable CAN interrupts CAN_enableInterrupt(CANA_BASE, CAN_INT_IE0 | CAN_INT_ERROR | CAN_INT_STATUS); CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT0); // Register the CAN ISR Interrupt_register(INT_CANA0, &canISR); // Enable the CAN interrupt in the PIE Interrupt_enable(INT_CANA0); // Enable global interrupts EINT; ERTM;
// Read the received message CAN_readMessage(CANA_BASE, RECEIVE_LOOPBACK_MAILBOX_1 + 1, rxData); // Clear the New Data flag CAN_clearMessage(CANA_BASE, RECEIVE_LOOPBACK_MAILBOX_1 + 1); // Clear the interrupt flag CAN_clearInterruptStatus(CANA_BASE, RECEIVE_LOOPBACK_MAILBOX_1 + 1); // Clear CAN global interrupt flag CAN_clearGlobalInterruptStatus(CANA_BASE, CAN_GLOBAL_INT_CANINT0); // Acknowledge the interrupt Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
我面临一个问题、即 CAN_clearMessage
函数不清除该 NewDat
位、所以在接收到第一条消息后、微控制器没有在同一个邮箱接收到任何其他消息。 一旦该邮箱收到第一个消息、它就可以在其他邮箱接收消息、但不能在同一邮箱接收消息。
这是驱动程序中的错误吗?还是错误地使用了这些函数? 我应该如何正确地使用这些函数来确保该 NewDat
位被清除并且邮箱能够接收新消息?
在用以下指令替换 CAN_clearMessage (清除 IF2MCTL 寄存器的 NewDat 位)后、CAN 模块能够接收连续的消息:
void MyCAN_clearMessage(uint32_t base, uint32_t objID) { // Check the arguments. ASSERT(CAN_isBaseValid(base)); ASSERT((objID >= 1U) && (objID <= 32U)); // Wait for busy bit to clear while((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY) { } // Clear the New Data flag HWREG_BP(base + CAN_O_IF2CMD) = ((uint32_t)CAN_IF2CMD_TXRQST | (objID & CAN_IF2CMD_MSG_NUM_M)); // Wait for busy bit to clear while((HWREGH(base + CAN_O_IF2CMD) & CAN_IF2CMD_BUSY) == CAN_IF2CMD_BUSY) { } }
感谢您的帮助。
此致、
Filipe