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

📄 freeportreceive.c

📁 simulink real-time workshop for dragon12 development board from
💻 C
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************/
/*                                                                            */
/* Name: freePortReceive.c  - mex function for the communication to the       */
/*                            free asynchronous serial interface SCI0/1       */
/*                                                                            */
/******************************************************************************/

// =============================================================================
// fw-10-06
// =============================================================================

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


#include "mex.h"
#include "matrix.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

#include "freePortComms.h"		// macros, struct myUsrBuf


// DEFINE global user communication admin variables
myUsrBuf	*freecomTelBuf[MAX_FREECOM_CHANNELS];		/* pointer to the data buffer admin structures of all user telegrams */



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

// input signals may have the following bytes per element
#define		numDATATYPES	8
const unsigned int BuiltInDTypeSize[numDATATYPES] =	{
															4,    /* single  : ID = 0*/
															1,    /* int8    : ID = 1 */
															1,    /* uint8   : ID = 2 */
															2,    /* int16   : ID = 3 */
															2,    /* uint16  : ID = 4 */
															4,    /* int32   : ID = 5 */
															4,    /* uint32  : ID = 6 */
															2     /* boolean : ID = 7 */
														};


#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
#define		numBAUDRATES	10
const unsigned int BaudRates[numBAUDRATES] =	{
													300,
													600,
												   1200,
												   2400,
												   4800,
												   9600,
												  19200,
												  38400,
												  57600,
												 115200
												};


// DEFINE maximum number of elements per channel transmission
// (inconsistent -> see freePortComms.h, macro MAX_FREECOM_BUF_SIZE  --  fw-10-05)
#define		maxNUMELEMENTS			100


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


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

	//mexPrintf("checkCOM4data: IN.\n");

	/* 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) */
		//mexPrintf("checkCOM4data: OUT (not valid).\n");
		return -1;

	}

} /* end checkCOMforData */



/* Function: FreePortOpenConnection =================================================
 *
 *  Open the connection with the target using the free communication port.
 */
HANDLE FreePortOpenConnection(unsigned int port, unsigned int baudrate) {

	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("freePortReceive|FreePortOpenConnection: IN\n");
	#endif /* VERBOSE */


	// open serial interface 'COMxString'
	sprintf(COMxString, "COM%1d", (uint8_T)port);
	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 = baudrate;						// 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("freePortReceive|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)
            mexPrintf ("Receive: Timeout during data reception.\n");
         *ReceiveTimeoutFlag = TRUE;
         return (FALSE);
      }
   }
   else
   {
      // unspecified error during data reception
      mexPrintf ("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;
	
}



// ----------------------------------------------------------------------------------------------------
// mex function
// ----------------------------------------------------------------------------------------------------

/* Function: mexFunction =======================================================
 * Abstract:
 *    Gateway from Matlab.
 */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    

mxArray		    *pArray;            /* output data */
mxArray		    *pArray2;           /* number of elements received */
mxArray			*FreePortAdminVar;
myCOMPort		**myPtr;

unsigned int	myPort = 1;
unsigned int	myBaud = 300;
unsigned int	myChannel = 0;
unsigned int	channel;
unsigned int	myElements = 0;
unsigned char	mydType = 0;
unsigned int	myRawFlag;
unsigned int	buf_size = 0;
unsigned int	size;
unsigned char	*buf;
unsigned int	myBlockingFlag = 0;

myUsrBuf	*admin;
myCOMPort   *adminP = NULL;
uint8_T		*outBuf;
double		*outnEls;

#define	 NDIMS  2							// dimension of the output data
static unsigned int   dims[NDIMS];



	/* check syntax */
    if ((nlhs != 2) || (nrhs != 6)) {
        
        mexErrMsgTxt("Usage:  [data, nElementsReceived] = freePortReceive(COMx, baudrate, channel, nElememts, dataType, blockingFlag)\n");
        
    } else {
		
		/* syntax correct -> analyse inputs */
		int  k = 0;
		while(k < 6) {
		
			switch(k) {
				
				case 0:
					
					/* COM port */
					if(mxIsNumeric(prhs[k]) && !mxIsComplex(prhs[k])) {
						
						/* get COM port */
						myPort = (unsigned int)mxGetScalar(prhs[k]);
						
						if((myPort < 0) || (myPort > 30))
							mexErrMsgTxt("Invalid COM port number.\n");
						
						#ifdef VERBOSE
						mexPrintf("freePortReceive: COMx = %d\n", myPort);
						#endif /* VERBOSE */
						
					}
					else {
						
						mexErrMsgTxt("Parameter [COMx] needs to be a scalar number.\n");
						
					}
					
					k = k + 1;
					break;
					
				case 1:
					
					/* Baudrate */
					if(mxIsNumeric(prhs[k]) && !mxIsComplex(prhs[k])) {
						
						int i, m;
						
						/* get Baudrate */
						myBaud = (unsigned int)mxGetScalar(prhs[k]);
						
						/* check if this is a valid baudrate */
						for(i=0, m=-1; i<numBAUDRATES; i++) {
							
							#ifdef VERBOSE
							mexPrintf("freePortReceive: Checking baudrate: %d\n", BaudRates[i]);
							#endif /* VERBOSE */
							
							if(myBaud == BaudRates[i]) {
								
								#ifdef VERBOSE
								mexPrintf("freePortReceive: Detected supported baudrate (%d)\n", myBaud);
								#endif /* VERBOSE */
								
								m = i;
								break;
								
							}
							
						}
						
						if(m == -1) {
							
							mexErrMsgTxt("Unsupported baudrate.\n");
							
						}
						
					}
					else {
						

⌨️ 快捷键说明

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