Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

CAN Xmit

CAN Xmit Sample Application (SSK 2.x)

Overview

The CAN Xmit sample application demonstrates how to transmit CAN messages on a selected channel using the NAI Software Support Kit (SSK 2.x). The application supports both CAN A/B (standard CAN 2.0) and CAN J1939 protocols. It queries the user for the channel, protocol (on modules that support both), baud rate timing, PGN (for J1939), and payload size, then configures the channel for transmission and sends frames on demand.

This sample supports CAN module types including CB1, CB2, CB3, CB6, and CB8. On CB3 and CB6 modules, the user can choose between CAN A/B and J1939 protocols. CB2 defaults to J1939, and CB1 defaults to CAN A/B.

For the SSK 1.x version, see CAN Transmit (SSK 1.x).

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with a CAN module installed (CB1-CB3, CB6, or CB8).

  • SSK 2.x installed on your development host.

  • The sample applications built. Refer to the SSK 2.x Software Development Guide for platform-specific build instructions.

How to Run

Launch the can_xmit executable from your build output directory. On startup the application looks for a configuration file (default_CANTx.txt). Once connected, the application queries for configuration parameters and enters a transmit loop.

Board Connection and Module Selection

Note
This startup sequence is common to all NAI sample applications.

The main() function follows a standard SSK 2.x startup flow. After connecting, it verifies the channel count is non-zero using naibrd_CAN_GetChannelCount().

Program Structure

Entry Point

The entry point is main() on most platforms, or CAN_Transmit() on VxWorks.

Application Flow

  1. Query for a channel number.

  2. Query for protocol (J1939 or CAN A/B) on supported modules.

  3. Configure the channel for the selected protocol.

  4. Query for baud rate timing.

  5. For J1939, query for PGN and claim addresses if applicable.

  6. Query for payload size.

  7. Configure the channel for transmission.

  8. Enter a transmit loop that sends frames on user command.

Channel Configuration and Transmission

The channel is configured for the selected protocol and baud rate:

naiapp_Cfg_Tx_CAN(cardIndex, module, channel, baudRate);

Each time the user presses Enter, the application generates data and transmits:

numOfFramesToTransmit = 1;
naiapp_generateData(channel, numOfFramesToTransmit, payload, isJ1939, fifoData);

fifoData[channel - 1].data[0].length = payload;
naiapp_transmitFIFOChannelData_PGN(cardIndex, module, channel, pgn, fifoData, numOfFramesToTransmit);
  • naiapp_generateData() fills the frame buffer with test data.

  • naiapp_transmitFIFOChannelData_PGN() loads the frame into the transmit FIFO and sends it.

For CAN A/B, the maximum payload is NAIBRD_CAN_AB_MAX_DATA_LEN (8 bytes). For J1939, the payload range is 8 to 345 bytes.

Troubleshooting Reference

Error / Symptom Possible Causes Suggested Resolution

Receiver does not see message

Cable not connected, baud rate mismatch, protocol mismatch

Verify CAN bus cabling. Ensure both endpoints use the same protocol and baud rate.

Module selection not recognized

Not a CAN module (CB1-CB3, CB6, CB8)

Verify the module type supports CAN.

J1939 address claim fails

No other J1939 nodes on the bus

J1939 address claiming requires at least one other node.

No board found or connection timeout

Board not powered, incorrect configuration file

Verify hardware is powered and connected.

Invalid payload size

Payload exceeds protocol maximum

For CAN A/B max is 8 bytes. For J1939 max is 345 bytes.

PGN not recognized by receiver

PGN value does not match receiver filter

Verify the PGN value matches what the receiver expects.

Full Source

The complete source for this sample is provided below for reference. The sections above explain each part in detail.

Full Source — can_xmit.c (SSK 2.x)
/**************************************************************************************************************/
/**
* <summary>
* This sample application lets you select a channel from a Gen5 CAN module and transmit on it.
*
* </summary>
*/
/**************************************************************************************************************/

/* nailib include files */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/nailib/include/nailib.h"
#include "nai_libs/nailib/include/nailib_utils.h"

/* naibrd include files */
#include "nai_libs/naibrd/include/naibrd.h"
#include "nai_libs/naibrd/include/functions/naibrd_can.h"
#include "nai_libs/naibrd/include/boards/naibrd_gen5.h"

/* naiif include files */
#include "nai_libs/naiif/include/naiif_stdio.h"

/* Common Sample Program include files */
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_menu.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_query.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_access.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_display.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_utils.h"

/* Common CAN Sample Program include files */
#include "nai_sample_apps/naiapp_src/board_modules/can/can_common_utils/can_common_utils.h"

/********************/
/* Application Name */
/********************/
static const int8_t *DEF_CONFIG_FILE = (int8_t *)"default_CANTx.txt";

/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t naiapp_Run_CAN_Transmit(int32_t cardIndex, int32_t module, uint32_t modId);

/**************************************************************************************************************/
/**
* <summary>
*
* The main routine assists in gaining access to the board.
*
* The following routines from the nai_sys_cfg.c file are
* called to assist with accessing and configuring the board.
*
* - ConfigDevice
* - DisplayDeviceCfg
* - GetBoardSNModCfg
* - CheckModule
*
* </summary>
*/
/*****************************************************************************/
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t CAN_Transmit(void)
#else
int32_t main(void)
#endif
{
   int32_t moduleCnt;
   bool_t stop = NAI_FALSE;
   int32_t channelCount, cardIndex, module;
   uint32_t modId;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;


   if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == (bool_t)NAI_TRUE)
   {
      while (stop != NAI_TRUE)
      {
         /* Select Card Index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != NAI_TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Select Module */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != NAI_TRUE)
            {
               check_status(naibrd_GetModuleName(cardIndex, module, &modId));

               channelCount = naibrd_CAN_GetChannelCount(modId);

               if ((channelCount != 0))
               {
                  naiapp_Run_CAN_Transmit(cardIndex, module, modId);
               }
               else
               {
                  naiif_printf(" *** Module selection not recognized as valid module type for this application. ***\r\n\r\n");
               }
            }

            naiif_printf("\r\nType Q to quit or Enter key to restart application:\r\n");
            stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         }
      }
   }

   naiif_printf("\r\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

   naiapp_access_CloseAllOpenCards();

   return 0;
}

/**************************************************************************************************************/
/**
* <summary>
* CAN_Transmit lets you generate or read data from a file and transmit it on a particular can channel.
*
* </summary>
*/
/**************************************************************************************************************/
static bool_t naiapp_Run_CAN_Transmit(int32_t cardIndex, int32_t module, uint32_t modId)
{
   int32_t numOfFramesToTransmit;
   bool_t bContinue;
   int32_t maxChannel;
   int32_t minChannel;
   int32_t payload = 0;
   uint32_t pgn = 0;
   int32_t channel;
   bool_t isJ1939 = NAI_TRUE;
   bool_t bQuit = NAI_FALSE;
   naibrd_can_baud_rate_type_t baudRate = NAIBRD_CAN_BAUD_UNASSIGNED;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   minChannel = 1;
   maxChannel = naibrd_CAN_GetChannelCount(modId);
   bQuit = naiapp_query_ChannelNumber(maxChannel, minChannel, &channel);

   if (!bQuit)
   {
      if (modId == NAIBRD_MODULE_ID_CB3 || modId == NAIBRD_MODULE_ID_CB6)
      {
         /* query for protocol - for J1939 capable modules only, otherwise no query will occur, and isJ1939 will be set to NAI_FALSE */
         bQuit = naiapp_QueryForChannelProtocol(modId, &isJ1939);
         if (isJ1939 && !bQuit)
         {
            memset(fifoData[channel - 1].data[0].dataJ1939, 0, sizeof(fifoData[channel - 1].data[0].dataJ1939));

            naiapp_setChannelToCANJ1939_R(cardIndex, module, modId, channel);
         }
         else if (!bQuit)
         {
            memset(fifoData[channel - 1].data[0].dataAB, 0, sizeof(fifoData[channel - 1].data[0].dataAB));

            naiapp_setChannelToCANAB_R(cardIndex, module, modId, channel);
         }
      }
      else if (modId == NAIBRD_MODULE_ID_CB2)
      {
         isJ1939 = NAI_TRUE;
      }
      else if (modId == NAIBRD_MODULE_ID_CB1)
      {
         isJ1939 = NAI_FALSE;
      }
   }
   if (!bQuit)
   {
      bQuit = naiapp_QueryUserForCANTiming(&baudRate, isJ1939);
   }

   if (naiapp_IsCAN_AB(cardIndex, module, channel))
   {
      fifoData[channel - 1].minLength = 0;
      fifoData[channel - 1].maxLength = NAIBRD_CAN_AB_MAX_DATA_LEN;
   }
   else if (naiapp_IsCAN_J1939(cardIndex, module, channel))
   {
      /*prompt user for pgn*/
      if (!bQuit)
         bQuit = naiapp_QueryForPGN(&pgn);

      fifoData[channel - 1].minLength = 8;
      fifoData[channel - 1].maxLength = 345;
   }

   naiif_printf("\r\n");
   if (!bQuit /*&& generateInput*/)
   {
      bQuit = naiapp_QueryForPayload(&payload, fifoData[channel - 1].minLength, fifoData[channel - 1].maxLength, isJ1939);
   }
   if (!bQuit)
   {
      bContinue = NAI_TRUE;
#if defined (NAIBRD_SSK_MODULE_ID_CB2) || defined (NAIBRD_SSK_MODULE_ID_CB3) || defined (NAIBRD_SSK_MODULE_ID_CB6)
      if (naiapp_IsCAN_J1939(cardIndex, module, channel))
      {
         naibrd_msDelay(250);
         naiif_printf("\r\n");
         naiapp_claimAddresses(cardIndex, module, channel);
      }
#endif
      /*Configure channel to transmit*/
      naiapp_Cfg_Tx_CAN(cardIndex, module, channel, baudRate);

      while (bContinue)
      {
         naiif_printf("\r\nPress Enter to Begin Transmission...Or Press Q to quit:\r\n");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            numOfFramesToTransmit = 1;
            naiapp_generateData(channel, numOfFramesToTransmit, payload, isJ1939, fifoData);

            fifoData[channel - 1].data[0].length = payload;
            naiapp_transmitFIFOChannelData_PGN(cardIndex, module, channel, pgn, fifoData, numOfFramesToTransmit);

            naiif_printf("fifo DATA Transmitted\r\n");
            naiif_printf("-----------------------");
            naiif_printf("\r\n");
            naiapp_printFIFOChannelData(channel, fifoData, isJ1939);
            naiif_printf("\r\n");
            naiif_printf("\r\n");
         }
         else
         {
            bContinue = NAI_FALSE;
         }
      }

   }

   return bQuit;
}

Help Bot

X