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

📄 com.h

📁 TBCOMM串口类使用用例.TBCOMM是本人在CNCOMM的基础上改良后的一个类块,这个用例是在C++ BUILDER 2007上开发的
💻 H
字号:
/*
作者:季节彬 --中科飞跃
写于2007.08
*/
#ifndef	_TB_COMM_H_
#define _TB_COMM_H_
#include <assert.h>
#include <stdio.h>
#include <windows.h>
#include <time.h>
#define UART_BPS 115200					 // 串口波特率
#define UART_RW_BUF 4096                 //读写缓冲大小
#define ON_COM_RECEIVE WM_USER + 618	 //	 WPARAM 端口号
#define max_cmd 16						//读取的最大命令数
#define pc_debug
class TBComm
{
public:
	TBComm()
	{
		Init();
	}
	virtual ~TBComm()
	{
		Close();	
		UnInit();
	}
   bool Open(DWORD dwPort,HWND Wnd)						 							//打开串口
	{
			char p[5];
			if(dwPort < 1 || dwPort > 1024)
			 {
				return false;
			 }
			if(CommHandle!=INVALID_HANDLE_VALUE) 					//已经打开了
			 {
				return false;
			 }
			SendWnd=Wnd;
			strcpy(CommStr, "\\\\.\\COM");								//WINDOWS 串口标准路径
			ltoa(dwPort, p, 10);
			strcat(CommStr, p);

			CommHandle = ::CreateFile(
				CommStr,
				GENERIC_READ | GENERIC_WRITE,
				0,
				NULL,
				OPEN_EXISTING,
				FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
				NULL
				);																					//打开串口
	
				if((CommHandle!=INVALID_HANDLE_VALUE) && BeginThread())
				{
				 ;	//return true;
				}
				else
				{
					Close(); 																	//创建线程失败
					return false;
				  }
		
			 if(!::SetupComm(CommHandle,UART_RW_BUF, UART_RW_BUF)) {return false;}//设置推荐缓冲区

			 if(!::GetCommTimeouts(CommHandle, &TB_CO)) {return false;}//设置超时时间
			 TB_CO.ReadIntervalTimeout = 0;
			 TB_CO.ReadTotalTimeoutMultiplier = 0;
			 TB_CO.ReadTotalTimeoutConstant =0;
			 TB_CO.WriteTotalTimeoutMultiplier = 0;
			 TB_CO.WriteTotalTimeoutConstant = 2000;
			 if(!::SetCommTimeouts(CommHandle, &TB_CO)) {return false;}//设置超时时间结束

			 if(!::PurgeComm(CommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
			  {return false;}																					//清空串口缓冲区
			  
			 if(!::GetCommState(CommHandle, &TB_DCB))									//设置连接参数
			  {return false;}
				TB_DCB.BaudRate = UART_BPS;
				TB_DCB.ByteSize = 8;
				TB_DCB.Parity   = NOPARITY;
				TB_DCB.StopBits = ONESTOPBIT;
			 return ::SetCommState(CommHandle, &TB_DCB) == TRUE;			//设置连接参数结束,波特率57600,n,8,1
	}
	
	virtual void Close()
	{
		if(CommHandle!=INVALID_HANDLE_VALUE)		
		{
			EndThread();
			::CloseHandle(CommHandle);
			CommHandle = INVALID_HANDLE_VALUE;
		}
	}
protected:
	volatile HWND SendWnd; 								// 通知窗口
	volatile HANDLE CommHandle;							//串口句柄
	volatile HANDLE ThreadHandle_NO1;					//辅助线程:接收
	volatile HANDLE ThreadHandle_NO2;					//辅助线程:处理
	OVERLAPPED _ReadOverlapped, _WriteOverlapped; 		//重叠I/O
	OVERLAPPED _WaitOverlapped; 						//WaitCommEvent use
	COMMTIMEOUTS TB_CO;     							//超时结构
	DCB TB_DCB;											//波特率,停止位,等
	char CommStr[20];
	DWORD CMD_INDEX,CMD_PARM;                           //命令+参数
	char Command_WStr[30];								//发送出去的命令缓存
	bool Command_Enable;                                //命令发送使能,true:可以发送命令,false:暂停200ms后允许发送命令
	char Command_Buf[max_cmd][UART_RW_BUF];						//串口命令堆栈
	char Command_Num;
	char Command_Work_Ptr;								//最后处理完成的命令指针
	char Command_Read_Ptr;								//命令堆栈数组最后一条指针
	unsigned char  *Data_Ptr; 			  				//花样数据指针
	unsigned long Data_len;								//花样数据长度
	char Command_Step; 									//命令执行控制开关
	char Connect_flag;									//是否已经处于联机中了
	char Run_flag;                                      //处于刺绣中,电机正运行
	char Data_flag;										//数据发送过没有?
	char Wound_flag;									//正在绕线标志
	char Connect_step;									//连接的步骤状态
	void Init()	//初始化
		{
			memset(CommStr, 0, 20);
			memset(&TB_DCB, 0, sizeof(TB_DCB));
			TB_DCB.DCBlength = sizeof(TB_DCB);
			CommHandle = INVALID_HANDLE_VALUE;
	
			memset(&_ReadOverlapped, 0, sizeof(_ReadOverlapped));
			memset(&_WriteOverlapped, 0, sizeof(_WriteOverlapped));
	
			_ReadOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
			assert(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE); 
			
			_WriteOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
			assert(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);
	
			ThreadHandle_NO1 = NULL;
			ThreadHandle_NO2 = NULL;
			Command_Enable=true;
			CMD_INDEX=0;
			Command_Num=0;
			Command_Work_Ptr=0;
			Command_Read_Ptr=0;
			Command_Step=0;
			Run_flag=0;
			Connect_flag=0;
			Data_flag=0;
			Wound_flag=0;
			Connect_step=0;
			Data_len=0;
			memset(&_WaitOverlapped, 0, sizeof(_WaitOverlapped));
			_WaitOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
			assert(_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE);	
	}	
			
	void UnInit()
	{
			if(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)
				CloseHandle(_ReadOverlapped.hEvent);
	
			if(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)
				CloseHandle(_WriteOverlapped.hEvent);
	
			if(_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE)
				CloseHandle(_WaitOverlapped.hEvent);
	}
	DWORD Write(char *szBuffer, DWORD dwBufferLength)							//写串口 szBuffer
	{
		if(CommHandle==INVALID_HANDLE_VALUE)
			return 0;
		
		DWORD dwError;
		if(::ClearCommError(CommHandle, &dwError, NULL) && dwError > 0)	//清除错误
			::PurgeComm(CommHandle, PURGE_TXABORT | PURGE_TXCLEAR);	

		unsigned long uWriteLength = 0;

		if(!::WriteFile(CommHandle, szBuffer, dwBufferLength+1, &uWriteLength, &_WriteOverlapped))
		if(::GetLastError() != ERROR_IO_PENDING)
		{
			uWriteLength = 0;
		}
		return uWriteLength;
	}
	
	bool BeginThread() 																//辅助线程控制 建监视线程
	{
			DWORD id1,id2;
			ThreadHandle_NO1 = ::CreateThread(NULL, 0, Com_Read_ThreadProc, this, 0, &id1); //接收线程
			ThreadHandle_NO2 = ::CreateThread(NULL, 0, Com_Work_ThreadProc, this, 0, &id2); //处理线程
			return ((ThreadHandle_NO1 != NULL)&&(ThreadHandle_NO2 != NULL)); //辅助线程
	}

	bool EndThread(DWORD dwWaitTime = 100)
	{
			::SetCommMask(CommHandle, 0);
			::SetEvent(_WaitOverlapped.hEvent);
			if(::WaitForSingleObject(ThreadHandle_NO1, dwWaitTime) != WAIT_OBJECT_0)
			{
			if(!::TerminateThread(ThreadHandle_NO1, 0))
			{return false;}
			}
			::CloseHandle(ThreadHandle_NO1);
			::ResetEvent(_WaitOverlapped.hEvent);
				
			::TerminateThread(ThreadHandle_NO2, 0);
			::CloseHandle(ThreadHandle_NO2);

			ThreadHandle_NO1 = NULL;
			ThreadHandle_NO2 = NULL;
			return true;
	}
private:
	 void Delay(unsigned long ulMicroSeconds)
	 {
		LARGE_INTEGER  timeStop;
		LARGE_INTEGER  timeStart;
		LARGE_INTEGER  Freq;
		ULONG  ulTimeToWait;

		if (!QueryPerformanceFrequency( &Freq ))
		return;

		ulTimeToWait = Freq.QuadPart * ulMicroSeconds / 1000 / 1000;

		QueryPerformanceCounter ( &timeStart );

		timeStop = timeStart;

		while( timeStop.QuadPart - timeStart.QuadPart < ulTimeToWait )
			{
			QueryPerformanceCounter( &timeStop );
			}
	 }

	static DWORD WINAPI  Com_Read_ThreadProc(LPVOID lpPara)
	{
	TBComm *pComm = (TBComm *)lpPara;
	if(!::SetCommMask(pComm->CommHandle, EV_RXCHAR | EV_ERR))
		return 1;

		COMSTAT Stat;
		DWORD dwError;
		unsigned long dwSize = 0;      //读取串口数据缓冲长度
		unsigned long uReadLength = 0;      //读取串口数据长度
		unsigned long dwsize=0;
        ::ClearCommError(pComm->CommHandle, &dwError, &Stat);
		for(DWORD dwLength, dwMask = 0;pComm->CommHandle!=INVALID_HANDLE_VALUE; dwMask = 0)
		{
			if(!::WaitCommEvent(pComm->CommHandle, &dwMask, &pComm->_WaitOverlapped))
			{
				if(::GetLastError() == ERROR_IO_PENDING)
				{
				 ::GetOverlappedResult(pComm->CommHandle, &pComm->_WaitOverlapped, &dwLength, true);
				}
			}
			if(dwMask & EV_ERR) // == EV_ERR
				{
				 ::ClearCommError(pComm->CommHandle, &dwError, &Stat);
				}
			if(dwMask & EV_RXCHAR) // == EV_RXCHAR
			{
			char szBuf;
			DWORD dwIncommingReadSize=0;
			::ClearCommError(pComm->CommHandle, &dwError, &Stat);
			if(Stat.cbInQue>0)
			 {
			  dwSize = 0;
			  while(Stat.cbInQue > 0)
			  {
				if(::ReadFile(pComm->CommHandle,&szBuf,1, &dwIncommingReadSize, &pComm->_ReadOverlapped))
					{
					if(dwIncommingReadSize > 0)
						{
						pComm->Command_Buf[pComm->Command_Read_Ptr][dwSize]=szBuf;
						dwSize += dwIncommingReadSize;
						if(dwSize>UART_RW_BUF)
						{
						 ::PurgeComm(pComm->CommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
						 break;
						}
						}
					}
				else
					{
					 ::PurgeComm(pComm->CommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
					 //WaitForSingleObject(pComm->_ReadOverlapped.hEvent,20);	//等待20ms
					 break;
					}
				float i=10000000/UART_BPS;		//该波特率下
											//每个字节传送时间=(1/(UART_BPS/10)*1000*1000)uS
				pComm->Delay((unsigned long)i);
			  }
			 if((dwSize>UART_RW_BUF)||(dwSize==0))
			 {
			  continue;
			 }
			 pComm->Command_Buf[pComm->Command_Read_Ptr][dwSize]='\0';
			 pComm->Command_Read_Ptr++;
			 if(pComm->Command_Read_Ptr>=max_cmd)
				{
				pComm->Command_Read_Ptr=0;																			//命令堆栈头
				}
			 pComm->Command_Num++;
		   }
		  }
		}
		return 0;
	}
	static DWORD WINAPI  Com_Work_ThreadProc(LPVOID lpPara)
	{
	TBComm *pComm = (TBComm *)lpPara;
	unsigned char *ss;
	int ss_p=0;
	while(1)
	{
	if(pComm->Command_Num>0)           //处理接收状态命令
		{//测试用
		ss=&pComm->Command_Buf[pComm->Command_Work_Ptr][0];
		ss_p=strlen(&pComm->Command_Buf[pComm->Command_Work_Ptr][0]);
		::PostMessage(pComm->SendWnd, ON_COM_RECEIVE, WPARAM((int)ss), LPARAM(ss_p));
		pComm->Command_Work_Ptr++;
		if(pComm->Command_Work_Ptr>=max_cmd)
		 {
			pComm->Command_Work_Ptr=0;																			//命令堆栈头
		 }
		pComm->Command_Num--;
		}
	Sleep(1);
	}
   }
};
#endif

⌨️ 快捷键说明

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