📄 rtsscom.c
字号:
/*****************************************************************************
*** RTSSCOM.c -- source file (RTSS to Win32 Communication function calls) ***
******************************************************************************
**** ****
**** Source file containing functions that allow the RTSS process ****
**** to communicate with a Win32 application ****
**** ****
**** Last revision date: 1/4/99 ****
**** Programmer: Dan Block ****
**** ****
*****************************************************************************/
#include <windows.h>
#include <stdio.h>
#include <rtapi.h>
#include "cslrtx.h"
#include "rtsscom.h"
// global variables using by the following functions
HANDLE g_hMutex,g_hShm,g_hSemPostC;
HANDLE g_hSemPostCAck,g_hSemDRdy,g_hSemDRdyAck,g_hSemRecv;
HANDLE g_hEvent,g_hSemAckEvent;
PSHRMEM g_pshrcommand;
int g_EventCommand;
int g_SendEvent = 0;
long int g_mod_count,g_data_count,g_once_through;
float g_data[8][NUM_POINTS];
/*****************************************************************************
**** InitRTSS_Communication -- Sets up the communicatoin objects needed **
**** to communicate with a Win32 application **
*****************************************************************************/
int InitRTSS_Communication(void) {
// Open Shared Memory
g_hShm = RtOpenSharedMemory( PAGE_READWRITE, FALSE, COECSL_SHM1, (LPVOID) &g_pshrcommand);
if (g_hShm==0)
{
RtCloseHandle( g_hShm);
printf("ERROR: Could not Open SharedMemory\n");
return 1;
}
// Open Mutex
g_hMutex = RtOpenMutex( SYNCHRONIZE, FALSE, COECSL_MUTEX);
if (g_hMutex==0) {
RtCloseHandle( g_hShm);
RtCloseHandle(g_hMutex);
printf("ERROR: Could not Open Mutex\n");
return 1;
}
// Open Post Command Semaphore
g_hSemPostC = RtOpenSemaphore( SYNCHRONIZE, FALSE, COECSL_SEM_COM_CLIENT);
if (g_hSemPostC==0)
{
RtCloseHandle( g_hShm);
RtCloseHandle( g_hMutex);
RtCloseHandle( g_hSemPostC);
printf("ERROR: Could not Open g_hSemPostC\n");
return 1;
}
// Open Post Command Acknowledge Semaphore
g_hSemPostCAck = RtOpenSemaphore( SYNCHRONIZE, FALSE, COECSL_SEM_COM_CLIENT_ACK);
if (g_hSemPostCAck==0)
{
RtCloseHandle( g_hShm);
RtCloseHandle( g_hMutex);
RtCloseHandle( g_hSemPostC);
RtCloseHandle( g_hSemPostCAck);
printf("ERROR: Could not Open g_hSemPostCAck\n");
return 1;
}
// Open Data Ready Semaphore
g_hSemDRdy = RtOpenSemaphore( SYNCHRONIZE, FALSE, COECSL_SEM_DATA_RDY_SERVER);
if (g_hSemDRdy==0)
{
RtCloseHandle( g_hShm);
RtCloseHandle( g_hMutex);
RtCloseHandle( g_hSemPostC);
RtCloseHandle( g_hSemPostCAck);
RtCloseHandle( g_hSemDRdy);
printf("ERROR: Could not Open g_hSemDRdy\n");
return 1;
}
// Open Data Ready Acknowledge Semaphore
g_hSemDRdyAck = RtOpenSemaphore( SYNCHRONIZE, FALSE, COECSL_SEM_DATA_RDY_SERVER_ACK);
if (g_hSemDRdyAck==0)
{
RtCloseHandle( g_hShm);
RtCloseHandle( g_hMutex);
RtCloseHandle( g_hSemPostC);
RtCloseHandle( g_hSemPostCAck);
RtCloseHandle( g_hSemDRdy);
RtCloseHandle( g_hSemDRdyAck);
printf("ERROR: Could not Open g_hSemDRdyAck\n");
return 1;
}
// Open Receive Data Semaphore
g_hSemRecv = RtOpenSemaphore( SYNCHRONIZE, FALSE, COECSL_SEM_DATA_RECV_CLIENT);
if (g_hSemRecv==0)
{
RtCloseHandle( g_hShm);
RtCloseHandle( g_hMutex);
RtCloseHandle( g_hSemPostC);
RtCloseHandle( g_hSemPostCAck);
RtCloseHandle( g_hSemDRdy);
RtCloseHandle( g_hSemDRdyAck);
RtCloseHandle( g_hSemRecv);
printf("ERROR: Could not Open g_hSemRecv\n");
return 1;
}
// Open Acknowledge Event Semaphore
g_hSemAckEvent = RtOpenSemaphore( SYNCHRONIZE, FALSE, COECSL_SEM_ACK_SENT_EVENT);
if (g_hSemAckEvent==0)
{
RtCloseHandle( g_hShm);
RtCloseHandle( g_hMutex);
RtCloseHandle( g_hSemPostC);
RtCloseHandle( g_hSemPostCAck);
RtCloseHandle( g_hSemDRdy);
RtCloseHandle( g_hSemDRdyAck);
RtCloseHandle( g_hSemRecv);
RtCloseHandle( g_hSemAckEvent);
printf("ERROR: Could not Open g_hSemAckEvent\n");
return 1;
}
// Open Event
g_hEvent = RtOpenEvent( SYNCHRONIZE, FALSE, COECSL_EVENT1);
if (g_hEvent==0)
{
RtCloseHandle( g_hShm);
RtCloseHandle( g_hMutex);
RtCloseHandle( g_hSemPostC);
RtCloseHandle( g_hSemPostCAck);
RtCloseHandle( g_hSemDRdy);
RtCloseHandle( g_hSemDRdyAck);
RtCloseHandle( g_hSemRecv);
RtCloseHandle( g_hSemAckEvent);
RtCloseHandle( g_hEvent);
printf("ERROR: Could not Open g_hEvent\n");
return 1;
}
// Wait to sync with DLL
RtWaitForSingleObject(g_hMutex, INFINITE);
return 0;
}
/*****************************************************************************
**** WaitforCommandandProcessEvents -- This function continually waits ****
**** for the Post Command Semaphore to be activated. When PostC has **
**** been activated the command is acknowledged with the PostCAck
**** semaphore and the command value is returned.
**** This function also checks to see if a send event command has been
**** requested. The parameter "eventcheckmillsec" determines how
**** often a check is done to see if an event has been requested to be
**** sent. The minimum value is 1.
*****************************************************************************/
LONG WaitforCommandandProcessEvents(DWORD eventcheckmillsec) {
LONG command;
// wait for the PostC semaphore
while (RtWaitForSingleObject(g_hSemPostC, eventcheckmillsec) == WAIT_TIMEOUT) {
// check if there is an event send request
if (g_SendEvent == 1) {
g_pshrcommand->Event_Command = CSL_EVENT;
g_pshrcommand->Event_UserCommand = g_EventCommand;
g_SendEvent = 0;
RtSetEvent(g_hEvent);
RtWaitForSingleObject(g_hSemAckEvent, INFINITE);
}
}
command = g_pshrcommand->Command_for_Client;
// Acknowledge that comand was received
RtReleaseSemaphore( g_hSemPostCAck, 1, NULL);
return command;
}
// check the status of Event
int ProcessingEvent(void) {
return g_SendEvent;
}
// Send an Event to the Win32 DLL
// The VB program will need to have code to process the eventcommand
// number sent
void fcnSendEvent(int eventcommand) {
if (g_SendEvent == 0) {
g_EventCommand = eventcommand;
g_SendEvent = 1;
}
}
/*****************************************************************************
**** GetSentData -- Call this function when a GetDataCommand has been sent **
**** GetSentData returns in its parameters an array of 20 **
**** floating point value and an array of characters. **
**** Depending on what command was sent, your program should **
**** know how to handle the sent data.
*****************************************************************************/
void GetSentData(float data[20],char *buffer) {
int i;
// get Sent float data from the shared memory
for (i=0;i<20;i++) {
data[i] = g_pshrcommand->Send_to_Client[i];
}
// get Sent char data and Null Terminator from the shared memory
for (i=0;i<g_pshrcommand->bufferlength+1;i++) {
buffer[i] = g_pshrcommand->buffer[i];
}
// acknowledge that data was received
RtReleaseSemaphore( g_hSemRecv, 1, NULL);
}
/*****************************************************************************
**** SetSendData -- Call this function when a RecvDataCommand has been sent **
**** SetSendData's parameter 'data' is a floating point array **
**** of the values being sent to the Win32 Server DLL (mecha.dll)
**** Depending on the command sent the RTSS process should know **
**** what data to send to the Win32 DLL
*****************************************************************************/
void SetSendData(float data[20]) {
int i;
// Load shared memory with data to be sent
for (i=0;i<20;i++) {
g_pshrcommand->Send_to_Server[i] = data[i];
}
// Set Semaphore Data Ready
RtReleaseSemaphore( g_hSemDRdy, 1, NULL);
// Wait for acknowledgement that the data was received
RtWaitForSingleObject(g_hSemDRdyAck, INFINITE);
}
/*********************************************************************
**** DeleteRTSS_Communcation -- Closes all communication objects **
*****************************************************************************/
void DeleteRTSS_Communication(void) {
RtCloseHandle( g_hShm);
RtCloseHandle( g_hMutex);
RtCloseHandle( g_hSemPostC);
RtCloseHandle( g_hSemPostCAck);
RtCloseHandle( g_hSemDRdy);
RtCloseHandle( g_hSemDRdyAck);
RtCloseHandle( g_hSemRecv);
RtCloseHandle( g_hSemAckEvent);
RtCloseHandle( g_hEvent);
}
// RTX 4.2's library does not have the standard 'sprintf' function
// only the 'vsprintf' function so I had to create my one 'sprintf'
// function. You can read more about vsprintf in Visual C++'s
// On-line help
void csl_sprintf( char *Buffer, const char *Format, ... ) {
va_list ArgList;
va_start(ArgList, Format);
vsprintf(Buffer, Format, ArgList);
va_end(ArgList);
}
// Initialize global variables for the savedata function
void init_savedata(void) {
g_data_count = 0;
g_mod_count = 0;
g_once_through = 0;
}
/*****************************************************************************
**** savedata -- Stores data in a once through or circular buffer.
**** Call this function to save data points that can later be
**** written to a data file with the function 'savedatafile'.
**** If circ = 0 the buffer is once through.
**** If circ = 1 the buffer is circular
**** savedata can save 8 floating points values
*****************************************************************************/
void savedata(int circ,float d1,float d2,float d3,float d4,float d5,
float d6,float d7,float d8)
{
// check if data_count larger the buffer size
if (g_data_count < NUM_POINTS) {
// save data every POINT_INCREMENT calls to savedata
if ((g_mod_count%POINT_INCREMENT)==0) {
// g_data is the buffer
g_data[0][g_data_count] = d1;
g_data[1][g_data_count] = d2;
g_data[2][g_data_count] = d3;
g_data[3][g_data_count] = d4;
g_data[4][g_data_count] = d5;
g_data[5][g_data_count] = d6;
g_data[6][g_data_count] = d7;
g_data[7][g_data_count] = d8;
// keep track of data size and index
g_data_count++;
g_mod_count++;
} else {
g_mod_count++;
}
}
// If using as circular buffer reset index g_data_count back
// to zero when buffer is full
if ((g_data_count == NUM_POINTS) && (circ == 1)) {
g_once_through = 1;
g_mod_count = 0;
g_data_count = 0;
}
}
/*****************************************************************************
**** savedatafile -- Write data stored by the 'savedata' function
**** to the filename given in datafile
*****************************************************************************/
int savedatafile(char* datafile) {
HANDLE hmyfile;
char mybuff[256];
DWORD mybyteswritten;
int i;
// open the file
if ((hmyfile = CreateFile(datafile,GENERIC_WRITE,0,NULL,CREATE_ALWAYS
,FILE_ATTRIBUTE_NORMAL
,NULL)) == INVALID_HANDLE_VALUE) {
printf("error opening file, error code %ld",GetLastError());
return 1;
}
// write a header to the file User Matlab comment '%'
csl_sprintf(mybuff,"%% var1 var2 var3 var4 var5 var6 var7 var8\n");
if (WriteFile(hmyfile,mybuff,strlen(mybuff), &mybyteswritten,NULL) == 0) {
printf("Error writing to file");
CloseHandle(hmyfile);
return 2;
}
// check if using a circular buffer
if (g_once_through == 1) {
g_data_count = NUM_POINTS;
}
// write data to file
for (i=0;i<g_data_count;i++) {
csl_sprintf(mybuff,"%.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f\n",
g_data[0][i],
g_data[1][i],
g_data[2][i],
g_data[3][i],
g_data[4][i],
g_data[5][i],
g_data[6][i],
g_data[7][i]
);
WriteFile(hmyfile,mybuff,strlen(mybuff), &mybyteswritten,NULL);
} /* endfor */
// close file
CloseHandle(hmyfile);
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -