分享
 
 
 

串口基础类库(WIN32)ver 0.3 增加的流控制和监测, 增加了监测的项目

王朝system·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

/*

串口基础类库(WIN32) ver 0.3

编译器 : BC++ 5; C++ BUILDER 4, 5, 6, X; VC++ 5, 6; VC.NET; GCC;

使用:

定义

cnComm MyComm1(false, 0);//第1个参数为是否启动监视线程, 第2个参数为阻塞(0)/异步方式(默认)

cnComm MyComm2;//默认启动监视线程, 异步

cnComm MyComm3(true);//监视线程, 阻塞

打开

MyComm1.Open(1);//1-1024 2k支持1024串口

MyComm1.Open(1, 1200);

MyComm1.Open(1, 9600);

MyComm1.Open(1, "9600,8,n,1");//可使用标准的设置字符串

MyComm1.SetBufferSize(1200, 4800)//设置缓冲区大小,可不用设置

MyComm1.SetState("9600,8,n,1")//修改波特率等

读写

MyComm1.Read(buf, 1000);

MyComm1.Write(buf, 200);

窗口句柄

MyComm1.SetWnd(hWnd);

线程控制下面都有注明就不说了

相应的处理都有对应的处理函数见ThreadFunc;

处理函数均为虚函数,为的是继承扩展;

引脚号 作用 方向

1 DCD数据载波检测 输入

2 RXD接收数据 输入

3 TXD发送数据 输出

4 DTR数据终端准备就绪 输出

5 SG信号地

6 DSR数据设备准备就绪 输入

7 RTS请求发送 输出

8 CTS清除发送 输入

9 RI振铃指示 输入

copyright(c) 2004.8 llbird wushaojian@21cn.com

*/

#ifndef _CN_COMM_H_

#define _CN_COMM_H_

#pragma warning(disable: 4530)

#pragma warning(disable: 4786)

#pragma warning(disable: 4800)

#include <assert.h>

#include <stdio.h>

#include <windows.h>

//当接受到数据送到窗口的消息 WPARAM 均为串口的端口号

#define ON_COM_RECEIVE WM_USER + 618

#define ON_COM_CTS WM_USER + 619 //LPARAM 1 为 有效, 0 为无效

#define ON_COM_DSR WM_USER + 621 //LPARAM 1 为 有效, 0 为无效

#define ON_COM_RING WM_USER + 623

#define ON_COM_RLSD WM_USER + 624

#define ON_COM_BREAK WM_USER + 625

#define ON_COM_TXEMPTY WM_USER + 626

class cnComm

{

public:

cnComm(bool fAutoBeginThread = true, DWORD dwIOMode = FILE_FLAG_OVERLAPPED)

: _dwIOMode(dwIOMode), _fAutoBeginThread(fAutoBeginThread)

{

Init();

}

virtual ~cnComm()

{

Close();

UnInit();

}

//打开串口 缺省 9600, 8, n, 1

inline bool Open(DWORD dwPort)

{

return Open(dwPort, 9600);

}

//打开串口 缺省 baud_rate, 8, n, 1

inline bool Open(DWORD dwPort, DWORD dwBaudRate)

{

if(dwPort < 1 || dwPort > 1024)

return false;

BindCommPort(dwPort);

if(!OpenCommPort())

return false;

if(!SetupPort())

return false;

return SetState(dwBaudRate);

}

//打开串口, 使用类似"9600, 8, n, 1"的设置字符串设置串口

inline bool Open(DWORD dwPort, char *szSetStr)

{

if(dwPort < 1 || dwPort > 1024)

return false;

BindCommPort(dwPort);

if(!OpenCommPort())

return false;

if(!SetupPort())

return false;

return SetState(szSetStr);

}

//判断串口是或打开

inline bool IsOpen()

{

return _hCommHandle != INVALID_HANDLE_VALUE;

}

/*--------------------------------------------------------------------------------------------------*/

//获得串口句炳

inline HANDLE GetHandle()

{

return _hCommHandle;

}

//获得串口句炳

operator HANDLE()

{

return _hCommHandle;

}

//设置串口参数:波特率,停止位,等 支持设置字符串 "9600, 8, n, 1"

bool SetState(char *szSetStr)

{

if(IsOpen())

{

if(!::GetCommState(_hCommHandle, &_DCB))

return false;

if(!::BuildCommDCB(szSetStr, &_DCB))

return false;

return ::SetCommState(_hCommHandle, &_DCB) == TRUE;

}

return false;

}

//设置串口参数:波特率,停止位

bool SetState(DWORD dwBaudRate, DWORD dwByteSize = 8, DWORD dwParity = NOPARITY, DWORD dwStopBits = ONESTOPBIT)

{

if(IsOpen())

{

if(!::GetCommState(_hCommHandle, &_DCB))

return false;

_DCB.BaudRate = dwBaudRate;

_DCB.ByteSize = (unsigned char)dwByteSize;

_DCB.Parity = (unsigned char)dwParity;

_DCB.StopBits = (unsigned char)dwStopBits;

return ::SetCommState(_hCommHandle, &_DCB) == TRUE;

}

return false;

}

//设置串口的I/O缓冲区大小

bool SetBufferSize(DWORD dwInputSize, DWORD dwOutputSize)

{

if(IsOpen())

return ::SetupComm(_hCommHandle, dwInputSize, dwOutputSize);

return false;

}

/*--------------------------------------------------------------------------------------------------*/

//读取串口 dwBufferLength - 1 个字符到 szBuffer 返回实际读到的字符数

DWORD Read(char *szBuffer, DWORD dwBufferLength, DWORD dwWaitTime = 20)

{

if(!IsOpen())

return 0;

szBuffer[0] = '\0';

COMSTAT Stat;

DWORD dwError;

if(::ClearCommError(_hCommHandle, &dwError, &Stat) && dwError > 0) //清除错误

{

::PurgeComm(_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR); /*清除输入缓冲区*/

return 0;

}

if(!Stat.cbInQue)// 缓冲区无数据

return 0;

unsigned long uReadLength = 0;

dwBufferLength = dwBufferLength - 1 > Stat.cbInQue ? Stat.cbInQue : dwBufferLength - 1;

if(!::ReadFile(_hCommHandle, szBuffer, dwBufferLength, &uReadLength, &_ReadOverlapped)) //2000 下 ReadFile 始终返回 True

{

if(::GetLastError() == ERROR_IO_PENDING) // 结束异步I/O

{

WaitForSingleObject(_ReadOverlapped.hEvent, dwWaitTime); //等待20ms

if(!::GetOverlappedResult(_hCommHandle, &_ReadOverlapped, &uReadLength, false))

{

if(::GetLastError() != ERROR_IO_INCOMPLETE)//其他错误

uReadLength = 0;

}

}

else

uReadLength = 0;

}

szBuffer[uReadLength] = '\0';

return uReadLength;

}

/*--------------------------------------------------------------------------------------------------*/

//写串口 szBuffer

DWORD Write(char *szBuffer, DWORD dwBufferLength)

{

if(!IsOpen())

return 0;

DWORD dwError;

if(::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0) //清除错误

::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);

unsigned long uWriteLength = 0;

if(!::WriteFile(_hCommHandle, szBuffer, dwBufferLength, &uWriteLength, &_WriteOverlapped))

if(::GetLastError() != ERROR_IO_PENDING)

uWriteLength = 0;

return uWriteLength;

}

//写串口 szBuffer

inline DWORD Write(char *szBuffer)

{

assert(szBuffer);

return Write(szBuffer, strlen(szBuffer));

}

//强制同步写

inline DWORD WriteSync(char *szBuffer, DWORD dwBufferLength)

{

if(!IsOpen())

return 0;

DWORD dwError;

if(::ClearCommError(_hCommHandle, &dwError, NULL) && dwError > 0) //清除错误

::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);

unsigned long uWriteLength = 0;

if(!::WriteFile(_hCommHandle, szBuffer, dwBufferLength, &uWriteLength, NULL))

if(::GetLastError() != ERROR_IO_PENDING)

uWriteLength = 0;

return uWriteLength;

}

//写串口 szBuffer 可以输出格式字符串

DWORD Write(char *szBuffer, DWORD dwBufferLength, char * szFormat, ...)

{

if(!IsOpen())

return 0;

va_list va;

va_start(va, szFormat);

_vsnprintf(szBuffer, dwBufferLength, szFormat, va);

va_end(va);

return Write(szBuffer);

}

//写串口 szBuffer 可以输出格式字符串

DWORD Write(char *szBuffer, char * szFormat, ...)

{

if(!IsOpen())

return 0;

va_list va;

va_start(va, szFormat);

vsprintf(szBuffer, szFormat, va);

va_end(va);

return Write(szBuffer);

}

/*--------------------------------------------------------------------------------------------------*/

//关闭串口

inline virtual void Close()

{

if(IsOpen())

{

EndThread();

::CloseHandle(_hCommHandle);

_hCommHandle = INVALID_HANDLE_VALUE;

}

}

/*---------------------------------------------流控制函数---------------------------------------------*/

//设置串口的DTR信号 true高电平/有效 false低电平 数据终端准备 引脚(9)4 引脚(25)20

bool SetDTR(bool OnOrOff)

{

return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR : CLRDTR) : false;

}

//设置串口的RTS信号 true高电平 false低电平 引脚(9)4 引脚(25)20

bool SetRTS(bool OnOrOff)

{

return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS : CLRRTS) : false;

}

//设置串口的字符传输状态 true终止传输 false恢复传输

bool SetBreak(bool OnOrOff)

{

return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETBREAK : CLRBREAK) : false;

}

/*-------------------------------------------辅助线程函数-----------------------------------------------*/

//设定发送通知, 接受字符最小值

inline void SetNotifyNum(int iNum)

{

_dwNotifyNum = iNum;

}

//送消息的窗口句柄

inline void SetWnd(HWND hWnd)

{

_hNotifyWnd = hWnd;

}

//辅助线程控制 建监视线程

bool BeginThread()

{

if(!IsThreadRunning())

{

_fRunFlag = true;

_hThreadHandle = NULL;

DWORD id;

_hThreadHandle = ::CreateThread(NULL, 0, CommThreadProc, this, 0, &id); //兼容98 故使用&ID

return (_hThreadHandle != NULL); //辅助线程

}

return false;

}

//线程是否运行

inline bool IsThreadRunning()

{

return _hThreadHandle != NULL;

}

//获得线程句柄

inline HANDLE GetThread()

{

return _hThreadHandle;

}

//暂停监视线程

inline bool SuspendThread()

{

return IsThreadRunning() ? ::SuspendThread(_hThreadHandle) != 0xFFFFFFFF : false;

}

//恢复监视线程

inline bool ResumeThread()

{

return IsThreadRunning() ? ::ResumeThread(_hThreadHandle) != 0xFFFFFFFF : false;

}

//终止线程

bool EndThread(DWORD dwWaitTime = 100)

{

if(IsThreadRunning())

{

_fRunFlag = false;

::SetCommMask(_hCommHandle, 0);

::SetEvent(_WaitOverlapped.hEvent);

if(::WaitForSingleObject(_hThreadHandle, dwWaitTime) != WAIT_OBJECT_0)

if(!::TerminateThread(_hThreadHandle, 0))

return false;

::CloseHandle(_hThreadHandle);

::ResetEvent(_WaitOverlapped.hEvent);

_hThreadHandle = NULL;

return true;

}

return false;

}

protected:

volatile DWORD _dwPort; //串口号

volatile HANDLE _hCommHandle;//串口句柄

char _szCommStr[20];

DCB _DCB; //波特率,停止位,等

COMMTIMEOUTS _CO; //超时结构

DWORD _dwIOMode; // 0 同步 默认 FILE_FLAG_OVERLAPPED 重叠I/O 异步

OVERLAPPED _ReadOverlapped, _WriteOverlapped; // 重叠I/O

//线程用

volatile HANDLE _hThreadHandle; //辅助线程

volatile HWND _hNotifyWnd; // 通知窗口

volatile DWORD _dwNotifyNum;//接受多少字节(>_dwNotifyNum)发送通知消息

volatile bool _fRunFlag; //线程运行循环标志

bool _fAutoBeginThread;//Open() 自动 BeginThread();

OVERLAPPED _WaitOverlapped; //WaitCommEvent use

void Init() //初始化

{

memset(_szCommStr, 0, 20);

memset(&_DCB, 0, sizeof(_DCB));

_DCB.DCBlength = sizeof(_DCB);

_hCommHandle = 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);

_dwNotifyNum = 0;

_hNotifyWnd = NULL;

_hThreadHandle = NULL;

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);

}

//绑定串口

inline void BindCommPort(DWORD dwPort)

{

assert(dwPort >= 1 && dwPort <= 1024);

char p[5];

_dwPort = dwPort;

strcpy(_szCommStr, "\\\\.\\COM");

ltoa(_dwPort, p, 10);

strcat(_szCommStr, p);

}

//打开串口

virtual bool OpenCommPort()

{

if(IsOpen())

Close();

_hCommHandle = ::CreateFile(

_szCommStr,

GENERIC_READ | GENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

FILE_ATTRIBUTE_NORMAL | _dwIOMode,

NULL

);

if(_fAutoBeginThread)

{

if(IsOpen() && BeginThread())

return true;

else

{

Close(); //创建线程失败

return false;

}

}

return IsOpen();//检测串口是否成功打开

}

//设置串口

virtual bool SetupPort()

{

if(!IsOpen())

return false;

//设置推荐缓冲区

if(!::SetupComm(_hCommHandle, 4096, 4096))

return false;

//设置超时时间

if(!::GetCommTimeouts(_hCommHandle, &_CO))

return false;

_CO.ReadIntervalTimeout = 0xFFFFFFFF;

_CO.ReadTotalTimeoutMultiplier = 0;

_CO.ReadTotalTimeoutConstant = 0;

_CO.WriteTotalTimeoutMultiplier = 0;

_CO.WriteTotalTimeoutConstant = 2000;

if(!::SetCommTimeouts(_hCommHandle, &_CO))

return false;

//清空串口缓冲区

if(!::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))

return false;

return true;

}

/*---------------------------------------线程监视处理-----------------------------------------------------*/

//线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含窗口编号

virtual void OnReceive()//EV_RXCHAR

{

if(_hNotifyWnd)

::PostMessage(_hNotifyWnd, ON_COM_RECEIVE, WPARAM(_dwPort), LPARAM(0));

}

//获得串口的DSR信号处理

virtual void OnDSR()

{

if(_hNotifyWnd)

{

DWORD Status;

if(GetCommModemStatus(_hCommHandle, &Status))

::PostMessage(_hNotifyWnd, ON_COM_DSR, WPARAM(_dwPort), LPARAM( (Status & MS_DSR_ON) ? 1 : 0));

}

}

//获得串口的CTS信号处理

virtual void OnCTS()

{

if(_hNotifyWnd)

{

DWORD Status;

if(GetCommModemStatus(_hCommHandle, &Status))

::PostMessage(_hNotifyWnd, ON_COM_CTS, WPARAM(_dwPort), LPARAM( (Status & MS_CTS_ON) ? 1 : 0));

}

}

//获得串口字符传输状态终止传输处理

virtual void OnBreak()

{

if(_hNotifyWnd)

::PostMessage(_hNotifyWnd, ON_COM_BREAK , WPARAM(_dwPort), LPARAM(0));

}

//获得串口输出完毕信号处理

virtual void OnTXEmpty()

{

if(_hNotifyWnd)

::PostMessage(_hNotifyWnd, ON_COM_TXEMPTY, WPARAM(_dwPort), LPARAM(0));

}

//错误处理

virtual void OnError()

{

COMSTAT Stat;

DWORD dwError;

::ClearCommError(_hCommHandle, &dwError, NULL);

}

//振玲处理

virtual void OnRing()

{

if(_hNotifyWnd)

::PostMessage(_hNotifyWnd, ON_COM_RING, WPARAM(_dwPort), LPARAM(0));

}

//RLSD信号处理

virtual void OnRLSD()

{

if(_hNotifyWnd)

::PostMessage(_hNotifyWnd, ON_COM_RLSD, WPARAM(_dwPort), LPARAM(0));

}

//可扩展的线程工作函数

virtual void ThreadFunc()

{

if(!::SetCommMask(_hCommHandle, EV_RXCHAR | EV_ERR | EV_CTS | EV_DSR | EV_BREAK | EV_TXEMPTY | EV_RING | EV_RLSD))

MessageBox(NULL, "设置监视事件失败, 线程工作无效", "cnComm Class", MB_OK);

COMSTAT Stat;

DWORD dwError;

for(DWORD dwLength, dwMask = 0; _fRunFlag && IsOpen(); dwMask = 0)

{

if(!::WaitCommEvent(_hCommHandle, &dwMask, &_WaitOverlapped))

{

if(::GetLastError() == ERROR_IO_PENDING)//用于异步

::GetOverlappedResult(_hCommHandle, &_WaitOverlapped, &dwLength, TRUE);

else

continue;

}

switch(dwMask)

{

case EV_RXCHAR :

::ClearCommError(_hCommHandle, &dwError, &Stat);

if(Stat.cbInQue > _dwNotifyNum)

OnReceive();

break;

case EV_TXEMPTY :

OnTXEmpty();

break;

case EV_CTS :

OnCTS();

break;

case EV_DSR :

OnDSR();

break;

case EV_RING :

OnRing();

break;

case EV_RLSD :

OnRLSD();

break;

case EV_BREAK:

OnBreak();

break;

case EV_ERR :

OnError();

break;

}//case

}//for

}

private:

//监视线程

static DWORD WINAPI CommThreadProc(LPVOID lpPara)

{

cnComm *pComm = (cnComm *)lpPara;

pComm->ThreadFunc();

return 0;

}

};

#endif //_CN_COMM_H_

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有