Hi, I am trying to test the CAN0 port on the Tiva C Series TM4C123G - TM4C123GH6PMI and I can't see the output with the oscilloscope. Everything seems to be right on debugging, but the pins PB4 and PB5 (RX and TX) have no output. I used a Project0 as starting point, and then I added the following example: C:\ti\TivaWare_C_Series-1.1\examples\peripherals\can\simple_tx.c I tried a lot of changes but it doesn't work. There are many topics about this issue on the forum, but they doesn't explain very well the solution (or maybe I am too noob in microcontrollers for understand it, sorry!) Thank you very much in advance!! This is the code I used: //***************************************************************************** // // simple_tx.c - Example demonstrating simple CAN message transmission. // // Copyright (c) 2010-2013 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the // distribution. // // Neither the name of Texas Instruments Incorporated nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // // This is part of revision 1.1 of the Tiva Firmware Development Package. // //***************************************************************************** #include #include #include "inc/hw_can.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "driverlib/can.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/pin_map.h" #include "driverlib/sysctl.h" #include "driverlib/uart.h" #include "utils/uartstdio.h" //***************************************************************************** // //! \addtogroup can_examples_list //! Simple CAN TX (simple_tx) //! //! This example shows the basic setup of CAN in order to transmit messages //! on the CAN bus. The CAN peripheral is configured to transmit messages //! with a specific CAN ID. A message is then transmitted once per second, //! using a simple delay loop for timing. The message that is sent is a 4 //! byte message that contains an incrementing pattern. A CAN interrupt //! handler is used to confirm message transmission and count the number of //! messages that have been sent. //! //! This example uses the following peripherals and I/O signals. You must //! review these and change as needed for your own board: //! - CAN0 peripheral //! - GPIO Port B peripheral (for CAN0 pins) //! - CAN0RX - PB4 //! - CAN0TX - PB5 //! //! This example uses the following interrupt handlers. To use this example //! in your own application you must add these interrupt handlers to your //! vector table. //! - INT_CAN0 - CANIntHandler // //***************************************************************************** //***************************************************************************** // // A counter that keeps track of the number of times the TX interrupt has // occurred, which should match the number of TX messages that were sent. // //***************************************************************************** volatile uint32_t g_ui32MsgCount = 0; //***************************************************************************** // // A flag to indicate that some transmission error occurred. // //***************************************************************************** volatile bool g_bErrFlag = 0; // //***************************************************************************** // // This function provides a 1 second delay using a simple polling method. // //***************************************************************************** void SimpleDelay(void) { // // Delay cycles for 1 second // SysCtlDelay(16000000 / 3); } //***************************************************************************** // // This function is the interrupt handler for the CAN peripheral. It checks // for the cause of the interrupt, and maintains a count of all messages that // have been transmitted. // //***************************************************************************** void CANIntHandler(void) { uint32_t ui32Status; // // Read the CAN interrupt status to find the cause of the interrupt // ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); // // If the cause is a controller status interrupt, then get the status // if(ui32Status == CAN_INT_INTID_STATUS) { // // Read the controller status. This will return a field of status // error bits that can indicate various errors. Error processing // is not done in this example for simplicity. Refer to the // API documentation for details about the error status bits. // The act of reading this status will clear the interrupt. If the // CAN peripheral is not connected to a CAN bus with other CAN devices // present, then errors will occur and will be indicated in the // controller status. // ui32Status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL); // // Set a flag to indicate some errors may have occurred. // g_bErrFlag = 1; } // // Check if the cause is message object 1, which what we are using for // sending messages. // else if(ui32Status == 1) { // // 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. // CANIntClear(CAN0_BASE, 1); // // 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. // g_ui32MsgCount++; // // Since the message was sent, clear any error flags. // g_bErrFlag = 0; } // // Otherwise, something unexpected caused the interrupt. This should // never happen. // else { // // Spurious interrupt handling can go here. // } } //***************************************************************************** // // Configure the CAN and enter a loop to transmit periodic CAN messages. // //***************************************************************************** int main(void) { tCANMsgObject sCANMessage; uint32_t ui32MsgData; uint8_t *pui8MsgData; pui8MsgData = (uint8_t *)&ui32MsgData; // // 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); // // For this example CAN0 is used with RX and TX pins on port E4 and E5. // 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. // GPIOPinConfigure(GPIO_PE4_CAN0RX); GPIOPinConfigure(GPIO_PE5_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. 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. ui32MsgData = 0; sCANMessage.ui32MsgID = 1; sCANMessage.ui32MsgIDMask = 0; sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE; sCANMessage.ui32MsgLen = sizeof(pui8MsgData); sCANMessage.pui8MsgData = pui8MsgData; // // Enter loop to send messages. A new message will be sent once per // second. The 4 bytes of message content will be treated as an uint32_t // and incremented by one each time. // while(1) { // Send the CAN message using object number 1 (not the same thing as // CAN ID, which is also 1 in this example). This function will cause // the message to be transmitted right away. CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX); // Now 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_ui32MsgCount); } // Increment the value in the message data. ui32MsgData++; } // Return no errors return(0); }
↧