| Products & Services | Solutions | Academia | Support | User Community | Company |
| Download Product Updates | | | Get Pricing | | | Trial Software |
| Documentation → xPC Target |
| Contents | Index |
| Learn more about xPC Target |
| On this page… |
|---|
Building the xPC Target Application Creating a Visual C Application Building a Visual C Application Running a Visual C xPC Target API Application |
This release includes an example using the xPC Target API to create a Win32 console application written in C. You can use this example as a template to write your own application.
Before you start, you should have an existing xPC Target application that you want to load and run on a target PC. The following tutorials use the target application sf_car_xpc.dlm, built from the Simulink model sf_car_xpc.mdl, which models an automatic transmission control system. The automatic transmission control system consists of modules that represent the engine, transmission, and vehicle, with an additional logic block to control the transmission ratio. User inputs to the model are in the form of throttle (%) and brake torque (pound-foot). You can control the target application through MATLAB with the Simulink External Model interface, or through a custom xPC Target API application, which you can create using the tutorials in this chapter.
This directory contains the C source of a Win32 console application that serves as an example for using the xPC Target API. The necessary sf_car_xpc files are in the directory
C:\matlabroot\toolbox\rtw\targets\xpc\api
Filename | Description |
|---|---|
VisualBasic\Models\sf_car_xpc\sf_car_xpc.mdl | Simulink model for use with xPC Target |
VisualBasic\Models\sf_car_xpc\sf_car_xpc.dlm | Target application compiled from Simulink model |
VisualC\sf_car_xpc.dsp | Project file for API application |
sf_car_xpc.c | Source code for API application |
VisualC\sf_car_xpc.exe | Compiled API application |
VisualBasic\Models\xpcapi.dll | xPC Target API functions for all programming languages. Place this file in one of the following, in order of preference:
|
The necessary xPC Target API files are in the directory
C:\matlabroot\toolbox\rtw\targets\xpc\api
You will need the files listed below for creating your own API application with Microsoft Visual C++.
Filename | Description |
|---|---|
xpcapi.h | Mapping of data types between xPC Target API and Visual C |
xpcapiconst.h | Symbolic constants for using scope, communication, and data-logging functions |
xpcinitfree.c | C functions to upload API from xpcapi.dll |
xpcapi.dll | xPC Target API functions for all programming languages |
The tutorials in this chapter use the prebuilt xPC Target application
C:\matlabroot\toolbox\rtw\targets\ xpc\api\VisualC\sf_car_xpc.dlm
You can rebuild this application for your example:
Create a new directory under your MathWorks directory. For example,
D:\mwd\sf_car_xpc2
Create a Simulink model and save to this directory. For example,
sf_car_xpc2.mdl
Build the target application with Real-Time Workshop® and Microsoft Visual C++. The target application file sf_car_xpc2.dlm is created.
The tutorials in this chapter describe how to create and build C applications using Microsoft Visual C++. However, to build an xPC Target API C application, you can use any C/C++ compiler capable of generating a Win32 application. You will need to link and compile the xPC Target API application along with xpcinitfree.c to generate the executable. The file xpcinitfree.c contains the definitions for the files in the xPC Target API and is located at
C:\matlabroot\toolbox\rtw\targets\xpc\api
This tutorial describes how to create a Visual C application. It is assumed that you know how to write C applications. Of particular note when writing xPC Target API applications,
Call the function xPCInitAPI at the start of the application to load the functions.
Call the function xPCFreeAPI at the end of the application to free the memory allocated to the functions.
To create a C application with a program such as Microsoft Visual C++,
From the previous tutorial, change directory to the new directory. This is your working directory. For example,
D:\mwd\sf_car_xpc2
Copy the files xpcapi.h, xpcapi.dll, xpcapiconst.h, and xpcintfree.c to the working directory. For example,
D:\mwd\sf_car_xpc2
Click the Start button, choose the Programs option, and choose the Microsoft Visual C++ entry. Select the Microsoft Visual C++ option.
The Microsoft Visual C++ application is displayed.
At the New dialog, click the File tab.

In the left pane, select C++ Source File. In the right, enter the name of the file. For example, sf_car_xpc.c. Select the directory. For example, C:\mwd\sf_car_xpc2.
Enter your code in this file. For example, you can enter the contents of sf_xpc_car.c into this file.
At the New dialog, click the Projects tab.

In the left pane, select Win32 Console Application. On the right, enter the name of the project. For example, sf_car_xpc. Select the working directory from step 1. For example, C:\mwd\sf_car_xpc2.
To create the project, click OK.
A Win32 Console Application dialog is displayed.
To confirm the creation of an empty project, click OK at the following dialog.
To add the C file you created in step 7, from the Project menu, select the Add to Project option and select Files.
Browse for the C file you created in step 7. For example,
D:\mwd\sf_car_xpc2\sf_car_xpc.c
Click OK.
Browse for the xpcinitfree.c file. For example, D:\mwd\xpcinitfree.c. Click OK.
If you did not copy the files xpcapi.h, xpcapi.dll, and xpcapiconst.h into the working or project directory, you should either copy them now, or also add these files to the project.
When you are ready to build your C application, go to Building a Visual C Application.
The sf_car_xpc.c file assumes that the xPC Target application file sf_car_xpc.dlm is in the same directory as sf_car_xpc.c. If you move that target application file (sf_car_xpc.dlm) to a new location, change the path to this file in the API application (sf_car_xpc.c) and recompile the API application. The relevant line in sf_car_xpc.c is in the function main(), and looks like this:
xPCLoadApp(port, ".", "sf_car_xpc"); checkError("LoadApp: ");The second argument (".") in the call to xPCLoadApp is the path to sf_car_xpc.dlm. The "." indicates that the files sf_car_xpc.dlm and sf_car_xpc.c are in the same directory. If you move the target application, enter its new path and rebuild the xPC Target API application.
This tutorial describes how to build the Visual C application from the previous tutorial, or to rebuild the example executable sf_car_xpc.exe, with Microsoft Visual C++:
To build your own application using the xPC Target API, ensure that the files xpcapi.h, xpcapi.dll, xpcapiconst.h, and xpcinitfree.c are in the working or project directory.
If Microsoft Visual C++ is not already running, click the Start button, choose the Programs option, and choose the Microsoft Visual C++ entry. Select the Microsoft Visual C++ option.
From the File menu, click Open.
The Open dialog is displayed.
Use the browser to select the project file for the application you want to build. For example, sf_car_xpc.dsp.
If a corresponding workspace file (for example, sf_car_xpc.dsw) exists for that project, a dialog prompts you to open that workspace instead. Click OK.
Build the application for the project. From the Build menu, select either the Build project_name.exe or Rebuild All option.
Microsoft Visual C++ creates a file named project_name.exe, where project_name is the name of the project.
When you are ready to run your Visual C Application, go to Running a Visual C xPC Target API Application.
Before starting the API application sf_car_xpc.exe, ensure the following:
The file xpcapi.dll must either be in the same directory as the xPC Target API application executable, or it must be in the Windows system directory (typically C:\windows\system or C:\winnt\system32) for global access. The xPC Target API application depends on this file, and will not run if the file is not found. The same is true for other applications you write using xPC Target API functions.
The compiled target application sf_car_xpc.dlm must be in the same directory as the xPC Target API executable. Do not move this file out of this directory. Moving the file requires you to change the path to the target application in the API application and recompile, as described in Building a Visual C Application.
Any xPC Target API application requires you to have a working target PC running at least xPC Target Version 2.0 (Release 13).
This tutorial assumes that you are using the xPC Target API application sf_car_xpc.exe that comes with xPC Target. In turn, sf_car_xpc.exe expects that the xPC Target application is sf_car_xpc.dlm.
If you are going to run a version of sf_car_xpc.exe that you compiled yourself using the sf_car_xpc.c code that comes with xPC Target, you can run that application instead. Ensure that the following files are in the same directory:
sf_car_xpc.exe, the xPC Target API executable
sf_car_xpc.dlm, the xPC Target application to be loaded to the target PC
xpcapi.dll, the xPC Target API dynamic link library
If you copy this file to the Windows system directory, you do not need to provide this file in the same directory.
Create an xPC Target boot disk with a serial or network communication. If you use serial communications, set the baud rate to 115200. Otherwise, create the boot disk as directed in xPC Target Getting Started.
Start the target PC with the xPC Target boot disk.
The target PC displays messages like the following in the top rightmost message area.
System: Host-Target Interface is RS232 (COM1/2)
or
System: Host-Target Interface is TCP/IP (Ethernet)
If you have downloaded target applications to the target PC through MATLAB, in the MATLAB window, type
close(xpc)
This command disconnects MATLAB from the target PC and leaves the target PC ready to connect to another client.
On the host PC, open a DOS window. Change directory to
C:\matlabroot\toolbox\rtw\targets\xpc\api\VisualC
If you are running your own version of sf_car_xpc.exe, change to the directory that contains the executable and xPC Target application. For example,
D:\mwd\sf_car_xpc2
From that DOS window, enter the command to start the demo application on the host PC and download the target application to the target PC.
The syntax for the demo command is
sf_car_xpc {-t IpAddress:IpPort|-c COMport}If you set up the xPC Target boot disk to use TCP/IP, then give the target PC's IP address and IP port as arguments to sf_car_xpc, along with the option -t. For example, at the DOS prompt, type
sf_car_xpc -t 192.168.0.1:22222
If you set up the xPC Target boot disk to use RS-232, give the serial port number as a command-line option. Note that indexing of serial ports starts from 0 instead of 1. For example, if you are using serial communication from COM port 1 on the host PC, type
sf_car_xpc -c 0
On the host PC, the demo application displays the following message:
*-------------------------------------------------------------* * xPC Target API Demo: sf_car_xpc. * * * * Copyright (c) 2000 The MathWorks, Inc. All Rights Reserved. * *-------------------------------------------------------------* Application sf_car_xpc loaded. SampleTime 0.001 StopTime: -1 R Br Th G VehSpeed VehRPM - ---- -- - ---------- --------- N 0 0 0 0.000 1000.000
The relevant line here is the last one, which displays the status of the application. The headings are as follows:
R | The status of the target application: R if running, N if stopped |
Br | The brake torque; legal values range from 0 to 4000 |
Th | The throttle as a percentage (0 - 100) of the total |
G | Gear the vehicle is in (ranges between 1 and 4) |
VehSpeed | Speed of the vehicle in miles per hour |
VehRPM | Revolutions per minute of the vehicle engine (0 to 6000) |
From this screen, various keystrokes control the target application. The following list summarizes these keys:
Key | Action |
|---|---|
s | Start or stop the application, as appropriate. |
T | Increase the throttle by 1 (does not go above 100). |
t | Decrease the throttle by 1 (does not go below 0). |
B | Increase the brake value by 20 (does not go above 4000). Note that a positive value for the brake automatically sets the throttle value to 0, and a positive value for the throttle automatically sets the brake value to 0. |
b | Decrease the brake value by 20 (does not go below 0). |
Q or Ctrl+C | Quit the application. |
The target PC displays the following messages and three scopes.

Hold down the Shift key and hold down T until the value of Th reaches 100.
Press s to start the application.

The first scope (SC1) shows the throttle rising to a maximum value of 100 and the vehicle speed gradually increasing. The third scope (SC3) shows the vehicle RPM. Notice the changes in the vehicle RPM as the gears shift from first to fourth gear as displayed in the third numerical scope (SC2).
When you are done testing the demo application, type Q or Ctrl+C.
The demo application is disconnected from the target PC, so you can reconnect to MATLAB.
This section contains the C code for the sf_car_xpc.c application:
/* File: sf_car_xpc.c
* Abstract: Demonstrates the use of the xPC Target C-API in Human-Machine
* interaction. This file generates a Win32 Console application,
* which when invoked loads the sf_car_xpc.dlm compiled application
* on to the xPC Target PC.
*
* To build the executable, use the Visual C/C++ project
* sf_car_xpc.dsp.
*
* Copyright 2000-2004 The MathWorks, Inc.
*/
/* Standard include files */
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <conio.h>
#include <windows.h>
/* xPC Target C-API specific includes */
#include "xpcapi.h"
#include "xpcapiconst.h"
#define SERIAL 0
#define TCPIP 1
/* max and min are defined by some compilers, so we wrap them in #ifndef's */
#ifndef max
#define max(a, b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef min
#define min(a, b) (((a) < (b)) ? (a) : (b))
#endif
/* Global Variables */
int mode = TCPIP, comPort = 0;
int port;
int thrPID, brakePID, rpmSID, speedSID, gearSID;
char *ipAddress, *ipPort, *pathToApp = NULL;
/* Function prototypes */
double getParam(int parIdx);
void setParam(int parIdx, double parValue);
void findParam(char *block, char *param, int *id);
void findSignal(char *sig, int *id);
void Usage(void);
void cleanUp(void);
void checkError(char *str);
void processKeys(void);
void parseArgs(int argc, char *argv[]);
int str2Int(char *str);
/* Function: main ============================================================
* Abstract: Main function for the sf_car_xpc demo */
int main(int argc, char *argv[]) {
printf("\n"
"*-------------------------------------------------------------*\n"
"* xPC Target API Demo: sf_car_xpc. *\n"
"* *\n"
"* Copyright (c) 2000 The MathWorks, Inc. All Rights Reserved. *\n"
"*-------------------------------------------------------------*\n"
"\n");
parseArgs(argc, argv);
atexit(cleanUp);
/* Initialize the API */
if (xPCInitAPI()) {
fprintf(stderr, "Could not load api\n");
return -1;
}
if (mode == SERIAL)
port = xPCOpenSerialPort(comPort, 0);
else if (mode == TCPIP)
port = xPCOpenTcpIpPort(ipAddress, ipPort);
else {
fprintf(stderr, "Invalid communication mode\n");
exit(EXIT_FAILURE);
}
checkError("PortOpen: ");
xPCLoadApp(port, ".", "sf_car_xpc"); checkError("LoadApp: ");
printf("Application sf_car_xpc loaded, SampleTime: %g StopTime: %g\n\n",
xPCGetSampleTime(port), xPCGetStopTime(port));
checkError(NULL);
findParam("Throttle", "Value", &thrPID);
findParam("Brake", "Value", &brakePID);
findSignal("Engine/rpm", &rpmSID);
findSignal("Vehicle/mph", &speedSID);
findSignal("shift_logic/p1", &gearSID);
processKeys(); /* Heart of the application */
if (xPCIsAppRunning(port)) {
xPCStopApp(port);
}
return 0;
} /* end main() */
/* Function: processKeys =====================================================
* Abstract: This function reads and processes the keystrokes typed by the
* user and takes action based on them. This function runs for most
* of the program life. */
void processKeys(void) {
int c = 0;
double throttle, brake;
throttle = getParam(thrPID);
brake = getParam(brakePID);
fputs("\nR Br Th G VehSpeed VehRPM \n", stdout);
fputs( "- ---- -- - ---------- -------- \n", stdout);
while (1) {
if (_kbhit()) {
c = _getch();
switch (c) {
case 't':
if (throttle)
setParam(thrPID, --throttle);
break;
case 'T':
if (brake)
setParam(brakePID, (brake = 0));
if (throttle < 100)
setParam(thrPID, ++throttle);
break;
case 'b':
setParam(brakePID, (brake = max(brake - 200, 0)));
if (brake)
setParam(thrPID, (throttle = 0));
break;
case 'B':
if (throttle)
setParam(thrPID, (throttle = 0));
setParam(brakePID, (brake = min(brake + 200, 4000)));
break;
case 's':
case 'S':
if (xPCIsAppRunning(port)) {
xPCStopApp(port); checkError(NULL);
} else {
xPCStartApp(port); checkError(NULL);
}
break;
case 'q':
case 'Q':
return;
break;
default:
fputc(7, stderr);
break;
}
} else {
Sleep(50);
}
printf( "\r%c %4d %3d %1d %10.3f %10.3f",
(xPCIsAppRunning(port) ? 'Y' : 'N'),
(int)brake, (int)throttle,
(int)xPCGetSignal(port, gearSID),
xPCGetSignal(port, speedSID),
xPCGetSignal(port, rpmSID));
}
} /* end processKeys() */
/* Function: Usage ===========================================================
* Abstract: Prints a simple usage message. */
void Usage(void) {
fprintf(stdout,
"Usage: sf_car_xpc {-t IPAddress:IpPort|-c num}\n\n"
"E.g.: sf_car_xpc -t 192.168.0.1:22222\n"
"E.g.: sf_car_xpc -c 1\n\n");
return;
} /* end Usage() */
/* Function: str2Int =========================================================
* Abstract: Converts the supplied string str to an integer. Returns INT_MIN
* if the string is invalid as an integer (e.g. "123string" is
* invalid) or if the string is empty. */
int str2Int(char *str) {
char *tmp;
int tmpInt;
tmpInt = (int)strtol(str, &tmp, 10);
if (*str == '\0' || (*tmp != '\0')) {
return INT_MIN;
}
return tmpInt;
} /* end str2Int */
/* Function: parseArgs =======================================================
* Abstract: Parses the command line arguments and sets the state of variables
* based on the arguments. */
void parseArgs(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "Insufficient command line arguments.\n\n");
Usage();
exit(EXIT_FAILURE);
}
if (strlen(argv[1]) != 2 ||
strchr("-/", argv[1][0]) == NULL ||
strchr("tTcC", argv[1][1]) == NULL) {
fprintf(stderr, "Unrecognized Argument %s\n\n", argv[1]);
Usage();
exit(EXIT_FAILURE);
}
mode = tolower(argv[1][1]) == 'c' ? SERIAL : TCPIP;
if (mode == SERIAL) {
int tmpInt;
if ((tmpInt = str2Int(argv[2])) > INT_MIN) {
comPort = tmpInt;
} else {
fprintf(stderr, "Unrecognized argument %s\n", argv[2]);
Usage();
}
} else {
char *tmp;
ipAddress = argv[2];
if ((tmp = strchr(argv[2], ':')) == NULL) {
/* memory need not be freed as it is allocated only once, will *
* hang around till app ends. */
if ((ipPort = malloc(6 * sizeof(char))) == NULL) {
fprintf(stderr, "Unable to allocate memory");
exit(EXIT_FAILURE);
}
strcpy(ipPort, "22222");
} else {
*tmp = '\0';
ipPort = ++tmp;
}
}
return;
} /* end parseArgs() */
/* Function: cleanUp =========================================================
* Abstract: Called at program termination to exit in a clean way. */
void cleanUp(void) {
xPCClosePort(port);
xPCFreeAPI();
return;
} /* end cleanUp() */
/* Function: checkError ======================================================
* Abstract: Checks for error by calling xPCGetLastError(); if an error is
* found, prints the appropriate error message and exits. */
void checkError(char *str) {
char errMsg[80];
if (xPCGetLastError()) {
if (str != NULL)
fputs(str, stderr);
xPCErrorMsg(xPCGetLastError(), errMsg);
fputs(errMsg, stderr);
exit(EXIT_FAILURE);
}
return;
} /* end checkError() */
/* Function: findParam =======================================================
* Abstract: Wrapper function around the xPCGetParamIdx() API call. Also
* checks to see if the parameter is not found, and exits in that
* case. */
void findParam(char *block, char *param, int *id) {
int tmp;
tmp = xPCGetParamIdx(port, block, param);
if (xPCGetLastError() || tmp == -1) {
fprintf(stderr, "Param %s/%s not found\n", block, param);
exit(EXIT_FAILURE);
}
*id = tmp;
return;
} /* end findParam() */
/* Function: findSignal ======================================================
* Abstract: Wrapper function around the xPCGetSignalIdx() API call. Also
* checks to see if the signal is not found, and exits in that
* case. */
void findSignal(char *sig, int *id) {
int tmp;
tmp = xPCGetSignalIdx(port, sig);
if (xPCGetLastError() || tmp == -1) {
fprintf(stderr, "Signal %s not found\n", sig);
exit(EXIT_FAILURE);
}
*id = tmp;
return;
} /* end findSignal() */
/* Function: getParam ========================================================
* Abstract: Wrapper function around the xPCGetParam() API call. Also checks
* for error, and exits if an error is found. */
double getParam(int parIdx) {
double p;
xPCGetParam(port, parIdx, &p);
checkError("GetParam: ");
return p;
} /* end getParam() */
/* Function: setParam ========================================================
* Abstract: Wrapper function around the xPCSetParam() API call. Also checks
* for error, and exits if an error is found. */
void setParam(int parIdx, double parValue) {
xPCSetParam(port, parIdx, &parValue);
checkError("SetParam: ");
return;
} /* end setParam() */
/** EOF sf_car_xpc.c **/
![]() | Before You Start | xPC Target COM API | ![]() |

Learn more about Simulink through this collection of videos, articles, technical literature and the Getting Started with Simulink Guide.
| © 1984-2009- The MathWorks, Inc. - Site Help - Patents - Trademarks - Privacy Policy - Preventing Piracy - RSS |