ZHCUBZ5A September 2021 – April 2024
可以将 CAN 功能添加到实验工程中,为用户提供用于发送启动/停止命令并获取运行状态反馈的通信总线。要利用此功能,请在工程构建属性中启用预定义符号 CMD_CAN_EN,如图 3-19 中所示。详细步骤如下所示。
<install_location>\c2000ware\driverlib\f28002x\driverlib\can.c
typedef struct _HAL_Obj_ { uint32_t adcHandle[2]; //!< the ADC handles ... ... uint32_t canHandle; //!< the CAN handle ... ... } HAL_Obj;
HAL_Handle HAL_init(void *pMemory,const size_t numBytes)
{
... ...
// initialize CAN handle
obj->canHandle = CANA_BASE; //!< the CAN handle
... ...
return(handle);
} // end of HAL_init() function
//! \brief Sets up the CANA
//! \param[in] handle The hardware abstraction layer (HAL) handle
extern void HAL_setupCANA(HAL_Handle handle);
void HAL_setupCANA(HAL_Handle halHandle)
{
HAL_Obj *obj = (HAL_Obj *)halHandle;
// Initialize the CAN controller
CAN_initModule(obj->canHandle);
// Set up the CAN bus bit rate to 200kHz
// Refer to the Driver Library User Guide for information on how to set
// tighter timing control. Additionally, consult the device data sheet
// for more information about the CAN module clocking.
CAN_setBitRate(obj->canHandle, DEVICE_SYSCLK_FREQ, 500000, 16);
// Initialize the transmit message object used for sending CAN messages.
// Message Object Parameters:
// Message Object ID Number: 1
// Message Identifier: 0x1
// Message Frame: Standard
// Message Type: Transmit
// Message ID Mask: 0x0
// Message Object Flags: Transmit Interrupt
// Message Data Length: 8 Bytes
CAN_setupMessageObject(CANA_BASE, TX_MSG_OBJ_ID, 0x1, CAN_MSG_FRAME_STD,
CAN_MSG_OBJ_TYPE_TX, 0, CAN_MSG_OBJ_TX_INT_ENABLE,
MSG_DATA_LENGTH);
// Initialize the receive message object used for receiving CAN messages.
// Message Object Parameters:
// Message Object ID Number: 2
// Message Identifier: 0x1
// Message Frame: Standard
// Message Type: Receive
// Message ID Mask: 0x0
// Message Object Flags: Receive Interrupt
// Message Data Length: 8 Bytes
CAN_setupMessageObject(obj->canHandle, RX_MSG_OBJ_ID, 0x1, CAN_MSG_FRAME_STD,
CAN_MSG_OBJ_TYPE_RX, 0, CAN_MSG_OBJ_RX_INT_ENABLE,
MSG_DATA_LENGTH);
// Start CAN module operations
CAN_startModule(obj->canHandle);
return;
} // end of HAL_setupCANA() function
SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_CANA);
// GPIO33->CAN_TX
GPIO_setPinConfig(GPIO_32_CANA_TX);
GPIO_setDirectionMode(32, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(32, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(32, GPIO_QUAL_ASYNC);
// GPIO33->CAN_RX
GPIO_setPinConfig(GPIO_33_CANA_RX);
GPIO_setDirectionMode(33, GPIO_DIR_MODE_IN);
GPIO_setPadConfig(33, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(33, GPIO_QUAL_ASYNC);
extern void HAL_enableCANInts(HAL_Handle handle);
void HAL_enableCANInts(HAL_Handle handle)
{
HAL_Obj *obj = (HAL_Obj *)handle;
// Enable CAN test mode with external loopback
// CAN_enableTestMode(CANA_BASE, CAN_TEST_EXL); // Only for debug
// Enable interrupts on the CAN peripheral.
CAN_enableInterrupt(obj->canHandle, CAN_INT_IE0 | CAN_INT_ERROR |
CAN_INT_STATUS);
// enable the PIE interrupts associated with the CAN interrupts
Interrupt_enable(INT_CANA0);
CAN_enableGlobalInterrupt(obj->canHandle, CAN_GLOBAL_INT_CANINT0);
// enable the cpu interrupt for CAN interrupts
Interrupt_enableInCPU(INTERRUPT_CPU_INT9);
return;
} // end of HAL_enableCANInts() function
// setup the CAN
HAL_setupCANA(halHandle);
// setup the CAN interrupt
HAL_enableCANInts(halHandle);
extern __interrupt void canaISR(void);
Interrupt_register(INT_CANA0, &canaISR);
#pragma CODE_SECTION(canaISR, ".TI.ramfunc");
__interrupt void canaISR(void) { ... ... // Check if the cause is the transmit message object 1 // Check if the cause is the transmit message object 1 else if(status == TX_MSG_OBJ_ID) { // // Getting to this point means that the TX interrupt occurred on // message object 1, and the message TX is complete. Clear the // message object interrupt. // CAN_clearInterruptStatus(CANA_BASE, TX_MSG_OBJ_ID); // Increment a counter to keep track of how many messages have been // sent. In a real application this could be used to set flags to // indicate when a message is sent. canComVars.txMsgCount++; // Since the message was sent, clear any error flags. canComVars.errorFlag = 0; } // Check if the cause is the receive message object 2 else if(status == RX_MSG_OBJ_ID) { // // Get the received message // CAN_readMessage(halHandle->canHandle, RX_MSG_OBJ_ID, (uint16_t *)(&canComVars.rxMsgData[0])); // Getting to this point means that the RX interrupt occurred on // message object 2, and the message RX is complete. Clear the // message object interrupt. CAN_clearInterruptStatus(halHandle->canHandle, RX_MSG_OBJ_ID); canComVars.rxMsgCount++; canComVars.flagRxDone = true; // Since the message was received, clear any error flags. canComVars. errorFlag = 0; } ... ... // Clear the global interrupt flag for the CAN interrupt line CAN_clearGlobalInterruptStatus(halHandle->canHandle, CAN_GLOBAL_INT_CANINT0); // Acknowledge this interrupt located in group 9 Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9); return; }
void updateCANCmdFreq(MOTOR_Handle handle)
{
...
}
updateCANCmdFreq(motorHandle_M1);
if((motorVars_M1.cmdCAN.flagEnablCmd == true) && (motorVars_M1.faultMtrUse.all == 0))
{
canComVars.flagCmdTxRun = motorVars_M1.cmdCAN.flagCmdRun;
canComVars.speedSet_Hz = motorVars_M1.cmdCAN.speedSet_Hz;
if(motorVars_M1.cmdCAN.flagEnablSyncLead == true)
{
motorVars_M1.flagEnableRunAndIdentify = motorVars_M1.cmdCAN.flagCmdRun;
motorVars_M1.speedRef_Hz = motorVars_M1.cmdCAN.speedSet_Hz;
}
else
{
motorVars_M1.flagEnableRunAndIdentify = canComVars.flagCmdRxRun;
motorVars_M1.speedRef_Hz = canComVars.speedRef_Hz;
}
}