CAN Receive
Edit this on GitLab
CAN Receive
Explanation
About This Sample Application
This sample application showcases how to receive CAN messages on a range of channels using North Atlantic Industries' (NAI) Software Support Kit (SSK) and their embedded function modules. Below is an explanation of the provided code to guide you through its structure and functionality.
File Inclusions
The code starts with including essential headers for standard input/output operations and NAI-specific functionalities:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* Common CAN Sample Program include files */
#include "nai_can_cfg.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_can.h"
#include "naibrd_ether.h"
#include "advanced/nai_ether_adv.h"
Application Configurations
A static constant for the configuration file is declared:
static const int8_t *CONFIG_FILE = (int8_t *)"default_CANRx.txt";
Internal Function Prototypes
Here, the application declares prototypes for its internal functions:
static bool_t Run_CAN_Receive(void);
int32_t Run_CAN_Receive_Main(void);
Main Function
The main routine is responsible for initializing configurations, selecting modules and channels, and running the core CAN message retrieval loop. Under the hood, several helper functions manage the configuration and querying processes:
#if defined (__VXWORKS__)
int32_t Run_CAN_Receive_Main(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t moduleCnt;
int32_t channelCount;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
initializeCANConfigurations(0, 0, 0, 0, 0, 0, MAX_CAN_PAYLOAD_AB, 8, NAI_CAN_500K_BAUD);
if (naiapp_RunBoardMenu(CONFIG_FILE) == (bool_t)TRUE)
{
while (stop != TRUE)
{
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &inputCANConfig.cardIndex);
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(inputCANConfig.cardIndex, &moduleCnt));
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &inputCANConfig.module);
if (stop != TRUE)
{
inputCANConfig.modid = naibrd_GetModuleID(inputCANConfig.cardIndex, inputCANConfig.module);
channelCount = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
if ((channelCount != 0))
{
Run_CAN_Receive();
}
else
{
printf(" *** Module selection not recognized as valid module type for this application. ***\n\n");
}
}
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
}
printf("\nType the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
naiapp_access_CloseAllOpenCards();
return 0;
}
CAN Message Receiving Logic
The Run_CAN_Receive
function encapsulates the logic for receiving CAN messages. It sets up channels, queries user input, and processes the incoming data.
static bool_t Run_CAN_Receive(void)
{
FIFO* fifoData[NAI_GEN5_CAN_MAX_CHANNEL_COUNT];
bool_t bContinue;
int32_t maxChannel;
int32_t minChannel;
bool_t isJ1939 = TRUE;
bool_t bQuit = FALSE;
int32_t channel;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
minChannel = 1;
maxChannel = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
bQuit = naiapp_query_ForChannelRange(&inputCANConfig.minChannel ,&inputCANConfig.maxChannel, minChannel, maxChannel);
if(!bQuit)
{
if(inputCANConfig.modid == NAI_MODULE_ID_CB3)
{
bQuit = QueryForChannelProtocol(&isJ1939);
if(isJ1939 && !bQuit)
{
setChannelToCANJ1939_R(inputCANConfig.cardIndex,inputCANConfig.module,inputCANConfig.modid,inputCANConfig.minChannel, inputCANConfig.maxChannel);
}
else if(!bQuit)
{
setChannelToCANAB_R(inputCANConfig.cardIndex,inputCANConfig.module,inputCANConfig.modid,inputCANConfig.minChannel, inputCANConfig.maxChannel);
}
}
else if(inputCANConfig.modid == NAI_MODULE_ID_CB2)
isJ1939 = TRUE;
else if(inputCANConfig.modid == NAI_MODULE_ID_CB1)
isJ1939 = FALSE;
}
if(!bQuit)
{
bQuit = QueryUserForCANTiming(&inputCANConfig.baudRate,isJ1939);
}
if (!bQuit)
{
bContinue = TRUE;
Cfg_Rx_CAN(inputCANConfig);
if(IsCAN_J1939(inputCANConfig.cardIndex, inputCANConfig.module, inputCANConfig.minChannel))
{
printf("\n");
nai_msDelay(250);
claimAddresses(inputCANConfig.cardIndex,inputCANConfig.module, inputCANConfig.minChannel, inputCANConfig.maxChannel);
}
setTxEnable(inputCANConfig.cardIndex,inputCANConfig.module,inputCANConfig.minChannel , inputCANConfig.maxChannel ,TRUE);
for(channel = inputCANConfig.minChannel; channel <= inputCANConfig.maxChannel;channel++)
{
fifoData[channel - 1] = allocateSpaceForFIFO(1,1785);
}
while (bContinue)
{
printf("\nPress Enter to Read Channel Fifos...Or Press Q to quit:\n");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
getAllFIFOData(inputCANConfig.cardIndex,inputCANConfig.module,fifoData,inputCANConfig.minChannel,inputCANConfig.maxChannel);
printf("fifo DATA Received\n");
printf("-----------------------");
printf("\n");
printAllFIFOData(fifoData,stdout,inputCANConfig.minChannel,inputCANConfig.maxChannel);
printf("\n");
printf("\n");
}
else
{
bContinue = FALSE;
}
}
for(channel = inputCANConfig.minChannel; channel <= inputCANConfig.maxChannel;channel++)
{
deallocSpaceForFIFO(fifoData[channel -1]);
}
}
return bQuit;
}
Key Functions and Concepts
-
naiapp_RunBoardMenu(): This function initializes board configurations.
-
naiapp_query_CardIndex(): Prompts and retrieves the card index from the user.
-
naibrd_GetModuleCount(): Gets the number of modules available on the specified card.
-
naiapp_query_ModuleNumber(): Queries the user for the module number.
-
naibrd_CAN_GetChannelCount(): Retrieves the number of CAN channels for a given module.
-
Cfg_Rx_CAN(): Configures the CAN channel for reception.
-
getAllFIFOData(): Retrieves all FIFO data from the CAN channels.
Summary
This application is designed for receiving CAN messages across multiple channels by configuring the appropriate settings, querying necessary user input, and processing incoming data efficiently. The Run_CAN_Receive
function implements the core logic, facilitating message reception and data handling.
/**************************************************************************************************************/
/**
<summary>
This sample application lets you receive CAN messages on a range of channels.
</summary>
*/
/**************************************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
/* Common CAN Sample Program include files */
#include "nai_can_cfg.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_can.h"
#include "naibrd_ether.h"
#include "advanced/nai_ether_adv.h"
/**********************/
/* Application Name */
/**********************/
static const int8_t *CONFIG_FILE = (int8_t *)"default_CANRx.txt";
/********************************/
/* Internal Function Prototypes */
/********************************/
static bool_t Run_CAN_Receive(void);
int32_t Run_CAN_Receive_Main(void);
/**************************************************************************************************************/
/**
<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 (__VXWORKS__)
int32_t Run_CAN_Receive_Main(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int32_t moduleCnt;
int32_t channelCount;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
initializeCANConfigurations(0, 0, 0, 0, 0, 0, MAX_CAN_PAYLOAD_AB, 8, NAI_CAN_500K_BAUD);
if (naiapp_RunBoardMenu(CONFIG_FILE) == (bool_t)TRUE)
{
while (stop != TRUE)
{
/* Select Card Index */
stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &inputCANConfig.cardIndex);
if (stop != TRUE)
{
check_status(naibrd_GetModuleCount(inputCANConfig.cardIndex, &moduleCnt));
/* Select Module */
stop = naiapp_query_ModuleNumber(moduleCnt, 1, &inputCANConfig.module);
if (stop != TRUE)
{
inputCANConfig.modid = naibrd_GetModuleID(inputCANConfig.cardIndex, inputCANConfig.module);
channelCount = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
if ((channelCount != 0))
{
Run_CAN_Receive();
}
else
{
printf(" *** Module selection not recognized as valid module type for this application. ***\n\n");
}
}
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
}
}
printf("\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_Receive lets you receive CAN messages on a range of channels.
</summary>
*/
/**************************************************************************************************************/
static bool_t Run_CAN_Receive(void)
{
FIFO* fifoData[NAI_GEN5_CAN_MAX_CHANNEL_COUNT];
bool_t bContinue;
int32_t maxChannel;
int32_t minChannel;
bool_t isJ1939 = TRUE;
bool_t bQuit = FALSE;
int32_t channel;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
minChannel = 1;
maxChannel = naibrd_CAN_GetChannelCount(inputCANConfig.modid);
bQuit = naiapp_query_ForChannelRange(&inputCANConfig.minChannel ,&inputCANConfig.maxChannel, minChannel, maxChannel);
if(!bQuit)
{
if( inputCANConfig.modid == NAI_MODULE_ID_CB3 )
{
bQuit = QueryForChannelProtocol(&isJ1939);
if(isJ1939 && !bQuit)
{
setChannelToCANJ1939_R(inputCANConfig.cardIndex,inputCANConfig.module,inputCANConfig.modid,inputCANConfig.minChannel, inputCANConfig.maxChannel);
}
else if(!bQuit)
{
setChannelToCANAB_R(inputCANConfig.cardIndex,inputCANConfig.module,inputCANConfig.modid,inputCANConfig.minChannel, inputCANConfig.maxChannel);
}
}
else if(inputCANConfig.modid == NAI_MODULE_ID_CB2)
isJ1939 = TRUE;
else if(inputCANConfig.modid == NAI_MODULE_ID_CB1)
isJ1939 = FALSE;
}
if(!bQuit)
{
bQuit = QueryUserForCANTiming(&inputCANConfig.baudRate,isJ1939);
}
if (!bQuit)
{
bContinue = TRUE;
/* Configure channel to Rx */
Cfg_Rx_CAN(inputCANConfig);
if(IsCAN_J1939(inputCANConfig.cardIndex, inputCANConfig.module, inputCANConfig.minChannel))
{
printf("\n");
nai_msDelay(250);
claimAddresses(inputCANConfig.cardIndex,inputCANConfig.module, inputCANConfig.minChannel, inputCANConfig.maxChannel);
}
/* Configure channel to Tx (Needed by other devices wishing to claim addresses) */
setTxEnable(inputCANConfig.cardIndex,inputCANConfig.module,inputCANConfig.minChannel , inputCANConfig.maxChannel ,TRUE);
/* allocate buffer to hold fifo data received */
for(channel = inputCANConfig.minChannel; channel <= inputCANConfig.maxChannel;channel++)
{
fifoData[channel - 1] = allocateSpaceForFIFO(1,1785);
}
while (bContinue)
{
printf("\nPress Enter to Read Channel Fifos...Or Press Q to quit:\n");
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
getAllFIFOData(inputCANConfig.cardIndex,inputCANConfig.module,fifoData,inputCANConfig.minChannel,inputCANConfig.maxChannel);
printf("fifo DATA Received\n");
printf("-----------------------");
printf("\n");
printAllFIFOData(fifoData,stdout,inputCANConfig.minChannel,inputCANConfig.maxChannel);
printf("\n");
printf("\n");
}
else
{
bContinue = FALSE;
}
}
for(channel = inputCANConfig.minChannel; channel <= inputCANConfig.maxChannel;channel++)
{
deallocSpaceForFIFO(fifoData[channel -1]);
}
}
return bQuit;
}