AR CAN Transmit
Edit this on GitLab
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.
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().
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 |
|---|---|---|
|
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. |
|
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);
}
}