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

📄 serialcom.c

📁 在VC6.0上编译通过的蓝牙通信演示程序, COM1口控制.
💻 C
📖 第 1 页 / 共 2 页
字号:
/*******************************************************************************
Copyright (C) Excelpoint System (Pte) Ltd. 2006

FILE: SerialCom.c

DESCRIPTION: This module is a Win32 implementation of a serial communication module.
			 The module is intended for use in combination with the ABCSP.
*******************************************************************************/




#include <Windows.h>
#include <process.h>
#include <stdlib.h>
#include <stdio.h>

#include "SerialCom.h"

#define	TX_BUF_MAX_SIZE				(4000)		/*	the buffer size for incoming and outgoing characters	*/
#define RX_BUF_MAX_SIZE				(4000)

#define DEBUG_ENABLE //enable uart TX/RX data log 

/* the following number can be used to limit the number of bytes send at the time to the YABCSP libray.
If not defined as many bytes as possible are send to the library */
/*#define	MAX_BYTES_TO_ABCSP			((uint16_t) 32)*/

#define CLOSE_DOWN_EVENT		0
#define	WROTE_DATA_EVENT		1
#define	NEW_TX_DATA_EVENT		2
#define	NO_OF_TX_EVENTS			3
#define	RX_DATA_EVENT			1
#define	DATA_READ_EVENT			2
#define	NO_OF_RX_EVENTS			3

/*	the UART file handler	*/
//static HANDLE	comHandle;	
static HANDLE	comHandle;	

/*	internal events used to signal the thread	*/
static HANDLE	newTxDataEvent;
static HANDLE	txCloseDownEvent;
static HANDLE	txDownEvent;
static HANDLE	rxCloseDownEvent;
static HANDLE	rxDownEvent;
static HANDLE	dataReadEvent;
static HANDLE	rxEvents[NO_OF_RX_EVENTS];
static HANDLE	txEvents[NO_OF_TX_EVENTS];

/*	ensure mutual exclusion for write and read	*/
static CRITICAL_SECTION	txMutex;
static CRITICAL_SECTION	rxMutex;

/*	the threads for rx and tx	*/
static HANDLE txThread;
static HANDLE rxThread;

static uint16_t	txIn;
static uint16_t	txOut;
static uint16_t	rxIn;
static uint16_t	rxOut;
static uint16_t	txSize;
static uint16_t	rxSize;
static uint8_t	txBuf[TX_BUF_MAX_SIZE];
static uint8_t	rxBuf[RX_BUF_MAX_SIZE];

static unsigned long baudRate;
static char comPortString[128];

DCB gDcb1, gDcb2;

void errorHandler(DWORD	line, char *file, char *text)
{
#ifdef DEBUG_ENABLE
	printf("Serial com error %s in file: %s, line %i\n", text, file, line);
#endif /*DEBUG_ENABLE*/
}

bool_t setComDefault(char *dcbInitString)
{
	/*	format of the init string must be: baud=1200 parity=N data=8 stop=1	*/
	bool_t			success;
	DCB				dcb;
	COMMTIMEOUTS	comTimeouts;

	success = TRUE;

    if(!GetCommState(comHandle, &dcb))
    {
		success = FALSE;
		errorHandler(__LINE__, __FILE__, "Can not read current DCB");
    }

	dcb.fOutxCtsFlow    = FALSE;
	dcb.fOutxDsrFlow    = FALSE;
	dcb.fDtrControl     = DTR_CONTROL_DISABLE;
	dcb.fDsrSensitivity = 0;
	dcb.fRtsControl     = RTS_CONTROL_DISABLE;
	dcb.ByteSize		= 8;		//8 bit
	dcb.StopBits		= ONESTOPBIT;
	dcb.Parity			= NOPARITY;	//non parity
	dcb.fBinary			= 1;

	/* then set baud rate, parity, data size and stop bit */
	if (!BuildCommDCB(dcbInitString, &dcb))
	{
		DWORD lastError;

		success = FALSE;
		lastError = GetLastError();
		printf("BuildCommDCB failed with error code: %ld!\n(device control string: %s)\n", lastError, dcbInitString);
	}

    comTimeouts.ReadIntervalTimeout = MAXDWORD;
    comTimeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
    comTimeouts.ReadTotalTimeoutConstant = 300000;
    comTimeouts.WriteTotalTimeoutMultiplier = 0;
    comTimeouts.WriteTotalTimeoutConstant = 0;

	if (!SetCommMask(comHandle, 0))
	{
		success = FALSE;
		errorHandler(__LINE__, __FILE__, "SetCommMask failed during initialisation");
	}

	if(!SetCommTimeouts(comHandle, &comTimeouts))
	{
		success = FALSE;
		errorHandler(__LINE__, __FILE__, "SetCommTimeouts failed during initialisation");
	}

	if(!SetCommState(comHandle, &dcb))
	{
		success = FALSE;
		errorHandler(__LINE__, __FILE__, "SetCommState failed during initialisation");
	}

	if (success == FALSE)
	{
		CloseHandle(comHandle);
		comHandle = INVALID_HANDLE_VALUE;
	}

	GetCommState(comHandle, &gDcb1);
	return(success);
}

bool_t	handleRxData(DWORD len, uint8_t	*data)
{
	uint16_t	theRxSize;

	EnterCriticalSection(&rxMutex);
	theRxSize = rxSize;
	rxSize = rxSize + (uint16_t) len;
	LeaveCriticalSection(&rxMutex);

	if ((rxIn + len) == RX_BUF_MAX_SIZE)
	{
		rxIn = 0;
	}
	else
	{
		rxIn = rxIn + (uint16_t) len;
	}

	if (memchr(data, 0xC0, len) != NULL)
	{
		//got data
	}
	return TRUE;
}

void txThreadFunc(void)
{
	OVERLAPPED	osWrote	= {0};
	DWORD		bytesWritten;
	DWORD		event;
	bool_t		txBusy;

	uint16_t	size;
	uint16_t	no2Send;
	DWORD		dwGetError;

	osWrote.hEvent	= CreateEvent(NULL, TRUE, FALSE, NULL);
	if ( osWrote.hEvent == NULL )
	{
		errorHandler(__LINE__, __FILE__, "Create event failed in tx thread");
		exit(0);
	}

	txEvents[CLOSE_DOWN_EVENT]	= txCloseDownEvent;
	txEvents[WROTE_DATA_EVENT]	= osWrote.hEvent;
	txEvents[NEW_TX_DATA_EVENT]	= newTxDataEvent;

	txBusy = FALSE;

	while (TRUE)
	{
		event = WaitForMultipleObjects(NO_OF_TX_EVENTS, txEvents, FALSE, INFINITE);

		switch (event)
		{
			case WAIT_OBJECT_0 + CLOSE_DOWN_EVENT:
			{
				/*	to do	*/
				ResetEvent(txCloseDownEvent);
				break;
			}
			case WAIT_OBJECT_0 + WROTE_DATA_EVENT:
			{
				BOOL	success;

				ResetEvent(osWrote.hEvent);

				txBusy = FALSE;
				success = GetOverlappedResult(comHandle, &osWrote, &bytesWritten, FALSE);
				if (success)
				{
					if (bytesWritten > 0)
					{
						txOut = txOut + (uint16_t) bytesWritten;
						if (txOut >= TX_BUF_MAX_SIZE)
						{
							txOut = 0;
						}
					}
					else
					{
						bytesWritten = 0;
					}
					EnterCriticalSection(&txMutex);
					txSize = txSize - (uint16_t) bytesWritten;
					LeaveCriticalSection(&txMutex);
				}
				else
				{
					errorHandler(__LINE__, __FILE__, "Error when sending data (wrote complete error - data packet lost)");
				}

				if (txSize > 0)
				{
					SetEvent(newTxDataEvent);
				}
				break;
			}

			case WAIT_OBJECT_0 + NEW_TX_DATA_EVENT:
			{
				ResetEvent(newTxDataEvent);

				/*	do not try to send while busy	*/
				if (!txBusy)
				{
					EnterCriticalSection(&txMutex);
					size = txSize;
					LeaveCriticalSection(&txMutex);

					if (size == 0)
					{
						/*	no data so take another loop	*/
						break;
					}

					no2Send = size;
					if (size + txOut > TX_BUF_MAX_SIZE)
					{
						no2Send = TX_BUF_MAX_SIZE - txOut;
					}

					if (WriteFile(comHandle, &(txBuf[txOut]), no2Send, &bytesWritten, &osWrote))
					{
						if (bytesWritten > 0)
						{
							txOut = txOut + (uint16_t) bytesWritten;
							if (txOut >= TX_BUF_MAX_SIZE)
							{
								txOut = 0;
							}
						}
						else
						{
							bytesWritten = 0;
						}
						EnterCriticalSection(&txMutex);
						txSize = txSize - (uint16_t) bytesWritten;
						LeaveCriticalSection(&txMutex);
						if (txSize > 0)
						{
							SetEvent(newTxDataEvent);
						}
					}
					else
					{
						dwGetError = GetLastError();
						if (dwGetError != ERROR_IO_PENDING)
						{
							printf("\n%d\n", dwGetError);
							errorHandler(__LINE__, __FILE__, "Serious error in write file (new data event) in tx thread");
						}
						else
						{
							/*	write pending	*/
							txBusy = TRUE;
						}
					}
				}
				else
				{
					if (WaitForSingleObject(osWrote.hEvent, 1) == WAIT_TIMEOUT)
					{
						ResetEvent(osWrote.hEvent);
						txBusy = FALSE;
						GetCommState(comHandle, &gDcb2);
					}
				}
				break;
			}

			default:
			{
				/*	error occured	*/
				errorHandler(__LINE__, __FILE__, "Default called");
				break;
			}
		}	/*	end switch	*/
		if (event == WAIT_OBJECT_0 + CLOSE_DOWN_EVENT)
		{
			break;
		}
	}	/*	end while	*/

	CloseHandle(osWrote.hEvent);

	SetEvent(txDownEvent);

	ExitThread(0);
}

void rxThreadFunc(void)
{
	OVERLAPPED	osRead	= {0};
	DWORD		event;
	uint8_t		*rxData;
	DWORD		bytesRead;
	bool_t		readSuccess;
	bool_t		startRead;
	uint16_t	theRxSize;
	COMSTAT		comStat;
	DWORD		errors;
	DWORD		numberToRead;


	osRead.hEvent	= CreateEvent(NULL, TRUE, FALSE, NULL);
	if ( (osRead.hEvent == NULL) )
	{
		errorHandler(__LINE__, __FILE__, "Create event failed in rx thread");
		exit(0);
	}

	rxEvents[CLOSE_DOWN_EVENT]	= rxCloseDownEvent;
	rxEvents[RX_DATA_EVENT]		= osRead.hEvent;
	rxEvents[DATA_READ_EVENT]	= dataReadEvent;

	rxData = rxBuf;
	rxSize = 0;

	while (TRUE)
	{
		EnterCriticalSection(&rxMutex);
		theRxSize = rxSize;
		LeaveCriticalSection(&rxMutex);

		/*	find next position for rx data in and if any space available in buffer	*/
		if (theRxSize < RX_BUF_MAX_SIZE)
		{
			startRead = TRUE;
		}
		else
		{
			/*	wait for available space in the buffer	*/
			startRead = FALSE;
		}
		
		/*	kick the read process if allowed (space left in rx buffer)	*/
		if (startRead)
		{
			rxData = rxBuf + rxIn;

			/* find out how many to read */
			if (!ClearCommError(comHandle, &errors, &comStat))
			{
				/*	serious error	*/
				errorHandler(__LINE__, __FILE__, "Serious error in read file in rx thread");
			}
			numberToRead = comStat.cbInQue > 0 ? comStat.cbInQue : 1;
			if (rxIn + numberToRead > RX_BUF_MAX_SIZE)
			{
				numberToRead = RX_BUF_MAX_SIZE - rxIn;
			}

			readSuccess = ReadFile(comHandle, rxData, numberToRead, &bytesRead, &osRead);
			if (!readSuccess)
			{
				if (GetLastError() != ERROR_IO_PENDING)
				{
					/*	serious error	*/
					errorHandler(__LINE__, __FILE__, "Serious error in read file in rx thread");
				}
			}
			else
			{
				if (bytesRead > 0)
				{
					handleRxData(bytesRead, rxData);
				}
			}
		}

		if (!readSuccess)
		{
			do
			{
				event = WaitForMultipleObjects(NO_OF_RX_EVENTS, rxEvents, FALSE, INFINITE);
				switch (event)
				{
					case CLOSE_DOWN_EVENT:
					{
						/*	to do	*/
						ResetEvent(rxCloseDownEvent);
						break;
					}
					case RX_DATA_EVENT:
					{
						bool_t	success;

						/*	receive complete, store the data	*/
						success = GetOverlappedResult(comHandle, &osRead, &bytesRead, FALSE);

						if ((bytesRead > 0) && success)
						{
							handleRxData(bytesRead, rxData);
						}

						startRead = FALSE;
						ResetEvent(osRead.hEvent);
						break;
					}
					case DATA_READ_EVENT:
					{
						/* sufficient data has been read from the rx buffer to restart the reader thread */
						ResetEvent(dataReadEvent);
						break;
					}

⌨️ 快捷键说明

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