This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

EK-TM4C1294XL: CAN1Tx Problem

Part Number: EK-TM4C1294XL
Other Parts Discussed in Thread: SN65HVD251, SN65HVD233

I'm having trouble using the CAN controller modules of the tm4c1294. I tried to modify the can example available for tm4c123 on tivaware, but I can't seem to make it work. I'm using 2 EK-TM4C1294XL, each one connected to a MCP2561 CAN transceiver on their CAN1 module (CAN1Rx PB0 and CAN1Tx PB1). My problem is, when I use an oscilloscope to watch the CAN1tx transmitting data, apparently no data is being transmied. CAN1Tx pin remains at 3V3 all the time. I get the message errors CAN_BUS_OFF and CAN_STATUS_EWARN. Below goes my code:

//*****************************************************************************
//
// can.c - Simple CAN example.
//
// Copyright (c) 2013-2017 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 2.1.4.178 of the DK-TM4C123G Firmware Package.
//
//*****************************************************************************

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "inc/hw_can.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "driverlib/fpu.h"
#include "driverlib/can.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "grlib/grlib.h"
#include "drivers/cfal96x64x16.h"
#include "utils/uartstdio.h"
#include "driverlib/interrupt.h"

//*****************************************************************************
//
//! \addtogroup example_list
//! <h1>CAN Example (can)</h1>
//!
//! This example application utilizes CAN to send characters back and forth
//! between two boards. It uses the UART to read / write the characters to
//! the UART terminal. It also uses the graphical display on the board to show
//! the last character transmited / received. Error handling is also included.
//!
//! CAN HARDWARE SETUP:
//!
//! To use this example you will need to hook up two DK-TM4C123G boards
//! together in a CAN network. This involves hooking the CANH screw terminals
//! together and the CANL terminals together. In addition 120ohm termination
//! resistors will need to be added to the edges of the network between CANH
//! and CANL. In the two board setup this means hooking a 120 ohm resistor
//! between CANH and CANL on both boards.
//!
//! See diagram below for visual. '---' represents wire.
//!
//! \verbatim
//! CANH--+--------------------------+--CANH
//! | |
//! .-. .-.
//! | |120ohm | |120ohm
//! | | | |
//! '-' '-'
//! | |
//! CANL--+--------------------------+--CANL
//! \endverbatim
//!
//! SOFTWARE SETUP:
//!
//! Once the hardware connections are setup connect both boards to the computer
//! via the In-Circuit Debug Interface USB port next to the graphical display.
//! Attach a UART terminal to each board configured 115,200 baud, 8-n-1 mode.
//!
//! Anything you type into one terminal will show up in the other terminal and
//! vice versa. The last character sent / received will also be displayed on
//! the graphical display on the board.
//
//*****************************************************************************

//*****************************************************************************
//
// A counter that keeps track of the number of times the TX & RX interrupt has
// occurred, which should match the number of messages that were transmitted /
// received.
//
//*****************************************************************************
volatile uint32_t g_ui32RXMsgCount = 0;
volatile uint32_t g_ui32TXMsgCount = 0;

//*****************************************************************************
//
// A flag for the interrupt handler to indicate that a message was received.
//
//*****************************************************************************
volatile bool g_bRXFlag = 0;

//*****************************************************************************
//
// A global to keep track of the error flags that have been thrown so they may
// be processed. This is necessary because reading the error register clears
// the flags, so it is necessary to save them somewhere for processing.
//
//*****************************************************************************
volatile uint32_t g_ui32ErrFlag = 0;

//*****************************************************************************
//
// CAN message Objects for data being sent / received
//
//*****************************************************************************
tCANMsgObject g_sCAN1RxMessage;
tCANMsgObject g_sCAN1TxMessage;

//*****************************************************************************
//
// Message Identifiers and Objects
// RXID is set to 0 so all messages are received
//
//*****************************************************************************
#define CAN1RXID 0
#define RXOBJECT 1
#define CAN1TXID 2
#define TXOBJECT 2

//*****************************************************************************
//
// Variables to hold character being sent / reveived
//
//*****************************************************************************
uint8_t g_ui8TXMsgData;
uint8_t g_ui8RXMsgData;

//*****************************************************************************
//
// Global context for text printed on graphics display
//
//*****************************************************************************
tContext g_sContext;


//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

//*****************************************************************************
//
// CAN 0 Interrupt Handler. It checks for the cause of the interrupt, and
// maintains a count of all messages that have been transmitted / received
//
//*****************************************************************************
void
CAN1IntHandler(void)
{
uint32_t ui32Status;

//
// Read the CAN interrupt status to find the cause of the interrupt
//
// CAN_INT_STS_CAUSE register values
// 0x0000 = No Interrupt Pending
// 0x0001-0x0020 = Number of message object that caused the interrupt
// 0x8000 = Status interrupt
// all other numbers are reserved and have no meaning in this system
//
ui32Status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE);

//
// If this was a status interrupt acknowledge it by reading the CAN
// controller status register.
//
if(ui32Status == CAN_INT_INTID_STATUS)
{
//
// Read the controller status. This will return a field of status
// error bits that can indicate various errors. Refer to the
// API documentation for details about the error status bits.
// The act of reading this status will clear the interrupt.
//
ui32Status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL);

//
// Add ERROR flags to list of current errors. To be handled
// later, because it would take too much time here in the
// interrupt.
//
g_ui32ErrFlag |= ui32Status;
}

//
// Check if the cause is message object RXOBJECT, which we are using
// for receiving messages.
//
else if(ui32Status == RXOBJECT)
{
//
// Getting to this point means that the RX interrupt occurred on
// message object RXOBJECT, and the message reception is complete.
// Clear the message object interrupt.
//
CANIntClear(CAN1_BASE, RXOBJECT);

//
// Increment a counter to keep track of how many messages have been
// received. In a real application this could be used to set flags to
// indicate when a message is received.
//
g_ui32RXMsgCount++;

//
// Set flag to indicate received message is pending.
//
g_bRXFlag = true;

//
// Since a message was received, clear any error flags.
// This is done because before the message is received it triggers
// a Status Interrupt for RX complete. by clearing the flag here we
// prevent unnecessary error handling from happeneing
//
g_ui32ErrFlag = 0;
}

//
// Check if the cause is message object TXOBJECT, which we are using
// for transmitting messages.
//
else if(ui32Status == TXOBJECT)
{
//
// Getting to this point means that the TX interrupt occurred on
// message object TXOBJECT, and the message reception is complete.
// Clear the message object interrupt.
//
CANIntClear(CAN1_BASE, TXOBJECT);

//
// Increment a counter to keep track of how many messages have been
// transmitted. In a real application this could be used to set
// flags to indicate when a message is transmitted.
//
g_ui32TXMsgCount++;

//
// Since a message was transmitted, clear any error flags.
// This is done because before the message is transmitted it triggers
// a Status Interrupt for TX complete. by clearing the flag here we
// prevent unnecessary error handling from happeneing
//
g_ui32ErrFlag = 0;
}

//
// Otherwise, something unexpected caused the interrupt. This should
// never happen.
//
else
{
//
// Spurious interrupt handling can go here.
//
}
}

//*****************************************************************************
//
// Configure the UART and its pins. This must be called before UARTprintf().
//
//*****************************************************************************
void
ConfigureUART(void)
{

// Uart0
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTConfigSetExpClk(UART0_BASE, 120000000, 115200,
(UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
UART_CONFIG_PAR_NONE));
UARTFIFODisable(UART0_BASE);
UARTEnable(UART0_BASE);
}

//*****************************************************************************
//
// Setup CAN1 to both send and receive at 500KHz.
// Interrupts on
// Use PE4 / PE5
//
//*****************************************************************************
void
InitCAN1(void)
{
//
// For this example CAN1 is used with RX and TX pins on port E4 and E5.
// GPIO port E needs to be enabled so these pins can be used.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
//
// Configure the GPIO pin muxing to select CAN1 functions for these pins.
// This step selects which alternate function is available for these pins.
//
GPIOPinConfigure(GPIO_PB0_CAN1RX);
GPIOPinConfigure(GPIO_PB1_CAN1TX);

//
// 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_0 | GPIO_PIN_1);

//
// The GPIO port and pins have been set up for CAN. The CAN peripheral
// must be enabled.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1);
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_CAN1));
//
// Initialize the CAN controller
//
CANInit(CAN1_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.
//
CANBitRateSet(CAN1_BASE, 120000000, 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.
//
CANIntRegister(CAN1_BASE, CAN1IntHandler);
CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);

//
// Enable the CAN interrupt on the processor (NVIC).
//
IntEnable(INT_CAN1);

//
// Enable the CAN for operation.
//
CANEnable(CAN1_BASE);

//
// Initialize a message object to be used for receiving CAN messages with
// any CAN ID. In order to receive any CAN ID, the ID and mask must both
// be set to 0, and the ID filter enabled.
//
g_sCAN1RxMessage.ui32MsgID = CAN1RXID;
g_sCAN1RxMessage.ui32MsgIDMask = 0;
g_sCAN1RxMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER;
g_sCAN1RxMessage.ui32MsgLen = sizeof(g_ui8RXMsgData);

//
// Now load the message object into the CAN peripheral. Once loaded the
// CAN will receive any message on the bus, and an interrupt will occur.
// Use message object RXOBJECT for receiving messages (this is not the
//same as the CAN ID which can be any value in this example).
//
CANMessageSet(CAN1_BASE, RXOBJECT, &g_sCAN1RxMessage, MSG_OBJ_TYPE_RX);

//
// Initialize the message object that will be used for sending CAN
// messages. The message will be 1 bytes that will contain the character
// received from the other controller. Initially it will be set to 0.
//
g_ui8TXMsgData = 0;
g_sCAN1TxMessage.ui32MsgID = CAN1TXID;
g_sCAN1TxMessage.ui32MsgIDMask = 0;
g_sCAN1TxMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
g_sCAN1TxMessage.ui32MsgLen = sizeof(g_ui8TXMsgData);
g_sCAN1TxMessage.pui8MsgData = (uint8_t *)&g_ui8TXMsgData;
}


//*****************************************************************************
//
// Can ERROR handling. When a message is received if there is an erro it is
// saved to g_ui32ErrFlag, the Error Flag Set. Below the flags are checked
// and cleared. It is left up to the user to add handling fuctionality if so
// desiered.
//
// For more information on the error flags please see the CAN section of the
// microcontroller datasheet.
//
// NOTE: you may experience errors during setup when only one board is powered
// on. This is caused by one board sending signals and there not being another
// board there to acknoledge it. Dont worry about these errors, they can be
// disregarded.
//
//*****************************************************************************
void
CANErrorHandler(void)
{
//
// CAN controller has entered a Bus Off state.
//
if(g_ui32ErrFlag & CAN_STATUS_BUS_OFF)
{
//
// Handle Error Condition here
//
// UARTprintf(" ERROR: CAN_STATUS_BUS_OFF \n");
debug_uart(" ERROR: CAN_STATUS_BUS_OFF \n", strlen(" ERROR: CAN_STATUS_BUS_OFF \n"));

//
// Clear CAN_STATUS_BUS_OFF Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_BUS_OFF);

}

//
// CAN controller error level has reached warning level.
//
if(g_ui32ErrFlag & CAN_STATUS_EWARN)
{
//
// Handle Error Condition here
//
//UARTprintf(" ERROR: CAN_STATUS_EWARN \n");
debug_uart(" ERROR: CAN_STATUS_EWARN \n", strlen(" ERROR: CAN_STATUS_EWARN \n"));
//
// Clear CAN_STATUS_EWARN Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_EWARN);
}

//
// CAN controller error level has reached error passive level.
//
if(g_ui32ErrFlag & CAN_STATUS_EPASS)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_EPASS Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_EPASS);
}

//
// A message was received successfully since the last read of this status.
//
if(g_ui32ErrFlag & CAN_STATUS_RXOK)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_RXOK Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_RXOK);
}

//
// A message was transmitted successfully since the last read of this
// status.
//
if(g_ui32ErrFlag & CAN_STATUS_TXOK)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_TXOK Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_TXOK);
}

//
// This is the mask for the last error code field.
//
if(g_ui32ErrFlag & CAN_STATUS_LEC_MSK)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_LEC_MSK Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_LEC_MSK);
}

//
// A bit stuffing error has occurred.
//
if(g_ui32ErrFlag & CAN_STATUS_LEC_STUFF)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_LEC_STUFF Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_LEC_STUFF);
}

//
// A formatting error has occurred.
//
if(g_ui32ErrFlag & CAN_STATUS_LEC_FORM)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_LEC_FORM Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_LEC_FORM);
}

//
// An acknowledge error has occurred.
//
if(g_ui32ErrFlag & CAN_STATUS_LEC_ACK)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_LEC_ACK Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_LEC_ACK);
}

//
// The bus remained a bit level of 1 for longer than is allowed.
//
if(g_ui32ErrFlag & CAN_STATUS_LEC_BIT1)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_LEC_BIT1 Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_LEC_BIT1);
}

//
// The bus remained a bit level of 0 for longer than is allowed.
//
if(g_ui32ErrFlag & CAN_STATUS_LEC_BIT0)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_LEC_BIT0 Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_LEC_BIT0);
}

//
// A CRC error has occurred.
//
if(g_ui32ErrFlag & CAN_STATUS_LEC_CRC)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_LEC_CRC Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_LEC_CRC);
}

//
// This is the mask for the CAN Last Error Code (LEC).
//
if(g_ui32ErrFlag & CAN_STATUS_LEC_MASK)
{
//
// Handle Error Condition here
//

//
// Clear CAN_STATUS_LEC_MASK Flag
//
g_ui32ErrFlag &= ~(CAN_STATUS_LEC_MASK);
}

//
// If there are any bits still set in g_ui32ErrFlag then something unhandled
// has happened. Print the value of g_ui32ErrFlag.
//
if(g_ui32ErrFlag !=0)
{
// UARTprintf(" Unhandled ERROR: %x \n",g_ui32ErrFlag);
debug_uart(" Unhandled ERROR: %x \n", strlen(" Unhandled ERROR: %x \n"));
}
}

void debug_uart(char * p, uint16_t length)
{
uint16_t x = 0;

while(x < length)
{
while (UARTBusy(UART0_BASE));
UARTCharPutNonBlocking(UART0_BASE, *p);
p++;
x++;
}
}

void sendCharUart0(unsigned char _c)
{
while (UARTBusy(UART0_BASE));
UARTCharPutNonBlocking(UART0_BASE, _c);
}

//*****************************************************************************
//
// Set up the system, initialize the UART, Graphics, and CAN. Then poll the
// UART for data. If there is any data send it, if there is any thing received
// print it out to the UART. If there are errors call the error handling
// function.
//
//*****************************************************************************
int
main(void)
{
//
// Enable lazy stacking for interrupt handlers. This allows floating-point
// instructions to be used within interrupt handlers, but at the expense of
// extra stack usage.
//
ROM_FPULazyStackingEnable();

//
// Set the clocking to run directly from the crystal.
//
uint32_t freq = SysCtlClockFreqSet(
(SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
SYSCTL_CFG_VCO_480), 120000000);

SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);

while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART3));
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));

GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6);
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0);

// Initialize the UART
ConfigureUART();


// Initialize CAN1
InitCAN1();


// Print welcome message
// UARTprintf("\nCAN Example App\n");
// UARTprintf("Type something to see it show up on the other terminal: \n\n");

debug_uart("\nCAN Example App\n", strlen("\nCAN Example App\n"));
debug_uart("Type something to see it show up on the other terminal: \n\n", strlen("Type something to see it show up on the other terminal: \n\n"));

// Poll UART for data, transmit across CAN when something is entered
while(1)
{

// If the flag is set, that means that the RX interrupt occurred and
// there is a message ready to be read from the CAN
if(g_bRXFlag)
{
//
// 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.
//
g_sCAN1RxMessage.pui8MsgData = (uint8_t *) &g_ui8RXMsgData;

//
// Read the message from the CAN. Message object RXOBJECT 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(CAN1_BASE, RXOBJECT, &g_sCAN1RxMessage, 0);

//
// Clear the pending message flag so that the interrupt handler can
// set it again when the next message arrives.
//
g_bRXFlag = 0;

//
// Check to see if there is an indication that some messages were
// lost.
//
if(g_sCAN1RxMessage.ui32Flags & MSG_OBJ_DATA_LOST)
{
// UARTprintf("\nCAN message loss detected\n");
debug_uart("\nCAN message loss detected\n",
strlen("\nCAN message loss detected\n"));
}


// Print the received character to the UART terminal
// UARTprintf("%c", g_ui8RXMsgData);
sendCharUart0(g_ui8RXMsgData);

//
// Print the received character to the display,
// clear line with spaces
//
}
else
{
//
// Error Handling
//
if(g_ui32ErrFlag != 0)
{
CANErrorHandler();
}

//
// See if there is something new to transmit
//
while(UARTCharsAvail(UART0_BASE))
{
//
// Read the next character from the UART terminal
//
g_ui8TXMsgData = UARTCharGetNonBlocking(UART0_BASE);


// Send the CAN message using object number TXOBJECT (not the
// same thing as CAN ID, which is also TXOBJECT in this
// example). This function will cause the message to be
// transmitted right away.
CANMessageSet(CAN1_BASE, TXOBJECT, &g_sCAN1TxMessage,
MSG_OBJ_TYPE_TX);
}
}
}
}

Does anyone have any idea what could be going wrong?

  • Hi,

      Your code is difficult to read. When you post your code please first select the 'Insert Code, Attach Files and more...' as shown below and then click on the button that will insert code using syntaxhighlighter.

      BTW, I will suggest you also reference the TivaWare CAN examples under <TivaWare_Installation>/examples/peripherals/can. In this folder you can find simple_tx.c and simple_rx.c. These examples are easier examples to get started. You just need to change the pin mapping for TM4C129.

  • //*****************************************************************************
    //
    // can.c - Simple CAN example.
    //
    // Copyright (c) 2013-2017 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 2.1.4.178 of the DK-TM4C123G Firmware Package.
    //
    //*****************************************************************************
    
    #include <stdint.h>
    #include <stdbool.h>
    #include <stdio.h>
    #include <string.h>
    #include "inc/hw_can.h"
    #include "inc/hw_ints.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/fpu.h"
    #include "driverlib/can.h"
    #include "driverlib/gpio.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/rom.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/uart.h"
    #include "grlib/grlib.h"
    //#include "drivers/cfal96x64x16.h"
    #include "utils/uartstdio.h"
    #include "driverlib/interrupt.h"
    
    //*****************************************************************************
    //
    //! \addtogroup example_list
    //! <h1>CAN Example (can)</h1>
    //!
    //! This example application utilizes CAN to send characters back and forth
    //! between two boards. It uses the UART to read / write the characters to
    //! the UART terminal. It also uses the graphical display on the board to show
    //! the last character transmited / received. Error handling is also included.
    //!
    //! CAN HARDWARE SETUP:
    //!
    //! To use this example you will need to hook up two DK-TM4C123G boards
    //! together in a CAN network. This involves hooking the CANH screw terminals
    //! together and the CANL terminals together. In addition 120ohm termination
    //! resistors will need to be added to the edges of the network between CANH
    //! and CANL.  In the two board setup this means hooking a 120 ohm resistor
    //! between CANH and CANL on both boards.
    //!
    //! See diagram below for visual. '---' represents wire.
    //!
    //! \verbatim
    //!       CANH--+--------------------------+--CANH
    //!             |                          |
    //!            .-.                        .-.
    //!            | |120ohm                  | |120ohm
    //!            | |                        | |
    //!            '-'                        '-'
    //!             |                          |
    //!       CANL--+--------------------------+--CANL
    //! \endverbatim
    //!
    //! SOFTWARE SETUP:
    //!
    //! Once the hardware connections are setup connect both boards to the computer
    //! via the In-Circuit Debug Interface USB port next to the graphical display.
    //! Attach a UART terminal to each board configured 115,200 baud, 8-n-1 mode.
    //!
    //! Anything you type into one terminal will show up in the other terminal and
    //! vice versa. The last character sent / received will also be displayed on
    //! the graphical display on the board.
    //
    //*****************************************************************************
    
    //*****************************************************************************
    //
    // A counter that keeps track of the number of times the TX & RX interrupt has
    // occurred, which should match the number of messages that were transmitted /
    // received.
    //
    //*****************************************************************************
    volatile uint32_t g_ui32RXMsgCount = 0;
    volatile uint32_t g_ui32TXMsgCount = 0;
    
    //*****************************************************************************
    //
    // A flag for the interrupt handler to indicate that a message was received.
    //
    //*****************************************************************************
    volatile bool g_bRXFlag = 0;
    
    //*****************************************************************************
    //
    // A global to keep track of the error flags that have been thrown so they may
    // be processed. This is necessary because reading the error register clears
    // the flags, so it is necessary to save them somewhere for processing.
    //
    //*****************************************************************************
    volatile uint32_t g_ui32ErrFlag = 0;
    
    //*****************************************************************************
    //
    // CAN message Objects for data being sent / received
    //
    //*****************************************************************************
    tCANMsgObject g_sCAN0RxMessage;
    tCANMsgObject g_sCAN0TxMessage;
    
    //*****************************************************************************
    //
    // Message Identifiers and Objects
    // RXID is set to 0 so all messages are received
    //
    //*****************************************************************************
    #define CAN1RXID                0
    #define RXOBJECT                1
    #define CAN1TXID                2
    #define TXOBJECT                2
    
    //*****************************************************************************
    //
    // Variables to hold character being sent / reveived
    //
    //*****************************************************************************
    uint8_t g_ui8TXMsgData;
    uint8_t g_ui8RXMsgData;
    
    //*****************************************************************************
    //
    // Global context for text printed on graphics display
    //
    //*****************************************************************************
    tContext g_sContext;
    
    //*****************************************************************************
    //
    // Screen line deffinitions, offsets from top in pixels
    //
    //*****************************************************************************
    #define SCREENLINE1             10
    #define SCREENLINE2             20
    #define SCREENLINE3             30
    #define SCREENLINE4             40
    #define SCREENLINE5             50
    
    //*****************************************************************************
    //
    // The error routine that is called if the driver library encounters an error.
    //
    //*****************************************************************************
    #ifdef DEBUG
    void
    __error__(char *pcFilename, uint32_t ui32Line)
    {
    }
    #endif
    
    //*****************************************************************************
    //
    // CAN 0 Interrupt Handler. It checks for the cause of the interrupt, and
    // maintains a count of all messages that have been transmitted / received
    //
    //*****************************************************************************
    void
    CAN0IntHandler(void)
    {
        uint32_t ui32Status;
    
        //
        // Read the CAN interrupt status to find the cause of the interrupt
        //
        // CAN_INT_STS_CAUSE register values
        // 0x0000        = No Interrupt Pending
        // 0x0001-0x0020 = Number of message object that caused the interrupt
        // 0x8000        = Status interrupt
        // all other numbers are reserved and have no meaning in this system
        //
        ui32Status = CANIntStatus(CAN1_BASE, CAN_INT_STS_CAUSE);
    
        //
        // If this was a status interrupt acknowledge it by reading the CAN
        // controller status register.
        //
        if(ui32Status == CAN_INT_INTID_STATUS)
        {
            //
            // Read the controller status.  This will return a field of status
            // error bits that can indicate various errors. Refer to the
            // API documentation for details about the error status bits.
            // The act of reading this status will clear the interrupt.
            //
            ui32Status = CANStatusGet(CAN1_BASE, CAN_STS_CONTROL);
    
            //
            // Add ERROR flags to list of current errors. To be handled
            // later, because it would take too much time here in the
            // interrupt.
            //
            g_ui32ErrFlag |= ui32Status;
        }
    
        //
        // Check if the cause is message object RXOBJECT, which we are using
        // for receiving messages.
        //
        else if(ui32Status == RXOBJECT)
        {
            //
            // Getting to this point means that the RX interrupt occurred on
            // message object RXOBJECT, and the message reception is complete.
            // Clear the message object interrupt.
            //
            CANIntClear(CAN1_BASE, RXOBJECT);
    
            //
            // Increment a counter to keep track of how many messages have been
            // received.  In a real application this could be used to set flags to
            // indicate when a message is received.
            //
            g_ui32RXMsgCount++;
    
            //
            // Set flag to indicate received message is pending.
            //
            g_bRXFlag = true;
    
            //
            // Since a message was received, clear any error flags.
            // This is done because before the message is received it triggers
            // a Status Interrupt for RX complete. by clearing the flag here we
            // prevent unnecessary error handling from happeneing
            //
            g_ui32ErrFlag = 0;
        }
    
        //
        // Check if the cause is message object TXOBJECT, which we are using
        // for transmitting messages.
        //
        else if(ui32Status == TXOBJECT)
        {
            //
            // Getting to this point means that the TX interrupt occurred on
            // message object TXOBJECT, and the message reception is complete.
            // Clear the message object interrupt.
            //
            CANIntClear(CAN1_BASE, TXOBJECT);
    
            //
            // Increment a counter to keep track of how many messages have been
            // transmitted. In a real application this could be used to set
            // flags to indicate when a message is transmitted.
            //
            g_ui32TXMsgCount++;
    
            //
            // Since a message was transmitted, clear any error flags.
            // This is done because before the message is transmitted it triggers
            // a Status Interrupt for TX complete. by clearing the flag here we
            // prevent unnecessary error handling from happeneing
            //
            g_ui32ErrFlag = 0;
        }
    
        //
        // Otherwise, something unexpected caused the interrupt.  This should
        // never happen.
        //
        else
        {
            //
            // Spurious interrupt handling can go here.
            //
        }
    }
    
    //*****************************************************************************
    //
    // Configure the UART and its pins.  This must be called before UARTprintf().
    //
    //*****************************************************************************
    void
    ConfigureUART(void)
    {
    
        // Uart0
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        UARTConfigSetExpClk(UART0_BASE, 120000000, 115200,
                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                        UART_CONFIG_PAR_NONE));
        UARTFIFODisable(UART0_BASE);
        UARTEnable(UART0_BASE);
    }
    
    //*****************************************************************************
    //
    // Setup CAN0 to both send and receive at 500KHz.
    // Interrupts on
    // Use PE4 / PE5
    //
    //*****************************************************************************
    void
    InitCAN0(void)
    {
        //
        // For this example CAN0 is used with RX and TX pins on port E4 and E5.
        // GPIO port E needs to be enabled so these pins can be used.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
        while (!SysCtlPeripheralReady(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.
        //
        GPIOPinConfigure(GPIO_PB0_CAN1RX);
        GPIOPinConfigure(GPIO_PB1_CAN1TX);
    
        //
        // 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_0 | GPIO_PIN_1);
    
        //
        // The GPIO port and pins have been set up for CAN.  The CAN peripheral
        // must be enabled.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1);
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_CAN1));
        //
        // Initialize the CAN controller
        //
        CANInit(CAN1_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.
        //
        CANBitRateSet(CAN1_BASE, 120000000, 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.
        //
        CANIntRegister(CAN1_BASE, CAN0IntHandler);
        CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        //
        // Enable the CAN interrupt on the processor (NVIC).
        //
        IntEnable(INT_CAN1);
    
        //
        // Enable the CAN for operation.
        //
        CANEnable(CAN1_BASE);
    
        //
        // Initialize a message object to be used for receiving CAN messages with
        // any CAN ID.  In order to receive any CAN ID, the ID and mask must both
        // be set to 0, and the ID filter enabled.
        //
        g_sCAN0RxMessage.ui32MsgID = CAN1RXID;
        g_sCAN0RxMessage.ui32MsgIDMask = 0;
        g_sCAN0RxMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER;
        g_sCAN0RxMessage.ui32MsgLen = sizeof(g_ui8RXMsgData);
    
        //
        // Now load the message object into the CAN peripheral.  Once loaded the
        // CAN will receive any message on the bus, and an interrupt will occur.
        // Use message object RXOBJECT for receiving messages (this is not the
        //same as the CAN ID which can be any value in this example).
        //
        CANMessageSet(CAN1_BASE, RXOBJECT, &g_sCAN0RxMessage, MSG_OBJ_TYPE_RX);
    
        //
        // Initialize the message object that will be used for sending CAN
        // messages.  The message will be 1 bytes that will contain the character
        // received from the other controller. Initially it will be set to 0.
        //
        g_ui8TXMsgData = 0;
        g_sCAN0TxMessage.ui32MsgID = CAN1TXID;
        g_sCAN0TxMessage.ui32MsgIDMask = 0;
        g_sCAN0TxMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
        g_sCAN0TxMessage.ui32MsgLen = sizeof(g_ui8TXMsgData);
        g_sCAN0TxMessage.pui8MsgData = (uint8_t *)&g_ui8TXMsgData;
    }
    
    
    //*****************************************************************************
    //
    // Can ERROR handling. When a message is received if there is an erro it is
    // saved to g_ui32ErrFlag, the Error Flag Set. Below the flags are checked
    // and cleared. It is left up to the user to add handling fuctionality if so
    // desiered.
    //
    // For more information on the error flags please see the CAN section of the
    // microcontroller datasheet.
    //
    // NOTE: you may experience errors during setup when only one board is powered
    // on. This is caused by one board sending signals and there not being another
    // board there to acknoledge it. Dont worry about these errors, they can be
    // disregarded.
    //
    //*****************************************************************************
    void
    CANErrorHandler(void)
    {
        //
        // CAN controller has entered a Bus Off state.
        //
        if(g_ui32ErrFlag & CAN_STATUS_BUS_OFF)
        {
            //
            // Handle Error Condition here
            //
    //        UARTprintf("    ERROR: CAN_STATUS_BUS_OFF \n");
            debug_uart("    ERROR: CAN_STATUS_BUS_OFF \n", strlen("    ERROR: CAN_STATUS_BUS_OFF \n"));
    
            //
            // Clear CAN_STATUS_BUS_OFF Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_BUS_OFF);
    
        }
    
        //
        // CAN controller error level has reached warning level.
        //
        if(g_ui32ErrFlag & CAN_STATUS_EWARN)
        {
            //
            // Handle Error Condition here
            //
            //UARTprintf("    ERROR: CAN_STATUS_EWARN \n");
            debug_uart("    ERROR: CAN_STATUS_EWARN \n", strlen("    ERROR: CAN_STATUS_EWARN \n"));
            //
            // Clear CAN_STATUS_EWARN Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_EWARN);
        }
    
        //
        // CAN controller error level has reached error passive level.
        //
        if(g_ui32ErrFlag & CAN_STATUS_EPASS)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_EPASS Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_EPASS);
        }
    
        //
        // A message was received successfully since the last read of this status.
        //
        if(g_ui32ErrFlag & CAN_STATUS_RXOK)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_RXOK Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_RXOK);
        }
    
        //
        // A message was transmitted successfully since the last read of this
        // status.
        //
        if(g_ui32ErrFlag & CAN_STATUS_TXOK)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_TXOK Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_TXOK);
        }
    
        //
        // This is the mask for the last error code field.
        //
        if(g_ui32ErrFlag & CAN_STATUS_LEC_MSK)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_LEC_MSK Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_LEC_MSK);
        }
    
        //
        // A bit stuffing error has occurred.
        //
        if(g_ui32ErrFlag & CAN_STATUS_LEC_STUFF)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_LEC_STUFF Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_LEC_STUFF);
        }
    
        //
        // A formatting error has occurred.
        //
        if(g_ui32ErrFlag & CAN_STATUS_LEC_FORM)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_LEC_FORM Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_LEC_FORM);
        }
    
        //
        // An acknowledge error has occurred.
        //
        if(g_ui32ErrFlag & CAN_STATUS_LEC_ACK)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_LEC_ACK Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_LEC_ACK);
        }
    
        //
        // The bus remained a bit level of 1 for longer than is allowed.
        //
        if(g_ui32ErrFlag & CAN_STATUS_LEC_BIT1)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_LEC_BIT1 Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_LEC_BIT1);
        }
    
        //
        // The bus remained a bit level of 0 for longer than is allowed.
        //
        if(g_ui32ErrFlag & CAN_STATUS_LEC_BIT0)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_LEC_BIT0 Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_LEC_BIT0);
        }
    
        //
        // A CRC error has occurred.
        //
        if(g_ui32ErrFlag & CAN_STATUS_LEC_CRC)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_LEC_CRC Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_LEC_CRC);
        }
    
        //
        // This is the mask for the CAN Last Error Code (LEC).
        //
        if(g_ui32ErrFlag & CAN_STATUS_LEC_MASK)
        {
            //
            // Handle Error Condition here
            //
    
            //
            // Clear CAN_STATUS_LEC_MASK Flag
            //
            g_ui32ErrFlag &= ~(CAN_STATUS_LEC_MASK);
        }
    
        //
        // If there are any bits still set in g_ui32ErrFlag then something unhandled
        // has happened. Print the value of g_ui32ErrFlag.
        //
        if(g_ui32ErrFlag !=0)
        {
    //        UARTprintf("    Unhandled ERROR: %x \n",g_ui32ErrFlag);
              debug_uart("    Unhandled ERROR: %x \n", strlen("    Unhandled ERROR: %x \n"));
        }
    }
    
    void debug_uart(char * p, uint16_t length)
    {
        uint16_t x = 0;
    
        while(x < length)
        {
            while (UARTBusy(UART0_BASE));
                UARTCharPutNonBlocking(UART0_BASE, *p);
            p++;
            x++;
        }
    }
    
    void sendCharUart0(unsigned char _c)
    {
        while (UARTBusy(UART0_BASE));
            UARTCharPutNonBlocking(UART0_BASE, _c);
    }
    
    //*****************************************************************************
    //
    // Set up the system, initialize the UART, Graphics, and CAN. Then poll the
    // UART for data. If there is any data send it, if there is any thing received
    // print it out to the UART. If there are errors call the error handling
    // function.
    //
    //*****************************************************************************
    int
    main(void)
    {
        //
        // Enable lazy stacking for interrupt handlers.  This allows floating-point
        // instructions to be used within interrupt handlers, but at the expense of
        // extra stack usage.
        //
        ROM_FPULazyStackingEnable();
    
        //
        // Set the clocking to run directly from the crystal.
        //
        uint32_t freq = SysCtlClockFreqSet(
                        (SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                                SYSCTL_CFG_VCO_480), 120000000);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART3));
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));
    
        GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6);
        GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0);
    
        // Initialize the UART
        ConfigureUART();
    
    
        // Initialize CAN0
        InitCAN0();
    
    
        // Print welcome message
    //    UARTprintf("\nCAN Example App\n");
    //    UARTprintf("Type something to see it show up on the other terminal: \n\n");
    
        debug_uart("\nCAN Example App\n", strlen("\nCAN Example App\n"));
        debug_uart("Type something to see it show up on the other terminal: \n\n", strlen("Type something to see it show up on the other terminal: \n\n"));
    
        // Poll UART for data, transmit across CAN when something is entered
        while(1)
        {
    
            // If the flag is set, that means that the RX interrupt occurred and
            // there is a message ready to be read from the CAN
            if(g_bRXFlag)
            {
                //
                // 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.
                //
                g_sCAN0RxMessage.pui8MsgData = (uint8_t *) &g_ui8RXMsgData;
    
                //
                // Read the message from the CAN.  Message object RXOBJECT 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(CAN1_BASE, RXOBJECT, &g_sCAN0RxMessage, 0);
    
                //
                // Clear the pending message flag so that the interrupt handler can
                // set it again when the next message arrives.
                //
                g_bRXFlag = 0;
    
                //
                // Check to see if there is an indication that some messages were
                // lost.
                //
                if(g_sCAN0RxMessage.ui32Flags & MSG_OBJ_DATA_LOST)
                {
    //                UARTprintf("\nCAN message loss detected\n");
                    debug_uart("\nCAN message loss detected\n",
                               strlen("\nCAN message loss detected\n"));
                }
    
    
                // Print the received character to the UART terminal
    //            UARTprintf("%c", g_ui8RXMsgData);
                sendCharUart0(g_ui8RXMsgData);
    
                //
                // Print the received character to the display, 
                // clear line with spaces
                //
            }
            else
            {
                //
                // Error Handling
                //
                if(g_ui32ErrFlag != 0)
                {
                    CANErrorHandler();
                }
    
                //
                // See if there is something new to transmit
                //
                while(UARTCharsAvail(UART0_BASE))
                {
                    //
                    // Read the next character from the UART terminal
                    //
                    g_ui8TXMsgData = UARTCharGetNonBlocking(UART0_BASE);
    
    
    
    
                    // Send the CAN message using object number TXOBJECT (not the
                    // same thing as CAN ID, which is also TXOBJECT in this
                    // example).  This function will cause the message to be
                    // transmitted right away.
                    CANMessageSet(CAN1_BASE, TXOBJECT, &g_sCAN0TxMessage,
                                  MSG_OBJ_TYPE_TX);
                }
            }
        }
    }
    

  • Hi,
    Did you have a CAN network setup with a least two nodes? The example you use is based on the DK-TM4C123 board which has the CAN transceiver on board. The EK-TM4C129 LaunchPad does not have the transceiver. I assume you have an external transceiver hooked. Is this correct? I quickly glanced through your code and I didn't really spot anything wrong that is obvious.
  • Yes, I do have two EK nodes, each one of them connected to their transceivers. I tested with the MCP2561 transceiver before and now I'm trying with the 65hvd251 transceiver. I have pin PB1 (CAN1tx) from tiva connected do pin 1 (TXD) from the transceiver, pin PB0 (CAN1RX) connected to pin 4 (RXD), Rs pin connected to ground, CANH and CANL from both transceivers connected together, but since I'm testing in a breadboard, where both transceivers are really close together, I didn't place any terminating resistors in the bus.
  • Can you reference the simple_tx.c and simple_rx.c examples and try these two examples too?
  • Yeah, sure. I'll give it a try.
  • Simple Rx
    //***************************************************************************** // // simple_rx.c - Example demonstrating simple CAN message reception. // // Copyright (c) 2010-2017 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDIFNG NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package. // //***************************************************************************** #include <stdbool.h> #include <stdint.h> #include <string.h> #include <stdio.h> #include "inc/hw_can.h" #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.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 //! <h1>Simple CAN RX (simple_rx)</h1> //! //! This example shows the basic setup of CAN in order to receive messages //! from the CAN bus. The CAN peripheral is configured to receive messages //! with any CAN ID and then print the message contents to the console. //! //! This example uses the following peripherals and I/O signals. You must //! review these and change as needed for your own board: //! - CAN1 peripheral //! - GPIO port B peripheral (for CAN1 pins) //! - CAN1RX - PB4 //! - CAN1TX - PB5 //! //! 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_CAN1 - CANIntHandler // //***************************************************************************** //***************************************************************************** // // A counter that keeps track of the number of times the RX interrupt has // occurred, which should match the number of messages that were received. // //***************************************************************************** volatile uint32_t g_ui32MsgCount = 0; //***************************************************************************** // // A flag for the interrupt handler to indicate that a message was received. // //***************************************************************************** volatile bool g_bRXFlag = 0; //***************************************************************************** // // A flag to indicate that some reception error occurred. // //***************************************************************************** volatile bool 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) { SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART3)); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0)); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA)); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD)); // Uart0 GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTConfigSetExpClk(UART0_BASE, 120000000, 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); UARTFIFODisable(UART0_BASE); UARTEnable(UART0_BASE); } //***************************************************************************** // // 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 received. // //***************************************************************************** void CANIntHandler(void) { uint32_t ui32Status; // // Read the CAN interrupt status to find the cause of the interrupt // ui32Status = CANIntStatus(CAN1_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. // ui32Status = 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 // receiving messages. // else if(ui32Status == 1) { // // Getting to this point means that the RX interrupt occurred on // message object 1, and the message reception is complete. Clear the // message object interrupt. // CANIntClear(CAN1_BASE, 1); // // Increment a counter to keep track of how many messages have been // received. In a real application this could be used to set flags to // indicate when a message is received. // g_ui32MsgCount++; // // Set flag to indicate received message is pending. // g_bRXFlag = 1; // // Since a message was received, clear any error flags. // g_bErrFlag = 0; } // // Otherwise, something unexpected caused the interrupt. This should // never happen. // else { // // Spurious interrupt handling can go here. // } } void debug_uart(char * p, uint16_t length) { uint16_t x = 0; while(x < length) { while (UARTBusy(UART0_BASE)); UARTCharPutNonBlocking(UART0_BASE, *p); p++; x++; } } void sendCharUart0(unsigned char _c) { while (UARTBusy(UART0_BASE)); UARTCharPutNonBlocking(UART0_BASE, _c); } //***************************************************************************** // // Configure the CAN and enter a loop to receive CAN messages. // //***************************************************************************** int main(void) { SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD)); GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6); GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0); uint32_t ui32SysClock; tCANMsgObject sCANMessage; uint8_t pui8MsgData[8]; // // Set the clocking to run directly from the external crystal/oscillator. // he SYSCTL_XTAL_ value must be changed to match the value of the // crystal used on your board. // ui32SysClock = SysCtlClockFreqSet( (SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); // // 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 CAN1 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); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB)); // // Configure the GPIO pin muxing to select CAN1 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_PB0_CAN1RX); GPIOPinConfigure(GPIO_PB1_CAN1TX); // // 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_0 | GPIO_PIN_1); // // The GPIO port and pins have been set up for CAN. The CAN peripheral // must be enabled. // SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1); while (!SysCtlPeripheralReady(SYSCTL_PERIPH_CAN1)); // // Initialize the CAN controller // CANInit(CAN1_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() or ui32SysClock 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() or ui32SysClock should be replaced with // 8000000. Consult the data sheet for more information about CAN // peripheral clocking. // CANBitRateSet(CAN1_BASE, ui32SysClock, 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(CAN1_BASE, CANIntHandler); // if using dynamic vectors // CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // // Enable the CAN interrupt on the processor (NVIC). // IntEnable(INT_CAN1); // // Enable the CAN for operation. // CANEnable(CAN1_BASE); // // Initialize a message object to be used for receiving CAN messages with // any CAN ID. In order to receive any CAN ID, the ID and mask must both // be set to 0, and the ID filter enabled. // sCANMessage.ui32MsgID = 0; sCANMessage.ui32MsgIDMask = 0; sCANMessage.ui32Flags = MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER; sCANMessage.ui32MsgLen = 8; // // Now load the message object into the CAN peripheral. Once loaded the // CAN will receive any message on the bus, and an interrupt will occur. // Use message object 1 for receiving messages (this is not the same as // the CAN ID which can be any value in this example). // CANMessageSet(CAN1_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_RX); // // Enter loop to process received messages. This loop just checks a flag // that is set by the interrupt handler, and if set it reads out the // message and displays the contents. This is not a robust method for // processing incoming CAN data and can only handle one messages at a time. // If many messages are being received close together, 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. // debug_uart("CAN reception code start!!!!\n",strlen("CAN reception code start!!!!\n")); for(;;) { unsigned int uIdx; // // If the flag is set, that means that the RX interrupt occurred and // there is a message ready to be read from the CAN // if(g_bRXFlag) { // // 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. // 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(CAN1_BASE, 1, &sCANMessage, 0); // // Clear the pending message flag so that the interrupt handler can // set it again when the next message arrives. // g_bRXFlag = 0; // // Check to see if there is an indication that some messages were // lost. // if(sCANMessage.ui32Flags & MSG_OBJ_DATA_LOST) { //UARTprintf("CAN message loss detected\n"); debug_uart("CAN message loss detected\n",strlen("CAN message loss detected\n")); } char ponteiro[50]; // // Print out the contents of the message that was received. // //UARTprintf("Msg ID=0x%08X len=%u data=0x",sCANMessage.ui32MsgID, sCANMessage.ui32MsgLen); sprintf(ponteiro,"Msg ID=0x%08X len=%u data=0x",sCANMessage.ui32MsgID, sCANMessage.ui32MsgLen); debug_uart(ponteiro, strlen(ponteiro)); for(uIdx = 0; uIdx < sCANMessage.ui32MsgLen; uIdx++) { //UARTprintf("%02X ", pui8MsgData[uIdx]); sprintf(ponteiro,"%d",pui8MsgData[uIdx]); debug_uart(ponteiro, strlen(ponteiro)); } //UARTprintf("total count=%u\n", g_ui32MsgCount); sprintf(ponteiro,"total count=%u\n",g_ui32MsgCount); debug_uart(ponteiro, strlen(ponteiro)); } } // // Return no errors // return(0); }

    Simple Tx

    //*****************************************************************************
    //
    // simple_tx.c - Example demonstrating simple CAN message transmission.
    //
    // Copyright (c) 2010-2017 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 SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // 
    // This is part of revision 2.1.4.178 of the Tiva Firmware Development Package.
    //
    //*****************************************************************************
    
    #include <stdbool.h>
    #include <stdint.h>
    #include <string.h>
    #include <stdio.h>
    #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
    //! <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:
    //! - CAN1 peripheral
    //! - GPIO Port B peripheral (for CAN1 pins)
    //! - CAN1RX - PB4
    //! - CAN1TX - PB5
    //!
    //! 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_CAN1 - 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 sets up UART0 to be used for a console to display information
    // as the example is running.
    //
    //*****************************************************************************
    void
    InitConsole(void)
    {
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UART3);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART3));
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_UART0));
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));
        // Uart0
        GPIOPinConfigure(GPIO_PA0_U0RX);
        GPIOPinConfigure(GPIO_PA1_U0TX);
        GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
        UARTConfigSetExpClk(UART0_BASE, 120000000, 115200,
                (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE |
                        UART_CONFIG_PAR_NONE));
        UARTFIFODisable(UART0_BASE);
        UARTEnable(UART0_BASE);
    }
    
    //*****************************************************************************
    //
    // 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(CAN1_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(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(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(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_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.
    //
    //*****************************************************************************
    void debug_uart(char * p, uint16_t length)
    {
        uint16_t x = 0;
    
        while(x < length)
        {
            while (UARTBusy(UART0_BASE));
                UARTCharPutNonBlocking(UART0_BASE, *p);
            p++;
            x++;
        }
    }
    
    void sendCharUart0(unsigned char _c)
    {
        while (UARTBusy(UART0_BASE));
            UARTCharPutNonBlocking(UART0_BASE, _c);
    }
    
    int
    main(void)
    {
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOD));
        GPIOPinTypeGPIOOutput(GPIO_PORTD_BASE, GPIO_PIN_6);
        GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_6, 0);
        uint32_t ui32SysClock;
    
        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.
        //
        ui32SysClock =  SysCtlClockFreqSet(
                (SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL |
                        SYSCTL_CFG_VCO_480), 120000000);
    
        //
        // 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 CAN1 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);
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOB));
    
        //
        // Configure the GPIO pin muxing to select CAN1 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_PB0_CAN1RX);
        GPIOPinConfigure(GPIO_PB1_CAN1TX);
    
        //
        // 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_1 | GPIO_PIN_0);
    
        //
        // The GPIO port and pins have been set up for CAN.  The CAN peripheral
        // must be enabled.
        //
        SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN1);
        while (!SysCtlPeripheralReady(SYSCTL_PERIPH_CAN1));
    
        //
        // Initialize the CAN controller
        //
        CANInit(CAN1_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() or ui32SysClock 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() or ui32SysClock should be replaced with
        // 8000000.  Consult the data sheet for more information about CAN
        // peripheral clocking.
        //
        CANBitRateSet(CAN1_BASE, ui32SysClock, 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(CAN1_BASE, CANIntHandler); // if using dynamic vectors
        //
        CANIntEnable(CAN1_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    
        //
        // Enable the CAN interrupt on the processor (NVIC).
        //
        IntEnable(INT_CAN1);
    
        //
        // Enable the CAN for operation.
        //
        CANEnable(CAN1_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.
        //
        char ponteiro[50];
    
        while(1)
        {
            //
            // 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",
    //                   pui8MsgData[0], pui8MsgData[1], pui8MsgData[2],
    //                   pui8MsgData[3]);
            sprintf(ponteiro,"Sending msg: 0x%02X %02X %02X %02X\n\r",pui8MsgData[0], pui8MsgData[1], pui8MsgData[2],pui8MsgData[3]);
            debug_uart(ponteiro, strlen(ponteiro));
    
            //
            // 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(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");
                debug_uart(" error - cable connected?\n\r", strlen(" error - cable connected?\n\r"));
            }
            else
            {
                //
                // If no errors then print the count of message sent
                //
                //UARTprintf(" total count = %u\n", g_ui32MsgCount);
                sprintf(ponteiro," total count = %u\n\r",g_ui32MsgCount);
                debug_uart(ponteiro, strlen(ponteiro));
            }
    
            //
            // Increment the value in the message data.
            //
            ui32MsgData++;
        }
    
        //
        // Return no errors
        //
        return(0);
    }

    Tried the examples, still nothing. Right now, I can see that some data is been sent but something happens during transmission and I keep getting the "is cable connected?" error. Any ideas?

  • Tried the examples, still nothing. Right now, I can see that some data is been sent but something happens during transmission and I keep getting the "is cable connected?" error. Any ideas?
  • This is how my network looks like right now.
  • Where are your two 120 Ohm termination resistors? You must have termination resistors between pins 6 and 7 of the CAN transceivers or the bus will not be able to return to the recessive state.

    See the following information on how to setup a CAN bus:
    www.ti.com/.../sloa101b.pdf

  • Tried that, didn't work. Voltage difference between canh and canl remains at zero volts, when I measure it using my oscilloscope.
  • Tried it with the resistors but it didn't make any difference.
  • Are you really using SN65HVD251 transceivers? Those are 5V parts and you are only powering with 3.3V. Using SN65HVD233 would be correct.