I'm using two TM4C123GXL develop board to sending a message via CAN interface, the Node address is 1 and 2.
When I config baud rate in the bus = 1000000, the message send and receive is correctly. However, when I config baud rate = 500000 or 125000, I have a receive message not correct. For example, I send "123456789", I receive "13579" in both Node.
I use sn65hvd235d for a CAN bus transceive, RS pin (pin 8) jump to GND for high speed mode.
Here is my code, it is a bit modify from TM4C123G CAN example.
#include <stdint.h>
#include <stdbool.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 "utils/uartstdio.h"
#include "driverlib/interrupt.h"
//======================================================
//=====================================================
const uint32_t CANID = 0x02; Node ID: 1 or 2 or another
uint32_t CANBitTiming;
uint32_t clock;
//======================================================
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;
tCANBitClkParms g_sCANBitClkParms;
tCANBitClkParms g_sCANBitClkParms_Read;
//*****************************************************************************
//
// Message Identifiers and Objects
// RXID is set to 0 so all messages are received
//
//*****************************************************************************
// Dia chi CAN
#define CAN0RXID CANID
#define CAN0TXID CANID
// CHua biet???
#define RXOBJECT 1
#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
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(CAN0_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(CAN0_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(CAN0_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(CAN0_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)
{
//
// Enable the GPIO Peripheral used by the UART.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
//
// Enable UART0
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);
//
// Configure GPIO Pins for UART mode.
//
GPIOPinConfigure(GPIO_PA0_U0RX);
GPIOPinConfigure(GPIO_PA1_U0TX);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
//
// Use the internal 16MHz oscillator as the UART clock source.
//
UARTClockSourceSet(UART0_BASE, UART_CLOCK_PIOSC);
//
// Initialize the UART for console I/O.
//
UARTStdioConfig(0, 115200, 16000000);
}
//*****************************************************************************
//
// 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_GPIOE);
//
// 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_PE4_CAN0RX);
GPIOPinConfigure(GPIO_PE5_CAN0TX);
//
// Enable the alternate function on the GPIO pins. The above step selects
// which alternate function is available. This step actually enables the
// alternate function instead of GPIO for these pins.
//
GPIOPinTypeCAN(GPIO_PORTE_BASE, GPIO_PIN_4 | GPIO_PIN_5);
//
// The GPIO port and pins have been set up for CAN. The CAN peripheral
// must be enabled.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);
//
// Initialize the CAN controller
//
CANInit(CAN0_BASE);
//
// Set up the bit rate for the CAN bus. This function sets up the CAN
// bus timing for a nominal configuration. You can achieve more control
// over the CAN bus timing by using the function CANBitTimingSet() instead
// of this one, if needed.
// In this example, the CAN bus is set to 500 kHz.
// TODO: CAN clock
CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000);
// g_sCANBitClkParms.ui32SyncPropPhase1Seg = 2;
// g_sCANBitClkParms.ui32Phase2Seg = 1;
// g_sCANBitClkParms.ui32SJW = 4;
// g_sCANBitClkParms.ui32QuantumPrescaler = 40;
// CANBitTimingSet(CAN0_BASE, &g_sCANBitClkParms);
//
// 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.
//
CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
//
// Enable the CAN interrupt on the processor (NVIC).
//
IntEnable(INT_CAN0);
//
// Enable the CAN for operation.
//
CANEnable(CAN0_BASE);
//
// Initialize a message object to 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 = CAN0RXID;
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(CAN0_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 = CAN0TXID;
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;
}
//*****************************************************************************
//
// Set up the OLED Graphical Display
//
//*****************************************************************************
//*****************************************************************************
//
// 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");
//
// 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");
//
// 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);
}
}
//*****************************************************************************
//
// 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.
//
FPULazyStackingEnable();
//
// Set the clocking to run directly from the crystal.
// TODO: SYS clock
// /5 = 40Mhz
// /4 = 50Mhz
// /2 = 80Mhz
SysCtlClockSet(SYSCTL_SYSDIV_2 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
//
// Initialize the UART
//
ConfigureUART();
//
// Initialize the graphical display
//
// InitGraphics();
//
// Initialize CAN0
//
InitCAN0();
//
// Print welcome message
//
UARTprintf("\nCAN ID: %d\n",CANID);
//TODO: Get CANBitClkParms
CANBitTimingGet(CAN0_BASE,&g_sCANBitClkParms_Read);
clock = SysCtlClockGet();
// UARTprintf("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(CAN0_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");
}
//
// Print the received character to the UART terminal
//
UARTprintf("%c", g_ui8RXMsgData);
//
// Print the received character to the display,
// clear line with spaces
//
/*
GrStringDrawCentered(&g_sContext, "RX Data", -1,
GrContextDpyWidthGet(&g_sContext) / 2,
SCREENLINE2, 0);
GrStringDrawCentered(&g_sContext, (const char *) &g_ui8RXMsgData,
1, GrContextDpyWidthGet(&g_sContext) / 2,
SCREENLINE3, true);
GrFlush(&g_sContext);
*/
}
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);
//
// Write the character to the display
// clear line with spaces
//
/*
GrStringDrawCentered(&g_sContext, "TX Data", -1,
GrContextDpyWidthGet(&g_sContext) / 2,
SCREENLINE4, true);
GrStringDrawCentered(&g_sContext,
(const char *)&g_ui8TXMsgData, 1,
GrContextDpyWidthGet(&g_sContext) / 2,
SCREENLINE5, true);
GrFlush(&g_sContext);
*/
//
// 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(CAN0_BASE, TXOBJECT, &g_sCAN0TxMessage,
MSG_OBJ_TYPE_TX);
}
}
}
}