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
