自己写的 C++ 串口通讯类,希望大家帮忙指正!自己使用过,能行!但感觉非常不好。。。。。

jackew 2010-11-08 06:22:05

//---------------------------------------------------------------------------

#ifndef _MscommH_H
#define _MscommH_H
//---------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h>
#include <string.h>

#define WM_COMM_RXCHAR WM_USER + 10 //自定义串口接收数据消息

class Mscomm
{
private:
HWND wHand; //主窗口句柄
HANDLE hThread; //线程句柄
HANDLE hComm; //串口句柄
bool IsOpen; //记录串口是否打开
bool ThreadFlag; //线程开关标记

OVERLAPPED WriteovReady,ReadovReady; //读写异步结构,用来保存异步操作结果

//以 Delimit 为分隔符拆分字符串 Str 到字符数组 S 中
// void SplitStr(String *S,String Str, char Delimit);


protected:
COMSTAT lpStat;
DWORD dwError;

DWORD GetInBufferCount()
{
dwError = 0;
lpStat.cbInQue = 0;
ClearCommError(hComm,&dwError,&lpStat);
return lpStat.cbInQue ;
}
void SetInBufferCount(int InBuf)
{
if(!InBuf)
PurgeComm(hComm, PURGE_RXCLEAR);
}

DWORD GetOutBufferCount()
{
dwError = 0;
lpStat.cbOutQue = 0;
ClearCommError(hComm,&dwError,&lpStat);
return lpStat.cbOutQue ;
}

void SetOutBufferCount(int OutBuf)
{
if(!OutBuf)
PurgeComm(hComm, PURGE_TXCLEAR);
}


void SetRThreshold(bool RTh) //线程开启和挂起函数
{

if((!this->ThreadFlag) && RTh)
{
ResumeThread(hThread);
}
if(this->ThreadFlag && !RTh)
{
SuspendThread(hThread);
}

this->ThreadFlag = RTh;

}

// bool GetRThreshold(void){return ThreadFlag;}

/***********************线程函数**********************/
static DWORD WaitThread(void *lp)
{
DWORD dwEventMask = 0; // 发生的事件
DWORD TempCount1 = 0;
DWORD TempCount2 = 0;
bool tFlag = FALSE;
OVERLAPPED Watch;
// HANDLE hEvent;
Mscomm *This = (Mscomm*)lp;

memset(&Watch,0,sizeof(Watch));
// 创建一个人工重设
Watch.hEvent = CreateEvent(NULL,FALSE,FALSE,"WatchEvent");

while(This->ThreadFlag)
{

if(WaitCommEvent(This->hComm,&dwEventMask,&Watch));
{
if(dwEventMask == EV_RXCHAR)
{

if(This->InBufferCount != 0)
{
SendMessage(This->wHand ,WM_COMM_RXCHAR,0,0);
dwEventMask = 0;
// while(This->InBufferCount != 0);
}
}
}

}

return 0;
}

//===============线程退出===============
void ExitThread()
{


if(ThreadFlag)
{
ThreadFlag = FALSE;
WaitForSingleObject(hThread,INFINITE);
}


CloseHandle(hThread);

}


public:
// int mPort; //端口号

//设置并返回接收缓冲区的字节数
// __property int InBufferSize = {write=SetInBufferSize};

//以字节的形式设置并返回传输缓冲区的大小
// __property int OutBufferSize = {write=SetOutBufferSize};

Mscomm(HWND hand = NULL);

virtual ~Mscomm();

bool OpenComm(int Port); //打开串口
void CloseComm(); //关闭打开的串口
bool CommSetting(char* Setting); //串口设置
bool RedComm(unsigned char* ReadData, //读串口数据
DWORD ReadCount=1);
bool WriteComm(char* Send); //发送数据到串口


__property DWORD InBufferCount = {read=GetInBufferCount,write=SetInBufferCount};
__property DWORD OutBufferCount = {read=GetOutBufferCount,write=SetOutBufferCount};


__property bool RThreshold = {write=SetRThreshold};

//__published:

};


#endif
...全文
400 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
helloCr7Win 2013-06-05
  • 打赏
  • 举报
回复
写的不错啊,楼主耍人?
jackew 2010-11-12
  • 打赏
  • 举报
回复
谢谢!我去找找看!
CppFile 2010-11-11
  • 打赏
  • 举报
回复
楼主搜索cncomm,这个串口类据说是跨平台的,可以在windows,linux,wince上用的
jackew 2010-11-11
  • 打赏
  • 举报
回复
类名是随便取的,本来我想使用MSCOMM32的控件,但死活加不进C++ Builder 2010 .......
所以一气之下自己试着写了个!

我这个类的确需要提供一个窗口句柄,更灵活复杂的类我更写不出来了.....所以希望大家多多指教!或者帮忙提供一个详细的学习资料。
xjq2003 2010-11-10
  • 打赏
  • 举报
回复
[Quote=引用楼主 jackew 的回复:]

//---------------------------------------------------------------------------

#ifndef _MscommH_H
#define _MscommH_H
//--------------------------------------------------------……
[/Quote]挺好的,
你感觉哪里不好啊
CppFile 2010-11-10
  • 打赏
  • 举报
回复
楼主这个类是自己写的,为啥起名叫ms呢?

楼主的类只能在有窗口的程序中运行?无法在线程中运行?构造函数要求提供一个窗口句柄。

tomrxjh 2010-11-10
  • 打赏
  • 举报
回复
很好,只是有点考验人的耐性。
周药师 2010-11-10
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 jackew 的回复:]

我感觉线程处理部分很不好!!!!但不知道具体该怎样做才正确......希望各位大侠拔刀相助~~~~~
[/Quote]
找一些开源的代码 去参考下
jackew 2010-11-10
  • 打赏
  • 举报
回复
我感觉线程处理部分很不好!!!!但不知道具体该怎样做才正确......希望各位大侠拔刀相助~~~~~
laowang2 2010-11-09
  • 打赏
  • 举报
回复
你写的很好。
Metrosexual 2010-11-09
  • 打赏
  • 举报
回复
可以啊。。。
我不懂电脑 2010-11-09
  • 打赏
  • 举报
回复
实现了,就很好啊。
HKCID 2010-11-08
  • 打赏
  • 举报
回复

不错。
jackew 2010-11-08
  • 打赏
  • 举报
回复

//========Mscomm.CPP============

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include "Mscomm.h"
#pragma hdrstop
//---------------------------------------------------------------------------




/****************************************************************************


构造函数


*****************************************************************************/
Mscomm::Mscomm(HWND hand)
{
IsOpen = FALSE;
hComm = 0;
hThread = NULL;
ThreadFlag = FALSE;

wHand = hand; //获得所使用这个类的主窗口的句柄

}


/****************************************************************************


析构函数


*****************************************************************************/
Mscomm::~Mscomm()
{
this->CloseComm();
}


/****************************************************************************


打开串口


*****************************************************************************/
bool Mscomm::OpenComm(int Port)
{
char CommPort[10];
COMMTIMEOUTS Timeout;


if(IsOpen) //如果串口打开状态
{
MessageBox(NULL,"串口处于打开状态","",MB_OK);
this->CloseComm();
IsOpen = FALSE;
}
memset(&CommPort,0,sizeof(CommPort));
sprintf(CommPort,"COM%d",Port);

hComm = CreateFile( CommPort, //串口号
GENERIC_READ|GENERIC_WRITE, //允许读写
0, //通讯设备必须以独占方式打开
NULL, //无安全属性
OPEN_EXISTING, //通讯设备已存在
FILE_FLAG_OVERLAPPED, //异步I/O
NULL); //通讯设备不能用模板打开

if(hComm == INVALID_HANDLE_VALUE)
{
MessageBox(NULL,"串口已打开或不存在","打开通信端口错误!!",MB_OK|MB_ICONERROR);
return FALSE;
}


/*---------------------- 设置超时 ----------------------*/

Timeout.ReadIntervalTimeout = MAXDWORD;
Timeout.ReadTotalTimeoutMultiplier = 0;
Timeout.ReadTotalTimeoutConstant = 0;
Timeout.WriteTotalTimeoutMultiplier = 0;
Timeout.WriteTotalTimeoutConstant = 0;

if (!SetCommTimeouts(hComm,&Timeout))
return FALSE;

//清零读写异步结构
memset(&ReadovReady,0,sizeof(OVERLAPPED));
memset(&WriteovReady,0,sizeof(OVERLAPPED));

//创建读写异步事件
ReadovReady.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
WriteovReady.hEvent =CreateEvent(NULL,TRUE,FALSE,NULL);

//监视串口中有无数据
SetCommMask(hComm,EV_RXCHAR);

//&&&&&&&&&&&&&&开线程&&&&&&&&&&&&&

hThread = CreateThread(NULL,
0,
(LPTHREAD_START_ROUTINE)WaitThread,
(void*)this,
CREATE_SUSPENDED , //线程挂起
NULL );

IsOpen = TRUE;
return IsOpen;
}


/****************************************************************************


关闭串口


*****************************************************************************/
void Mscomm::CloseComm()
{
IsOpen = FALSE;
CloseHandle(hComm);
hComm = NULL;

this->ExitThread();

CloseHandle(ReadovReady.hEvent);
// CloseHandle(WriteovReady.hEvent );
ReadovReady.hEvent =NULL;
WriteovReady.hEvent =NULL;

}


/****************************************************************************


配置串口参数


*****************************************************************************/

bool Mscomm::CommSetting(char* Setting)
{
DCB dcb;

memset(&dcb,0,sizeof(dcb));
if(!GetCommState(hComm,&dcb))//获取当前DCB配置

return FALSE;


/******************************************************************
//// set DCB to configure the serial port
//
// dcb.DCBlength = sizeof(dcb);
/// ---------- Serial Port Config -------
//
// dcb.BaudRate = rate;
//
// dcb.Parity = parity;
//
// dcb.fParity = 0;
//
// dcb.StopBits = stopBits; //ONESTOPBIT;
//
// dcb.ByteSize = byteSize;
//
// dcb.fOutxCtsFlow = 0;
//
// dcb.fOutxDsrFlow = 0;
//
// dcb.fDtrControl = DTR_CONTROL_DISABLE;
//
// dcb.fDsrSensitivity = 0;
//
// dcb.fRtsControl = RTS_CONTROL_DISABLE;
//
// dcb.fOutX = 0;
//
// dcb.fInX = 0;
//
//// ----------------- misc parameters -----
//
// dcb.fErrorChar = 0;
//
// dcb.fBinary = 1;
//
// dcb.fNull = 0;
//
// dcb.fAbortOnError = 0;
//
// dcb.wReserved = 0;
//
// dcb.XonLim = 2;
//
// dcb.XoffLim = 4;
//
// dcb.XonChar = 0x13;
//
// dcb.XoffChar = 0x19;
//
// dcb.EvtChar = 0;
//*******************************************************************/

BuildCommDCB(Setting,&dcb);

// set DCB
if (!SetCommState(hComm,&dcb))
{
MessageBox(NULL,"通信端口设置错误!!!","Set Error",MB_OK|MB_ICONSTOP);
return FALSE;
}

if (!SetupComm(hComm,1024,512))
return FALSE;
return TRUE;
}


/****************************************************************************


串口发送数据


*****************************************************************************/
bool Mscomm::WriteComm(char* Send)
{

DWORD BytesSent=0;
DWORD sendsize=0;
DWORD RecD;

if (!IsOpen)
return FALSE;

//清除串口的所有操作
PurgeComm(hComm, PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);

WriteovReady.Offset = 0;
WriteovReady.OffsetHigh = 0;

sendsize = strlen(Send);

bool hand = WriteFile(hComm, // 串口句柄
Send, // 指向待写入数据的首地址
sendsize, // 待写入数据的长度
&BytesSent, // 函数返回的实际写入串口的数据个数的地址
&WriteovReady); // 重叠I/O结构的指针


if (!hand)
{
if(GetLastError() != ERROR_IO_PENDING)
{
return FALSE;
}

else
{
//当指定的对象处于有信号状态或者等待时间结束的状态时,此函数返回
RecD = WaitForSingleObject(WriteovReady.hEvent,INFINITE);
}

if (RecD == WAIT_OBJECT_0)
{
//判断一个重叠操作当前的状态
if(!GetOverlappedResult(hComm,&WriteovReady,&BytesSent,FALSE))
return FALSE;
else
return TRUE;
}
else
return FALSE;
}


return TRUE;
}





/****************************************************************************


串口接收数据


*****************************************************************************/
bool Mscomm::RedComm(unsigned char* ReadData,DWORD ReadCount) //读串口数据
{
unsigned int i;
DWORD ReadLen=0;
unsigned char *Buf;
DWORD m=0;

if(!IsOpen)
return FALSE;
if(ReadovReady.hEvent == NULL)
return FALSE;
while(this->InBufferCount < ReadCount) //获得输入缓冲区的字节数
{
m++;
if(m == 200000)
{
m = 0;
MessageBox(NULL,"串口缓冲区无数据","接收数据错误",
MB_OK|MB_ICONERROR);
return FALSE;
}
}


Buf = new unsigned char[ReadCount];

if(!ReadFile(hComm, // 串口句柄
Buf, // 指向被读出数据的首地址
ReadCount, // 需读出的字节数
&ReadLen, // 指向实际读到的字节数
&ReadovReady) // 指向一个异步I/O结构
)
{
if (GetLastError() != ERROR_IO_PENDING)
return FALSE;
}

if(ReadLen == 0)
return false;


DWORD dwRead = 0;
const int READ_TIMEOUT = 500;
DWORD dwRes = WaitForSingleObject(ReadovReady.hEvent, READ_TIMEOUT);
switch(dwRes)
{
case WAIT_OBJECT_0:
if (!GetOverlappedResult(hComm, &ReadovReady, &dwRead, FALSE))
return FALSE;
break;

case WAIT_TIMEOUT:
MessageBox(NULL,"读取数据超时!","通讯错误",MB_OK|MB_ICONWARNING);
break;

default:
break;
}



for (i = 0; i < ReadCount; i++)
{
ReadData[i] = Buf[i];
}

delete[] Buf;

return TRUE;

}

#pragma package(smart_init)

1,221

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧