I am having trouble bring up CAN on a 123F part. I have used simple_tx from the Tivaware examples as a starting point and modified to remove UART (no Uart on board) and move to prt F since that is where the CAN transciever is connected.
Transciever is properly terminated and their is another device on the CAN bus (A pc monitoring dongle).
I am not able to get anything from the CAN, when checking with 'scope and logic analyser I get DC lines, no transitions.
The main loop is running once a second (I can visually observe an LED toggle) but there is no signal on the TX line and the interrupt does not fire (I am assuming that I should get output even w/o the interrupt firing, that it not firing is just further indication something is not set up right).
It appears to be behaving as if it is not enabled or not directed t othe appropraite pins. I am including a copy of the code below.
Any thoughts as to what I have missed?
Robert
/*****************************************************************************
//
*****************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "inc/tm4c123fh6pm.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 "startup.h"
/*****************************************************************************
A counter that keeps track of the number of times the TX interrupt has
occurred, which should match the number of TX messages that were sent.
*****************************************************************************/
/*lint -esym(960,8.7) could move to block scope */
/*lint -esym(551,g_ui32MsgCount) Not accessed */
static volatile uint32_t g_ui32MsgCount = 0u;
/*****************************************************************************
A flag to indicate that some transmission error occurred.
*****************************************************************************/
static volatile bool g_bErrFlag = false;
/*****************************************************************************
This function provides a 1 second delay using a simple polling method.
*****************************************************************************/
static void SimpleDelay(void)
{
/* Delay cycles for 1 second */
SysCtlDelay(16000000u / 3u);
}
/******************************************************************************
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 CAN0_ISR(void)
{
uint32_t ui32Status;
/* Read the CAN interrupt status to find the cause of the interrupt */
ui32Status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);
GPIO_PORTB_DATA_R &= ~0x40u;
GPIO_PORTB_DATA_R |= 0x40u;
GPIO_PORTB_DATA_R &= ~0x40u;
GPIO_PORTB_DATA_R |= 0x40u;
GPIO_PORTB_DATA_R &= ~0x40u;
GPIO_PORTB_DATA_R |= 0x40u;
GPIO_PORTB_DATA_R &= ~0x40u;
GPIO_PORTB_DATA_R |= 0x40u;
GPIO_PORTB_DATA_R &= ~0x40u;
GPIO_PORTB_DATA_R |= 0x40u;
/* 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 =*/
(void)CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
/* Set a flag to indicate some errors may have occurred. */
g_bErrFlag = 1;
}
/* Check if the cause is message object 1, which what we are using for
sending messages.*/
else if(ui32Status == 1u) {
/* Getting to this point means that the TX interrupt occurred on
message object 1, and the message TX is complete. Clear the
message object interrupt. */
CANIntClear(CAN0_BASE, 1);
/* Increment a counter to keep track of how many messages have been
sent. In a real application this could be used to set flags to
indicate when a message is sent. */
g_ui32MsgCount++;
/* Since the message was sent, clear any error flags. */
g_bErrFlag = 0;
}
/* Otherwise, something unexpected caused the interrupt. This should
never happen. */
else {
/* Spurious interrupt handling can go here. */
}
}
/*****************************************************************************
Configure the CAN and enter a loop to transmit periodic CAN messages.
*****************************************************************************/
int main(void)
{
tCANMsgObject sCANMessage;
uint32_t ui32MsgData;
/*uint8_t *pui8MsgData;*/
/*pui8MsgData = (uint8_t *)&ui32MsgData;*/
/* Set up clock (80MHz with 16MHz crystal.) 200MHz PLL/2.5 */
SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);
/* Enable the GPIO ports for the indicator LED. */
SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOD | SYSCTL_RCGC2_GPIOB;
/* Do a dummy read to insert a few cycles after enabling the
peripheral. */
SYSCTL_RCGC2_R;
/* Enable the GPIO pin for the LED (PD6) . Set the direction as
output, and enable the GPIO pin for digital function. */
GPIO_PORTD_DIR_R = 0x40u;
GPIO_PORTD_DEN_R = 0x40u;
GPIO_PORTB_DIR_R = 0x40u;
GPIO_PORTB_DEN_R = 0x40u;
/* CAN0 is used with RX and TX pins on port F0 and F3. */
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
/* Configure the GPIO pin muxing to select CAN0 functions for these pins.
This step selects which alternate function is available for these pins.
This is necessary if your part supports GPIO pin function muxing.*/
GPIOPinConfigure(GPIO_PF0_CAN0RX);
GPIOPinConfigure(GPIO_PF3_CAN0TX);
/* Enable the alternate function on the GPIO pins. */
GPIOPinTypeCAN(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_3);
/* 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. */
(void)CANBitRateSet(CAN0_BASE, SysCtlClockGet(), 500000);
/* Enable interrupts on the CAN peripheral. */
CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
/* Enable the CAN interrupt on the processor (NVIC). */
IntEnable(INT_CAN0);
/* Enable the CAN for operation. */
CANEnable(CAN0_BASE);
/* Initialize the message object that will be used for sending CAN
messages. The message will be 4 bytes that will contain an incrementing
value. Initially it will be set to 0. */
ui32MsgData = 0u;
sCANMessage.ui32MsgID = 1u;
sCANMessage.ui32MsgIDMask = 0u;
sCANMessage.ui32Flags = MSG_OBJ_TX_INT_ENABLE;
sCANMessage.ui32MsgLen = sizeof(ui32MsgData);
/*lint -e925 pointer to pointer cast. C++ rule. Probably should clean up library */
sCANMessage.pui8MsgData = (void *)&ui32MsgData;
/* 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. */
for (;;) {
/* Toggle the LED. on port D */
if( (GPIO_PORTD_DATA_R & 0x40u) != 0){
GPIO_PORTD_DATA_R &= ~0x40u;
}
else {
GPIO_PORTD_DATA_R |= 0x40u;
}
/* Send the CAN message using object number 1 (not the same thing as
CAN ID, which is also 1 in this example). This function will cause
the message to be transmitted right away. */
CANMessageSet(CAN0_BASE, 1, &sCANMessage, MSG_OBJ_TYPE_TX);
/* Now wait 1 second before continuing */
SimpleDelay();
/* Check the error flag to see if errors occurred */
if(g_bErrFlag) {
/* Space to report error */
}
else {
/* Space to report success */
}
/* Increment the value in the message data. */
ui32MsgData++;
}
}