//***************************************************************************** // // Configure the CAN and enter a loop to receive CAN messages. // //***************************************************************************** int main(void) { tCANMsgObject sCANMessage; uint8_t pui8MsgData[8]; // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal used on your board. // SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for CAN operation. // InitConsole(); // // For this example CAN0 is used with RX and TX pins on port B4 and B5. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the GPIO pin muxing to select CAN0 functions for these pins. // This step selects which alternate function is available for these pins. // This is necessary if your part supports GPIO pin function muxing. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using // GPIOPinConfigure(GPIO_PB4_CAN0RX); GPIOPinConfigure(GPIO_PB5_CAN0TX); // // Enable the alternate function on the GPIO pins. The above step selects // which alternate function is available. This step actually enables the // alternate function instead of GPIO for these pins. // TODO: change this to match the port/pin you are using // GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5); // // The GPIO port and pins have been set up for CAN. The CAN peripheral // must be enabled. // SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Initialize the CAN controller // CANInit(CAN0_BASE); // // Set up the bit rate for the CAN bus. 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. // In this example, the CAN bus is set to 500 kHz. In the function below, // the call to SysCtlClockGet() is used to determine the clock rate that // is used for clocking the CAN peripheral. This can be replaced with a // fixed value if you know the value of the system clock, saving the extra // function call. For some parts, the CAN peripheral is clocked by a fixed // 8 MHz regardless of the system clock in which case the call to // SysCtlClockGet() should be replaced with 8000000. Consult the data // sheet for more information about CAN peripheral clocking. // CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); // // Enable interrupts on the CAN peripheral. This example uses static // allocation of interrupt handlers which means the name of the handler // is in the vector table of startup code. If you want to use dynamic // allocation of the vector table, then you must also call CANIntRegister() // here. // // CANIntRegister(CAN0_BASE, CAN0_IRQHandler); // if using dynamic vectors // CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // // Enable the CAN interrupt on the processor (NVIC). // IntEnable(INT_CAN0); // // Enable the CAN for operation. // CANEnable(CAN0_BASE); // // Initialize a message object to receive CAN messages with ID 0x1001. // The expected ID must be set along with the mask to indicate that all // bits in the ID must match. // sCANMessage.ui32MsgID = 0x1001; sCANMessage.ui32MsgIDMask = 0xfffff; sCANMessage.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER | MSG_OBJ_EXTENDED_ID); sCANMessage.ui32MsgLen = 8; // // Now load the message object into the CAN peripheral message object 1. // Once loaded the CAN will receive any messages with this CAN ID into // this message object, and an interrupt will occur. // CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); // // Change the ID to 0x2001, and load into message object 2 which will be // used for receiving any CAN messages with this ID. Since only the CAN // ID field changes, we don't need to reload all the other fields. // sCANMessage.ui32MsgID = 0x2001; CANMessageSet(CAN0_BASE, 2, &sCANMessage, MSG_OBJ_TYPE_RX); // // Change the ID to 0x3001, and load into message object 3 which will be // used for receiving any CAN messages with this ID. Since only the CAN // ID field changes, we don't need to reload all the other fields. // sCANMessage.ui32MsgID = 0x3001; CANMessageSet(CAN0_BASE, 3, &sCANMessage, MSG_OBJ_TYPE_RX); // // Enter loop to process received messages. This loop just checks flags // for each of the 3 expected messages. The flags are set by the interrupt // handler, and if set this loop reads out the message and displays the // contents to the console. This is not a robust method for processing // incoming CAN data and can only handle one messages at a time per message // object. If many messages are being received close together using the // same message object, then some messages may be dropped. In a real // application, some other method should be used for queuing received // messages in a way to ensure they are not lost. You can also make use // of CAN FIFO mode which will allow messages to be buffered before they // are processed. // for(;;) { // // If the flag for message object 1 is set, that means that the RX // interrupt occurred and there is a message ready to be read from // this CAN message object. // if(g_bRXFlag1) { // // Reuse the same message object that was used earlier to configure // the CAN for receiving messages. A buffer for storing the // received data must also be provided, so set the buffer pointer // within the message object. This same buffer is used for all // messages in this example, but your application could set a // different buffer each time a message is read in order to store // different messages in different buffers. // sCANMessage.pui8MsgData = pui8MsgData; // // Read the message from the CAN. Message object number 1 is used // (which is not the same thing as CAN ID). The interrupt clearing // flag is not set because this interrupt was already cleared in // the interrupt handler. // CANMessageGet(CAN0_BASE, 1, &sCANMessage, 0); // // Clear the pending message flag so that the interrupt handler can // set it again when the next message arrives. // g_bRXFlag1 = 0; // // Print information about the message just received. // PrintCANMessageInfo(&sCANMessage, 1); } // // Check for message received on message object 2. If so then // read message and print information. // if(g_bRXFlag2) { sCANMessage.pui8MsgData = pui8MsgData; CANMessageGet(CAN0_BASE, 2, &sCANMessage, 0); g_bRXFlag2 = 0; PrintCANMessageInfo(&sCANMessage, 2); } // // Check for message received on message object 3. If so then // read message and print information. // if(g_bRXFlag3) { sCANMessage.pui8MsgData = pui8MsgData; CANMessageGet(CAN0_BASE, 3, &sCANMessage, 0); g_bRXFlag3 = 0; PrintCANMessageInfo(&sCANMessage, 3); } } // // Return no errors // return(0); }
//***************************************************************************** // // Configure the CAN and enter a loop to transmit periodic CAN messages. // //***************************************************************************** int main(void) { // // Set the clocking to run directly from the external crystal/oscillator. // TODO: The SYSCTL_XTAL_ value must be changed to match the value of the // crystal on your board. // SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Set up the serial console to use for displaying messages. This is // just for this example program and is not needed for CAN operation. // InitConsole(); // // For this example CAN0 is used with RX and TX pins on port B4 and B5. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port B needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB); // // Configure the GPIO pin muxing to select CAN0 functions for these pins. // This step selects which alternate function is available for these pins. // This is necessary if your part supports GPIO pin function muxing. // Consult the data sheet to see which functions are allocated per pin. // TODO: change this to select the port/pin you are using // GPIOPinConfigure(GPIO_PB4_CAN0RX); GPIOPinConfigure(GPIO_PB5_CAN0TX); // // Enable the alternate function on the GPIO pins. The above step selects // which alternate function is available. This step actually enables the // alternate function instead of GPIO for these pins. // TODO: change this to match the port/pin you are using // GPIOPinTypeCAN(GPIO_PORTB_BASE, GPIO_PIN_4 | GPIO_PIN_5); // // The GPIO port and pins have been set up for CAN. The CAN peripheral // must be enabled. // SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0); // // Initialize the CAN controller // CANInit(CAN0_BASE); // // Set up the bit rate for the CAN bus. 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. // In this example, the CAN bus is set to 500 kHz. In the function below, // the call to SysCtlClockGet() is used to determine the clock rate that // is used for clocking the CAN peripheral. This can be replaced with a // fixed value if you know the value of the system clock, saving the extra // function call. For some parts, the CAN peripheral is clocked by a fixed // 8 MHz regardless of the system clock in which case the call to // SysCtlClockGet() should be replaced with 8000000. Consult the data // sheet for more information about CAN peripheral clocking. // CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000); // // Enable interrupts on the CAN peripheral. This example uses static // allocation of interrupt handlers which means the name of the handler // is in the vector table of startup code. If you want to use dynamic // allocation of the vector table, then you must also call CANIntRegister() // here. // // CANIntRegister(CAN0_BASE, CANIntHandler); // if using dynamic vectors // CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // // Enable the CAN interrupt on the processor (NVIC). // IntEnable(INT_CAN0); // // Enable the CAN for operation. // CANEnable(CAN0_BASE); // // Initialize the message object that will be used for sending CAN // messages. The message will be 4 bytes that will contain an incrementing // value. Initially it will be set to 0. // // // Initialize message object 1 to be able to send CAN message 1. This // message object is not shared so it only needs to be initialized one // time, and can be used for repeatedly sending the same message ID. // g_sCANMsgObject1.ui32MsgID = 0x1001; g_sCANMsgObject1.ui32MsgIDMask = 0; g_sCANMsgObject1.ui32Flags = MSG_OBJ_TX_INT_ENABLE; g_sCANMsgObject1.ui32MsgLen = sizeof(g_pui8Msg1); g_sCANMsgObject1.pui8MsgData = g_pui8Msg1; // // Initialize message object 2 to be able to send CAN message 2. This // message object is not shared so it only needs to be initialized one // time, and can be used for repeatedly sending the same message ID. // g_sCANMsgObject2.ui32MsgID = 0x2001; g_sCANMsgObject2.ui32MsgIDMask = 0; g_sCANMsgObject2.ui32Flags = MSG_OBJ_TX_INT_ENABLE; g_sCANMsgObject2.ui32MsgLen = sizeof(g_pui8Msg2); g_sCANMsgObject2.pui8MsgData = g_pui8Msg2; // // Enter loop to send messages. Four messages will be sent once per // second. The contents of each message will be changed each time. // for(;;) { // // Send message 1 using CAN controller message object 1. This is // the only message sent using this message object. The // CANMessageSet() function will cause the message to be sent right // away. // PrintCANMessageInfo(&g_sCANMsgObject1, 1); CANMessageSet(CAN0_BASE, 1, &g_sCANMsgObject1, MSG_OBJ_TYPE_TX); // // Send message 2 using CAN controller message object 2. This is // the only message sent using this message object. The // CANMessageSet() function will cause the message to be sent right // away. // PrintCANMessageInfo(&g_sCANMsgObject2, 2); CANMessageSet(CAN0_BASE, 2, &g_sCANMsgObject2, MSG_OBJ_TYPE_TX); // // Load message object 3 with message 3. This is needs to be done each // time because message object 3 is being shared for two different // messages. // g_sCANMsgObject3.ui32MsgID = 0x3001; g_sCANMsgObject3.ui32MsgIDMask = 0; g_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE; g_sCANMsgObject3.ui32MsgLen = sizeof(g_pui8Msg3); g_sCANMsgObject3.pui8MsgData = g_pui8Msg3; // // Clear the flag that indicates that message 3 has been sent. This // flag will be set in the interrupt handler when a message has been // sent using message object 3. // g_bMsgObj3Sent = 0; // // Now send message 3 using CAN controller message object 3. This is // the first message sent using this message object. The // CANMessageSet() function will cause the message to be sent right // away. // PrintCANMessageInfo(&g_sCANMsgObject3, 3); CANMessageSet(CAN0_BASE, 3, &g_sCANMsgObject3, MSG_OBJ_TYPE_TX); // // Wait for the indication from the interrupt handler that message // object 3 is done, because we are re-using it for another message. // while(!g_bMsgObj3Sent) { } // // Load message object 3 with message 4. This is needed because // message object 3 is being shared for two different messages. // g_sCANMsgObject3.ui32MsgID = 0x3002; g_sCANMsgObject3.ui32MsgIDMask = 0; g_sCANMsgObject3.ui32Flags = MSG_OBJ_TX_INT_ENABLE; g_sCANMsgObject3.ui32MsgLen = sizeof(g_pui8Msg4); g_sCANMsgObject3.pui8MsgData = g_pui8Msg4; // // Now send message 4 using CAN controller message object 3. This is // the second message sent using this message object. The // CANMessageSet() function will cause the message to be sent right // away. // PrintCANMessageInfo(&g_sCANMsgObject3, 3); CANMessageSet(CAN0_BASE, 3, &g_sCANMsgObject3, MSG_OBJ_TYPE_TX); // // Wait 1 second before continuing // SimpleDelay(); // // Check the error flag to see if errors occurred // if(g_bErrFlag) { UARTprintf(" error - cable connected?\n"); } else { // // If no errors then print the count of message sent // UARTprintf(" total count = %u\n", g_ui32Msg1Count + g_ui32Msg2Count + g_ui32Msg3Count); } // // Change the value in the message data for each of the messages. // (*(uint32_t *)g_pui8Msg1)++; (*(uint32_t *)g_pui8Msg2)++; (*(uint32_t *)g_pui8Msg3)++; (*(uint32_t *)&g_pui8Msg4[0])++; (*(uint32_t *)&g_pui8Msg4[4])--; } // // Return no errors // return(0); }