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

📄 freeportcomms_txd.c

📁 simulink real-time workshop for dragon12 development board from
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************/
/*                                                                            */
/* Name: freePortComms_txd.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_txd
#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 */


/* send */
BOOL SendTimeoutFlag;


// 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	sendbuf[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);

	#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 */


		
// =====================================================================================================
// Send... sends a string via the serial interface 'hCom'
// =====================================================================================================

// CALL-UP PARAMETERS:
//
// '&data':			string to be sent is stored here 
// 'nToWrite':		number of characters to be sent
// 'EchoFlag = TRUE/FALSE': 	Send() awaits 'echo' / 'no echo'
// 'SendTimeoutFlag':		TRUE (timeout occurred), FALSE (no timeout)
// 'TimeoutMessageFlag':	TRUE (onscreen timeout messages) / FALSE (no messages)
//
// RETURN VALUE:			TRUE (successful transmission) / FALSE ('transmission error' or 'timeout')

BOOL Send(HANDLE hCom, BYTE data[], DWORD nToWrite, BOOL EchoFlag,
          BOOL *SendTimeoutFlag, BOOL TimeoutMessageFlag)
{
int		i;
DWORD	nWritten, z_len_read;
BYTE 	*myChar;
BYTE 	r_myChar;

    
	/* only attempt to send stuff if we're working with a proper port (not for the dummy port  --  fw-09-06) */
	if (hCom == INVALID_HANDLE_VALUE) return FALSE;


	*SendTimeoutFlag = FALSE;
	if (EchoFlag == with_echo) {

		// send message 'character by character'
		// request every character to be sent back (echo)
		for (i = 0; i < (int)(nToWrite); i++) {

			myChar = &data[i];
			if (WriteFile(hCom, (LPSTR) myChar, 1, &nWritten, NULL)) {

				if (nWritten == 1) {

					// a character has successfully been sent; awaiting echo...
					if (ReadFile(hCom, (LPSTR) &r_myChar, 1, &z_len_read, NULL)) {

						// ReadFile returns successfully
						if (z_len_read == 1) {

							// one character has been received
							if (r_myChar != *myChar) {

								// invalid echo
								ssPrintf ("Send: Transmission ('%3d') and reception ('%3d') differ.\n\n", *myChar, r_myChar);
								return (FALSE);

							}
						}
						else {

							// z_len_read != 1  >> more/less than one character have been received
							// -> timeout occurred during reception of the data echo (most likely)
							if (TimeoutMessageFlag == with_to_messages)
								ssPrintf ("Send: Timeout during reception of data echo.\n");
					
							*SendTimeoutFlag = TRUE;		// signal timeout
							return (FALSE);
						}
					}
					else {

						// error during call to ReadFile()
						ssPrintf ("Send: Unspecified error during reception of data echo.\n");
						return (FALSE);
					}
				}  
				else {

					// z_len_write != 1 >> more/less than one character have been sent
					// -> timeout occurred during the transmission of the character
					if (TimeoutMessageFlag == with_to_messages)
						ssPrintf ("Send: Timeout during data transmission (with echo).\n");

					*SendTimeoutFlag = TRUE;
					return (FALSE);
				}
			}
			else {

				// error during call to WriteFile()
				ssPrintf ("Send: Unspecified error during transmission (with echo).\n");
				return (FALSE);

			}

		} /* for (i = 0; i < nToWrite; i++) */

		return (TRUE);

	} /* if (EchoFlag == with_echo) */
	else {

		// send the entire string 'in one go' -> no echo
		if(WriteFile(hCom, (LPSTR) data, nToWrite, &nWritten, NULL)) {

			if (nWritten == nToWrite) {

				// no errors during transmission :-)
				return (TRUE);
			}   
			else {

				// Timeout during data transmission
				if (TimeoutMessageFlag == with_to_messages)
					ssPrintf ("Send: Timeout occurred during data transmission (without echo).\n");

				*SendTimeoutFlag = TRUE;
				return (FALSE);
			}
		}
		else {

			// WriteFile() returned unsuccessfully
			ssPrintf ("Send: Unspecified error during data transmission (without echo).\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]);

⌨️ 快捷键说明

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