I use the EKS-LM3S9B92 EVK and a selfmade CAN Transciever Board. I tryed to run the StellarisWare example (Examples\Peripherals\CAN\simple_tx.c) on my Board but i can't transmit any messages.
#include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_can.h" #include "inc/hw_ints.h" #include "driverlib/can.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "utils/uartstdio.h" //***************************************************************************** //***************************************************************************** // // 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 unsigned long g_ulMsgCount = 0; //***************************************************************************** // // A flag to indicate that some transmission error occurred. // //***************************************************************************** volatile unsigned long g_bErrFlag = 0; //***************************************************************************** // // This function sets up UART0 to be used for a console to display information // as the example is running. // //***************************************************************************** void InitConsole(void) { // // Enable GPIO port A which is used for UART0 pins // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // // Configure the pin muxing for UART0 functions on port A0 and A1. // This step is not necessary if your part does not support pin muxing. // GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); // // Select the alternate (UART) function for these pins. // GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // Initialize the UART for console I/O. // UARTStdioInit(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) { unsigned long ulStatus; // // Read the CAN interrupt status to find the cause of the interrupt // ulStatus = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE); // // If the cause is a controller status interrupt, then get the status // if(ulStatus == 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. // ulStatus = CANStatusGet(CAN1_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(ulStatus == 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(CAN1_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_ulMsgCount++; // // 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; unsigned char ucMsgData[4]; SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); InitConsole(); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF); GPIOPinConfigure(GPIO_PF0_CAN1RX); GPIOPinConfigure(GPIO_PF1_CAN1TX); GPIOPinTypeCAN(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_1); SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1); CANInit(CAN1_BASE); CANBitRateSet(CAN1_BASE, SysCtlClockGet(), 500000); CANIntRegister(CAN1_BASE, CANIntHandler); // if using dynamic vectors CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); IntEnable(INT_CAN1); CANEnable(CAN1_BASE); *(unsigned long *)ucMsgData = 0; sCANMessage.ulMsgID = 1; // CAN message ID - use 1 sCANMessage.ulMsgIDMask = 0; // no mask needed for TX sCANMessage.ulFlags = MSG_OBJ_TX_INT_ENABLE; // enable interrupt on TX sCANMessage.ulMsgLen = sizeof(ucMsgData); // size of message is 4 sCANMessage.pucMsgData = ucMsgData; // ptr to message content UARTprintf("Status_Tx:%08X",CANStatusGet(CAN0_BASE,CAN_STATUS_TXOK)); UARTprintf("Status_ACK:%08X",CANStatusGet(CAN0_BASE,CAN_STATUS_LEC_ACK)); for(;;) { UARTprintf("Sending msg: 0x%02X %02X %02X %02X", ucMsgData[0], ucMsgData[1], ucMsgData[2], ucMsgData[3]); CANMessageSet(CAN1_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_ulMsgCount); } // // Increment the value in the message data. // (*(unsigned long *)ucMsgData)++; } // // Return no errors // return(0); }
I have no errors or warnings when I build the programm. But my CAN0_tx pin (PD1) has a permanent high (3.3V) signal.
I hope someone can help me and tell me what I have to do!
Sebastian,
In the code you've posted, you're configuring the CAN1 module at PF0 (CAN1Rx) and PF1 (CAN1Tx). If you'd prefer CAN0Rx and CAN0Tx to be used, change the GPIO port configuration from Port F to Port D and CAN1 to CAN0.
Additionally, if you are using CAN1, be sure that Int_CAN1 - CANIntHandler is added to the vector table, and any other changes to the start-up file are made, depending on the particular compiler that you are using.
-Rebecca
HI Rebecca,
sry i've posted the wrong code (it's a modified one, to see if use CAN1 can fix my problem). Normally i use CAN0 with the original port config seen in the example.
I've added the Interrupt (#define INT_CAN0 - CANIntHandler) to my vector table, hope this is ok.
Which other changes in start-up do i have to do? (I use the TI v4.9.1 Compiler and CCS v5)
After a long day of testing and debugging I still have the problem that my CAN do not work. Now i have the problem that there is a buserror i cant fix. The Interrupt handler is executet once and the error is never reseted.
I think now i know why the Controller is in BusOff but i dont know how to fix it. When i look to the different CAN Register i found an error in CAN_STS_LEC Reg (Value: 101). The Datasheet says it is an Bit 0 Error what means that the port cant be set to a low level. When I disconnect my CAN Transceiver Board to exclude an mistake on my board the CAN0 Tx pin is still on a permanent high level and there is no vissible messagedata. I messured my board and there is no routing mistake. So i think there is a problem with the GPIO config or something like that.
main.c:
//***************************************************************************** // // simple_tx.c - Example demonstrating simple CAN message transmission. // // Copyright (c) 2010-2011 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 6852 of the Stellaris Firmware Development Package. // //***************************************************************************** #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_can.h" #include "inc/hw_ints.h" #include "driverlib/can.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/gpio.h" #include "utils/uartstdio.h" //***************************************************************************** // //! \addtogroup can_examples_list //! <h1>Simple CAN TX (simple_tx)</h1> //! //! 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 D peripheral (for CAN0 pins) //! - CAN0RX - PD0 //! - CAN0TX - PD1 //! //! The following UART signals are configured only for displaying console //! messages for this example. These are not required for operation of CAN. //! - GPIO port A peripheral (for UART0 pins) //! - UART0RX - PA0 //! - UART0TX - PA1 //! //! 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 unsigned long g_ulMsgCount = 0; //***************************************************************************** // // A flag to indicate that some transmission error occurred. // //***************************************************************************** volatile unsigned long g_bErrFlag = 0; //***************************************************************************** // // This function sets up UART0 to be used for a console to display information // as the example is running. // //***************************************************************************** void InitConsole(void) { // // Enable GPIO port A which is used for UART0 pins // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); // // Configure the pin muxing for UART0 functions on port A0 and A1. // This step is not necessary if your part does not support pin muxing. // GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); // // Select the alternate (UART) function for these pins. // GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // Initialize the UART for console I/O. // UARTStdioInit(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) { unsigned long ulStatus; // // Read the CAN interrupt status to find the cause of the interrupt // ulStatus = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE); // // If the cause is a controller status interrupt, then get the status // if(ulStatus == 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. // ulStatus = 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(ulStatus == 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_ulMsgCount++; // // 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; unsigned char ucMsgData[4]; // // 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 D0 and D1. // The actual port and pins used may be different on your part, consult // the data sheet for more information. // GPIO port D needs to be enabled so these pins can be used. // TODO: change this to whichever GPIO port you are using // SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); // // 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_PD0_CAN0RX); GPIOPinConfigure(GPIO_PD1_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_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1); // // 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. // *(unsigned long *)ucMsgData = 0; sCANMessage.ulMsgID = 1; // CAN message ID - use 1 sCANMessage.ulMsgIDMask = 0; // no mask needed for TX sCANMessage.ulFlags = MSG_OBJ_TX_INT_ENABLE; // enable interrupt on TX sCANMessage.ulMsgLen = sizeof(ucMsgData); // size of message is 4 sCANMessage.pucMsgData = ucMsgData; // ptr to message content // // 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 unsigned // long and incremented by one each time. // for(;;) { // // Print a message to the console showing the message count and the // contents of the message being sent. // UARTprintf("Sending msg: 0x%02X %02X %02X %02X", ucMsgData[0], ucMsgData[1], ucMsgData[2], ucMsgData[3]); // // 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_ulMsgCount); } // // Increment the value in the message data. // (*(unsigned long *)ucMsgData)++; } // // Return no errors // return(0); }
interrupt table (hw_ints.h):
// The following are defines for the interrupt assignments. // //***************************************************************************** #define INT_GPIOA 16 // GPIO Port A #define INT_GPIOB 17 // GPIO Port B #define INT_GPIOC 18 // GPIO Port C #define INT_GPIOD 19 // GPIO Port D #define INT_GPIOE 20 // GPIO Port E #define INT_UART0 21 // UART0 Rx and Tx #define INT_UART1 22 // UART1 Rx and Tx #define INT_SSI0 23 // SSI0 Rx and Tx #define INT_I2C0 24 // I2C0 Master and Slave #define INT_PWM_FAULT 25 // PWM Fault #define INT_PWM0 26 // PWM Generator 0 #define INT_PWM1 27 // PWM Generator 1 #define INT_PWM2 28 // PWM Generator 2 #define INT_QEI0 29 // Quadrature Encoder 0 #define INT_ADC0SS0 30 // ADC0 Sequence 0 #define INT_ADC0SS1 31 // ADC0 Sequence 1 #define INT_ADC0SS2 32 // ADC0 Sequence 2 #define INT_ADC0SS3 33 // ADC0 Sequence 3 #define INT_WATCHDOG 34 // Watchdog timer #define INT_TIMER0A 35 // Timer 0 subtimer A #define INT_TIMER0B 36 // Timer 0 subtimer B #define INT_TIMER1A 37 // Timer 1 subtimer A #define INT_TIMER1B 38 // Timer 1 subtimer B #define INT_TIMER2A 39 // Timer 2 subtimer A #define INT_TIMER2B 40 // Timer 2 subtimer B #define INT_COMP0 41 // Analog Comparator 0 #define INT_COMP1 42 // Analog Comparator 1 #define INT_COMP2 43 // Analog Comparator 2 #define INT_SYSCTL 44 // System Control (PLL, OSC, BO) #define INT_FLASH 45 // FLASH Control #define INT_GPIOF 46 // GPIO Port F #define INT_GPIOG 47 // GPIO Port G #define INT_GPIOH 48 // GPIO Port H #define INT_UART2 49 // UART2 Rx and Tx #define INT_SSI1 50 // SSI1 Rx and Tx #define INT_TIMER3A 51 // Timer 3 subtimer A #define INT_TIMER3B 52 // Timer 3 subtimer B #define INT_I2C1 53 // I2C1 Master and Slave #define INT_QEI1 54 // Quadrature Encoder 1 #define INT_CAN0 55 // CAN0 #define INT_CAN1 56 // CAN1 #define INT_CAN2 57 // CAN2 #define INT_ETH 58 // Ethernet #define INT_HIBERNATE 59 // Hibernation module #define INT_USB0 60 // USB 0 Controller #define INT_PWM3 61 // PWM Generator 3 #define INT_UDMA 62 // uDMA controller #define INT_UDMAERR 63 // uDMA Error #define INT_ADC1SS0 64 // ADC1 Sequence 0 #define INT_ADC1SS1 65 // ADC1 Sequence 1 #define INT_ADC1SS2 66 // ADC1 Sequence 2 #define INT_ADC1SS3 67 // ADC1 Sequence 3 #define INT_I2S0 68 // I2S0 #define INT_EPI0 69 // EPI0 #define INT_GPIOJ 70 // GPIO Port J //***************************************************************************** // // The following are defines for the total number of interrupts. // //***************************************************************************** #define NUM_INTERRUPTS 71 //********************************************
I hope somebody can help me?!
Can you tell me a little about your transceiver board? What part are you using? I understand that you are using an EK-LM3S9B92 for the receiver (have you programmed the CAN receiver code into this board to properly receive the CAN messages?), are you using an LM3S9B92 MCU for your transceiver board? If you are using an LM3S9B92 for you transceiver board, then the GPIO configurations provided in the example code (what you've posted above) are correct (correct ports and correct pins for the UART and the CAN0 functions). This doesn't seem like the issue. How are you programming the transceiver board? How are you measuring the expected data from the CAN0Tx pin?
Hi Sebastian,
I'm an engineer experienced with CAN hardware implementation. Would you would post a schematic and describe your transceiver circuit to us? Also, if you could describe the whole CAN network you are testing against, that would be a great help.
Thanks!
Hi Rebecca,
i think you misunderstand my transciever board. I am using an EKS-LM3S9B92 EVK to send messages with the code above and the transciever board i talk about is a board with CAN transciever (MCP2551). This is a IC that serves as interface between CAN controller and physikal bus. It converts the TTL signal in an differentail.To recieve the messages i use a programm named CANoe.
I measured the CAN0tx pin with a scope.
Hi,
I encountered the exact same problems, only on a Stellaris Launchpad.
First I was able to measure some weird stuff on the TX Pin but got an Error (-> Bus Off) and now it doesn't transmit nothing at all.
Could you tell me how you fixed it?
-Thomas