SPRUJ26A September 2021 – April 2024
CAN functionality can be added into the lab project to provide the user a communication bus for sending the start/stop command and getting the feedback running states. To utilize this, enable the pre-define symbol CMD_CAN_EN in project build properties as shown in Figure 3-19. The detailed steps are as the followings.
<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;
}
}