⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 freeportcomms_rxd.c

📁 simulink real-time workshop for dragon12 development board from
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************/
/*                                                                            */
/* Name: freePortComms_rxd.c  - S-Function for the communication using the    */
/*                              second asynchronous serial interface SCI0/1   */
/*                                                                            */
/******************************************************************************/

// =============================================================================
// fw-04-05
//
// level 2 s-function
//
// =============================================================================

#define S_FUNCTION_NAME freePortComms_rxd
#define S_FUNCTION_LEVEL 2


/* undefine VERBOSE to run this DLL in silent mode */
//#define VERBOSE


#include <simstruc.h>
#include <windows.h>			// BuildCommDCB, CloseHandle, CreateFile, EscapeCommFunction, GetCommState,
								// GetLastError, ReadFile, SetCommState, SetCommTimeouts, WriteFile, FlushFileBuffers
								// Sleep
#include <stdio.h>				// sprintf
#include <stdlib.h>				// malloc, calloc
#include <string.h>				// memcpy


#ifdef MATLAB_MEX_FILE
#define abort_LED(x) return
#else
#include "mc_signal.h"		/* abort_LED, etc. */
#endif

// declaration of global user communication admin variables (only relevant for the target module, defined in ext_srv.h)
#include "freePortComms.h"

// DEFINE global user communication admin variables ( initialised in mc_main->Init_ComVars() )
myUsrBuf	*freecomTelBuf[MAX_FREECOM_CHANNELS];		/* pointer to the data buffer admin structures of all user telegrams */


/* receive */
BOOL     ReceiveTimeoutFlag;


// flag : communication with/without echo?
#define with_echo  TRUE
#define no_echo    FALSE

// flag : display on-screen timeout messages?
#define with_to_messages  TRUE 
#define no_to_messages    FALSE


// -------------------------------------------------------------------------------
// Number of S-function Parameters and macros to access from the SimStruct
// -------------------------------------------------------------------------------

#define SAMPLE_TIME_ARG		ssGetSFcnParam(S,0)		/* Sample time in seconds */
#define CHANNEL_NO_ARG		ssGetSFcnParam(S,1) 	/* communication channel number (up to MAX_FREECOM_CHANNELS) */
#define NUM_ELEMENTS_ARG	ssGetSFcnParam(S,2)		/* block output width ->  # of elements */
#define DATA_TYPE_ARG       ssGetSFcnParam(S,3) 	/* data type to be expected at block input */
#define PORT_ARG            ssGetSFcnParam(S,4) 	/* communication port ([COM]1 - [COM]4) */
#define BAUDRATE_ARG        ssGetSFcnParam(S,5) 	/* baudrate (300 [bps] - 115200 [bps]) */
#define FORMAT_ARG          ssGetSFcnParam(S,6) 	/* format (0: formatted, 1: unformatted */
#define NUMBER_OF_ARG       7              			/* Number of input arguments */


// -------------------------------------------------------------------------------
// Macros to access the S-function parameter values
// -------------------------------------------------------------------------------

#define SAMPLE_TIME     ((real_T)   mxGetPr (SAMPLE_TIME_ARG)[0])
#define CHANNEL_NO      ((uint_T)   mxGetPr (CHANNEL_NO_ARG)[0])
#define NUM_ELEMENTS    ((uint_T)   mxGetPr (NUM_ELEMENTS_ARG)[0])
#define DATA_TYPE       ((uint_T)   mxGetPr (DATA_TYPE_ARG)[0])
#define PORT            ((uint_T)   mxGetPr (PORT_ARG)[0])
#define BAUDRATE        ((uint32_T) mxGetPr (BAUDRATE_ARG)[0])
#define FORMAT          ((uint_T)   mxGetPr (FORMAT_ARG)[0])


// ----------------------------------------------------------------------------------------------------
// global variables
// ----------------------------------------------------------------------------------------------------

// input signals may have the following bytes per element
const int_T	BuiltInDTypeSize[8] =	{
										4,    /* real32_T  */
    									1,    /* int8_T    */
    									1,    /* uint8_T   */
    									2,    /* int16_T   */
    									2,    /* uint16_T  */
    									4,    /* int32_T   */
    									4,    /* uint32_T  */
    									2     /* boolean_T */
									};


#define  tSINGLE  	0
#define  tINT8  	1
#define  tUINT8  	2
#define  tINT16  	3
#define  tUINT16  	4
#define  tINT32  	5
#define  tUINT32  	6
#define  tBOOLEAN	7

// map BAUDRATE parameter (1 - 10) to true baudrates
const DWORD BaudRates[10] =	{
										300,
										600,
									   1200,
									   2400,
									   4800,
									   9600,
									  19200,
									  38400,
									  57600,
									 115200
									};


/* descramble buffer ... (fw-09-06) */
unsigned char	receivebuf[MAX_FREECOM_BUF_SIZE + 10];



// ----------------------------------------------------------------------------------------------------
// local methods
// ----------------------------------------------------------------------------------------------------

/* allocate and initialise the communication variables associated with a particular channel (buffer, admin, ... ) */
static myUsrBuf *AllocateUserBuffer(uint_T channel, uint_T bufsize, uint8_T data_type_len) {

	uint8_T			*buf;
	static myUsrBuf	*admin = NULL;

	/* allocate memory for admin structure of this instance's data buffer */
	if((admin = (myUsrBuf *)calloc(1, sizeof(myUsrBuf))) == NULL)  return NULL;
		
	/* allocate memory for the buffer itself (buf_size '+ 4'  ->  telegram size, channel number, data type length, '0' [reserved]) */
	if((buf = (uint8_T *)calloc(bufsize + 4, sizeof(uint8_T))) == NULL)  return NULL;

	/* store pointer to buf in the admin structure */
	admin->buf = buf;

	/* store size of the actual data buffer */
	admin->buf_size = bufsize;

	/* initialise the access_count field */
	admin->access_count = 1;

	/* initialise the buffer_full flag */
	admin->buffer_full = 0;


	/* initialise buffer */

	/* set first field of the buffer to the number of bytes per user telegram (remains invariant)... */
	buf[0] = (uint8_T)(bufsize + 4);

	/* set second field of the buffer to the channel number (remains invariant)... */
	buf[1] = (uint8_T)channel;

	/* set third field of the buffer to the channel data type length: 1, 2, 4) (remains invariant)... */
	buf[2] = data_type_len;

	//mexPrintf("Setting channel %d data type length to: %d\n", channel, data_type_len);

	/* ... and clear the reserved byte (buf[3]) as well as the local data buffer */
	memset(&buf[3], 0, bufsize + 1);
	

	/* return access pointer */
	return admin;
}
		

/* Function: checkCOMforData ===================================================
 * check if there's data in the COM buffer (FW-09-02)
 */
static int checkCOMforData(HANDLE hCom) {

	COMSTAT		cs;
	DWORD		error;

	/* only check port if 'hCom' is valid... */
    if (hCom != INVALID_HANDLE_VALUE) {

		// reset error status (returns structure COMSTAT [winbase.h])
		if(!ClearCommError(hCom, (LPDWORD)&error, (LPCOMSTAT)&cs)) {
			// error during call to ClearCommError
			mexPrintf("checkCOM4data: Error during call to ClearCommError.\n");

			// flag error to the calling function
			return -1;
		}
		else {
		
			// debug
			//mexPrintf("FreePort: checkCOMforData detected %d data bytes in COM buffer\n", (int)cs.cbInQue);
		
			// return number of bytes in the buffer
			return (int)cs.cbInQue;
		}

	} else {

		/* port handle not valid (not a COM port) */
		return -1;

	}

} /* end checkCOMforData */


/* Function: FreePortOpenConnection =================================================
 *
 *  Open the connection with the target using the free communication port.
 */
HANDLE FreePortOpenConnection(SimStruct *S) {

	HANDLE			hCom = INVALID_HANDLE_VALUE;
	static char     COMxString[5];								// serial interface designator
	char		    COMxStringParam[16];
	DCB		        dcb;
	COMMTIMEOUTS	CommTimeouts;

	char			tmp[512];									// error messages

	// default communication parameters (dummy)
	#define	DefaultComParam ":9600,n,8,1"

	// default timeout value (ms) - send and receive
	#define	DefaultTimeout		10000


	#ifdef VERBOSE
	mexPrintf("freePortComms_rxd|FreePortOpenConnection: IN\n");
	#endif /* VERBOSE */


	// open serial interface 'COMxString' (PORT = 3 -> COM1, PORT = 4 -> COM2, etc.)
	sprintf(COMxString, "COM%1d", (uint8_T)(PORT - 2));
	hCom = CreateFile (COMxString, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
	if (hCom == INVALID_HANDLE_VALUE) {

		sprintf(tmp, "Error while trying to open serial interface %s:\n", COMxString);
		mexErrMsgTxt(tmp);
	}

	// initialise 'DCB' structure
	dcb.DCBlength = sizeof (DCB);
	if (!GetCommState (hCom, &dcb)) {

		mexErrMsgTxt("Error while trying to determine current state of the COM interface.\n");
	}

	sprintf (COMxStringParam, "%s%s", COMxString, DefaultComParam);
	if (!BuildCommDCB (COMxStringParam, &dcb)) {

		mexErrMsgTxt("Error while generating DCB data structure,\n");

	}

	// set transmission parameters
	dcb.BaudRate = BaudRates[BAUDRATE-1];			// transmission speed (bps)
	dcb.fRtsControl = RTS_CONTROL_DISABLE;			// RTS = 'low' (mis-used to generate a software 'reset'...
	dcb.fOutX = FALSE;								// disable XON/XOFF protocol
	dcb.fInX = FALSE;								// (both for TX and RX)

	// initialise serial interface 'hCom'
	if (!SetCommState (hCom, &dcb)) {

		sprintf(tmp, "Error during initialisation of the serial interface %s:\n", COMxString);
		mexErrMsgTxt(tmp);
	}

	// reset 'hCom' and set length of input/output buffer to FREEPORT_HOST_BUF_SIZE (default: 1200) bytes (each)
	if (!SetupComm (hCom, FREEPORT_HOST_BUF_SIZE, FREEPORT_HOST_BUF_SIZE)) {

		sprintf(tmp, "Error during reset of the serial interface %s:\n", COMxString);
		mexErrMsgTxt(tmp);
	}

	// initialise all timeouts (send/receive) as 'DefaultTimeout' (1000 ms)
	CommTimeouts.ReadIntervalTimeout = DefaultTimeout;
	CommTimeouts.ReadTotalTimeoutMultiplier = DefaultTimeout;
	CommTimeouts.ReadTotalTimeoutConstant = DefaultTimeout;
	CommTimeouts.WriteTotalTimeoutMultiplier = DefaultTimeout;
	CommTimeouts.WriteTotalTimeoutConstant = DefaultTimeout;
	SetCommTimeouts(hCom, &CommTimeouts);


	/* make sure we start with an empty buffer... */
	if(!FlushFileBuffers(hCom)) {
				
		/* flushing of the output buffer returns unsuccessful... */
		mexPrintf ("freePortComms_rxd|FreePortOpenConnection: Error whilst flushing output buffers (FlushFileBuffers).\n");
		{
			DWORD err = GetLastError();
			mexPrintf("Error code: %ld\n", err);
		}
				
	}


	#ifdef VERBOSE
	mexPrintf("freePortComms_rxd|FreePortOpenConnection: OUT\n");
	#endif /* VERBOSE */

	return hCom;

} /* end ExtOpenConnection */


/* Function: FreePortCloseConnection ================================================
 * 
 *  Close the connection via the free comms port.
 */
void FreePortCloseConnection(HANDLE hCom) {

	#ifdef VERBOSE
	mexPrintf("FreePortCloseConnection: IN\n");
	#endif

    if (hCom != INVALID_HANDLE_VALUE) {

		// close serial interface 'hCom'
		if(!CloseHandle(hCom)) {
			mexErrMsgTxt("Error when closing the serial interface.\n");
		}

	}

	#ifdef VERBOSE
	mexPrintf("FreePortCloseConnection: OUT\n");
	#endif

} /* end FreePortCloseConnection */



// =====================================================================================================
// Receive... receive a string from the serial interface 'hCom'
// =====================================================================================================

// CALL-UP PARAMETERS:
//
// '&r_zeichen':			store received characters here...
// 'z_len_toread':		number of characters to be read
// 'ReceiveTimeoutFlag':	TRUE (timeout occurred), FALSE (no timeout)
// 'TimeoutMessageFlag':	TRUE (onscreen timeout messages) / FALSE (no messages)
//
// RETURN VALUE:			TRUE (successful reception) / FALSE ('reception error' or 'timeout')


BOOL Receive (HANDLE hCom, BYTE r_zeichen[], DWORD z_len_toread, 
              BOOL *ReceiveTimeoutFlag, BOOL TimeoutMessageFlag)
{
DWORD		z_len_read;


   *ReceiveTimeoutFlag = FALSE;
   if (ReadFile(hCom, (LPSTR) r_zeichen, z_len_toread, &z_len_read, NULL))
   {
      if (z_len_read == z_len_toread)
	{
         // successful reception
         return (TRUE);
      }
      else
	{
	   // timeout occurred during reception of data
         if (TimeoutMessageFlag == with_to_messages)
            ssPrintf ("Receive: Timeout during data reception.\n");
         *ReceiveTimeoutFlag = TRUE;
         return (FALSE);
      }
   }
   else
   {
      // unspecified error during data reception
      ssPrintf ("Receive: Unspecified error during data reception.\n");
      return (FALSE);
   }
}


/* Function: ReverseOrder4 =================================================
 *
 *  Reverse the order of bytes in a 4-tuple
 */
void *ReverseOrder4(unsigned char *buf) {

unsigned char	temp;

	#ifdef VERBOSE
	{
		mexPrintf("ReverseOrder4 %d:%d:%d:%d >> ", buf[0], buf[1], buf[2], buf[3]);
	}
	#endif /* VERBOSE */

	temp   = buf[0];
	buf[0] = buf[3];
	buf[3] = temp;
	temp   = buf[1];
	buf[1] = buf[2];
	buf[2] = temp;
	
	#ifdef VERBOSE
	{
		mexPrintf("%d:%d:%d:%d\n", buf[0], buf[1], buf[2], buf[3]);
	}
	#endif /* VERBOSE */
	
	return (void *)buf;
	
}


/* Function: ReverseOrder2 =================================================
 *
 *  Reverse the order of bytes in a 2-tuple
 */
void *ReverseOrder2(unsigned char *buf) {

unsigned char	temp;

	#ifdef VERBOSE
	{
		mexPrintf("ReverseOrder2 %d:%d >> ", buf[0], buf[1]);
	}
	#endif /* VERBOSE */

	temp   = buf[0];
	buf[0] = buf[1];
	buf[1] = temp;
	
	#ifdef VERBOSE
	{
		mexPrintf("%d:%d\n", buf[0], buf[1]);
	}
	#endif /* VERBOSE */
	
	return (void *)buf;
	
}



// ----------------------------------------------------------------------------------------------------
// S-Function methods
// ----------------------------------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -