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

AR CAN Transmit

AR CAN Transmit Sample Application (SSK 2.x)

Overview

The AR CAN Transmit sample application demonstrates how to transmit CAN messages on a specific channel of an AR CAN module using the NAI Software Support Kit (SSK 2.x). The application supports both standard CAN (A/B) and CAN FD protocols. It queries the user for the channel, protocol type, mode (Mode A with 11-bit identifiers or Mode B with 29-bit identifiers for CAN FD), baud rate, and message ID, then generates a payload and transmits a single CAN message.

This sample supports AR CAN module types. It is designed to work with the AR CAN Recv sample application for receive testing.

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with an AR CAN module installed.

  • 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 ar_can_transmit executable from your build output directory. On startup the application looks for a configuration file (default_AR_CANTransmit.txt). Once connected, the application queries for all transmit parameters and sends a CAN message.

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_AR_CAN_GetChannelCount().

Program Structure

Entry Point

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

Application Flow

  1. Query for a channel number.

  2. Query for protocol (CAN A/B or CAN FD).

  3. If CAN FD, query for Mode A (11-bit) or Mode B (29-bit).

  4. Query for baud rate and data rate.

  5. Set the baud rate on the selected channel.

  6. Query for a message ID.

  7. Generate payload data and transmit.

Message Transmission

The application uses a two-step transmit process: queue the message, then enable TX:

status = naibrd_AR_CAN_QueueTransmit(cardIndex, module, channel, protocol,
    isModeA, msgId, buffer, length);

if (NAI_SUCCESS == status)
{
    status = naibrd_AR_CAN_SetTxEnable(cardIndex, module, channel, NAI_TRUE);
}
  • naibrd_AR_CAN_QueueTransmit() loads the message into the transmit queue with the specified protocol, mode, message ID, and payload.

  • naibrd_AR_CAN_SetTxEnable() enables the transmitter so the queued message is sent.

The payload is generated with incremental byte values:

static void fillMessageBuffer(uint8_t* buffer, int32_t bufferLength)
{
    uint32_t i;
    for (i = 0; i < (uint32_t)bufferLength; i++)
    {
        buffer[i] = (i & 0xFF);
    }
}

For CAN A/B, the payload is STANDARD_CAN_MAX_PAYLOAD bytes (8). For CAN FD, it is CAN_FD_MAX_PAYLOAD bytes (64).

Troubleshooting Reference

Error / Symptom Possible Causes Suggested Resolution

naibrd_AR_CAN_QueueTransmit error

Invalid protocol, mode, or message ID

Verify protocol and mode settings. Check that the message ID is within the valid range for the selected mode.

naibrd_AR_CAN_SetTxEnable error

Channel not properly configured

Verify baud rate configuration and channel selection.

Module selection not recognized

Not an AR CAN module

Verify the module type supports AR CAN.

Receiver does not see message

Cable not connected, baud rate mismatch, protocol mismatch

Verify cabling and ensure both endpoints use the same protocol, mode, and baud rate.

No board found or connection timeout

Board not powered, incorrect configuration file

Verify hardware is powered and connected.

Full Source

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

Full Source — ar_can_transmit.c (SSK 2.x)
/* 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_ar_can.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_utils.h"

/* Common ARCAN Sample Program include files */
#include "../../ar_can_common_utils/ar_can_common_utils.h"

static const int8_t* DEF_CONFIG_FILE = (int8_t*)"default_AR_CANTransmit.txt";

/* Internal Function prototypes */
static void Run_ARCAN_Transmit(int32_t cardIndex, int32_t module, uint32_t modId);
static void transmit_Message(int32_t cardIndex, int32_t module, int32_t channel,
    naibrd_ar_can_protocol_type_t protocol, bool_t isModeA, uint32_t msgId, uint8_t* buffer, int32_t length);
static void fillMessageBuffer(uint8_t* buffer, int32_t bufferLength);

/**************************************************************************************************************/
/**
* <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 AR_CAN_Transmit(void)
#else
int32_t main(void)
#endif
{
    bool_t stop = NAI_FALSE;
    int32_t cardIndex;
    int32_t moduleCnt;
    int32_t moduleNumber;
    int8_t inputBuffer[80];
    int32_t inputResponseCnt;
    uint32_t modId;
    int32_t channelCount;

    if (naiapp_RunBoardMenu(DEF_CONFIG_FILE) == NAI_TRUE)
    {
        while (stop != NAI_TRUE)
        {
            /* Query the user for the card index */
            stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);

            if (stop != NAI_TRUE)
            {
                check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

                /* Query the user for the module number */
                stop = naiapp_query_ModuleNumber(moduleCnt, 1, &moduleNumber);
                if (stop != NAI_TRUE)
                {
                    check_status(naibrd_GetModuleName(cardIndex, moduleNumber, &modId));

                    channelCount = naibrd_AR_CAN_GetChannelCount(modId);

                    if (channelCount != 0)
                    {
                        Run_ARCAN_Transmit(cardIndex, moduleNumber, 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>
* AR_CAN transmit lets you configure and transmit data on a specific channel
*
* </summary>
*/
/**************************************************************************************************************/
static void Run_ARCAN_Transmit(int32_t cardIndex, int32_t module, uint32_t modId)
{
    int32_t minChannel = 0u;
    int32_t maxChannel = 0u;
    bool_t bQuit = NAI_FALSE;
    int32_t channel = 0u;
    naibrd_ar_can_protocol_type_t protocol = NAIBRD_AR_CAN_PROTOCOL_FD;
    bool_t isModeA = NAI_TRUE;
    uint32_t msgId = 0x00;
    int32_t baudBaseRate = 0u;
    int32_t baudDataRate = 0u;

    minChannel = 1;
    maxChannel = naibrd_AR_CAN_GetChannelCount(modId);

    bQuit = naiapp_query_ChannelNumber(maxChannel, minChannel, &channel);

    if (!bQuit)
    {
        /*Query the user for protocol*/
        bQuit = naiapp_query_ARCAN_Protocol(&protocol);

        if (!bQuit)
        {
            /*Default is Mode A, the FD protocol lets user choose between Mode A (11 bits) or Mode B (29 bits) for messsage identifier length*/
            if (protocol == NAIBRD_AR_CAN_PROTOCOL_FD)
            {
                /*Query user for mode A or B*/
                bQuit = naiapp_query_ARCAN_isModeA(&isModeA);
            }
        }
    }

    if (!bQuit)
    {
        /* Query user for baud rate and data rate */
        bQuit = naiapp_query_ARCAN_BaudRate(&baudBaseRate, &baudDataRate);

        if (!bQuit)
        {
            /* Set baud rate and data rate */
            check_status(naibrd_AR_CAN_SetBaudRate(cardIndex, module, channel,
                (naibrd_ar_can_low_rate_type_t)baudBaseRate, (naibrd_ar_can_high_rate_type_t)baudDataRate));
        }
    }

    if (!bQuit)
    {
        bQuit = naiapp_query_ARCAN_msgId(&msgId, isModeA);
    }

    if (!bQuit)
    {
        if (protocol == NAIBRD_AR_CAN_PROTOCOL_AB)
        {
            /* Generate payload data */
            uint8_t u8Buffer[STANDARD_CAN_MAX_PAYLOAD];
            fillMessageBuffer(&u8Buffer[0], STANDARD_CAN_MAX_PAYLOAD);

            transmit_Message(cardIndex, module, channel, protocol, isModeA, msgId, &u8Buffer[0], STANDARD_CAN_MAX_PAYLOAD);
        }
        else if (protocol == NAIBRD_AR_CAN_PROTOCOL_FD)
        {
            /* Generate payload data */
            uint8_t u8Buffer[CAN_FD_MAX_PAYLOAD];
            fillMessageBuffer(&u8Buffer[0], CAN_FD_MAX_PAYLOAD);

            transmit_Message(cardIndex, module, channel, protocol, isModeA, msgId, &u8Buffer[0], CAN_FD_MAX_PAYLOAD);
        }
    }
}

static void transmit_Message(int32_t cardIndex, int32_t module, int32_t channel,
    naibrd_ar_can_protocol_type_t protocol, bool_t isModeA, uint32_t msgId, uint8_t* buffer, int32_t length)
{
    nai_status_t status;
    uint32_t i;

    /* Load message into transmit queue */
    status = naibrd_AR_CAN_QueueTransmit(cardIndex, module, channel, protocol,
        isModeA, msgId, buffer, length);

    if (NAI_SUCCESS == status)
    {
        /* Now set the TX Enable so the message gets transmitted */
        status = naibrd_AR_CAN_SetTxEnable(cardIndex, module, channel, NAI_TRUE);

        if (NAI_SUCCESS == status)
        {
            naiif_printf("\r\nCAN Message sent for chan: %d\r\n", channel);
            naiif_printf("Protocol: %s\r\n", (protocol == NAIBRD_AR_CAN_PROTOCOL_FD) ? "CAN FD" : "CAN AB");
            naiif_printf("Extended: %s\r\n", (isModeA) ? "no" : "yes");
            naiif_printf("MsgId = 0x%x\r\n", msgId);
            naiif_printf("\r\n------------ Payload ------------\r\n");
            naiif_printf("\r\n");
            for (i = 0; i < (uint32_t)length; i++)
            {
                naiif_printf("   Payload[%d] = 0x%x\r\n", i, buffer[i]);
            }
        }
        else
        {
            naiif_printf("ERROR: naibrd_AR_CAN_SetTxEnable returned status: %d\r\n", status);
        }
    }
    else /* naibrd_AR_CAN_QueueTransmit error detected */
    {
        naiif_printf("ERROR: naibrd_AR_CAN_QueueTransmit returned status: %d\r\n", status);
    }
}

static void fillMessageBuffer(uint8_t* buffer, int32_t bufferLength)
{
    uint32_t i;
    for (i = 0; i < (uint32_t)bufferLength; i++)
    {
        buffer[i] = (i & 0xFF);
    }
}

Help Bot

X