📄 com.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 + -