分享
 
 
 

串口基础类库(WIN32)ver 0.2(将以前的代码作了修改, 命名按WIN32的习惯,将多个类库合并)

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

/*

串口基础类库(WIN32) ver 0.2

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

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>

//当接受到数据送到窗口的消息

#define ON_COM_RECEIVE WM_USER + 618 // WPARAM 端口号

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(int iPort)

{

return Open(iPort, 9600);

}

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

inline bool Open(int iPort, int iBaudRate)

{

if(iPort < 1 || iPort > 1024)

return false;

SetCommPort(iPort);

if(!OpenPort())

return false;

if(!SetupPort())

return false;

return SetState(iBaudRate);

}

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

inline bool Open(int iPort, char *szSetStr)

{

if(iPort < 1 || iPort > 1024)

return false;

SetCommPort(iPort);

if(!OpenPort())

return false;

if(!SetupPort())

return false;

return SetState(szSetStr);

}

//判断串口是或打开

inline bool IsOpen()

{

return _hCommHandle != INVALID_HANDLE_VALUE;

}

//获得串口句炳

inline HANDLE GetHandle()

{

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(int iBaudRate, int iByteSize = 8, int iParity = NOPARITY, int iStopBits = ONESTOPBIT)

{

if(IsOpen())

{

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

return false;

_DCB.BaudRate = iBaudRate;

_DCB.ByteSize = iByteSize;

_DCB.Parity = iParity;

_DCB.StopBits = iStopBits;

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

}

return false;

}

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

bool SetBufferSize(int iInputSize, int iOutputSize)

{

if(IsOpen())

return ::SetupComm(_hCommHandle, iInputSize, iOutputSize);

return false;

}

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

int Read(char *szBuffer, DWORD dwBufferLength, int iWaitTime = 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 iReadLength = 0;

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

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

{

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

{

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

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

{

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

iReadLength = 0;

}

}

else

iReadLength = 0;

}

szBuffer[iReadLength] = '\0';

return iReadLength;

}

//写串口 szBuffer

int Write(char *szBuffer, int 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 int Write(char *szBuffer)

{

assert(szBuffer);

return Write(szBuffer, strlen(szBuffer));

}

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

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

{

if(!IsOpen())

return 0;

DWORD dwError;

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

::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);

va_list va;

va_start(va, szFormat);

_vsnprintf(szBuffer, dwBufferLength, szFormat, va);

va_end(va);

unsigned long uWriteLength = 0;

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

if(::GetLastError() != ERROR_IO_PENDING)

uWriteLength = 0;

return uWriteLength;

}

//关闭串口

inline virtual void Close()

{

if(IsOpen())

{

EndThread();

::CloseHandle(_hCommHandle);

_hCommHandle = INVALID_HANDLE_VALUE;

}

}

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

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

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 int _iPort; //串口号

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

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

virtual void OnReceive()

{

if(_hNotifyWnd)

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

}

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 SetCommPort(int iPort)

{

assert(iPort >= 1 || iPort <= 1024);

char p[5];

_iPort = iPort;

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

ltoa(_iPort, p, 10);

strcat(_szCommStr, p);

}

virtual bool OpenPort()

{

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;

}

private:

//监视线程

static DWORD WINAPI CommThreadProc(LPVOID lpPara)

{

cnComm *pComm = (cnComm *)lpPara;

if(!::SetCommMask(pComm->_hCommHandle, EV_RXCHAR | EV_ERR))

return 0;

COMSTAT Stat;

DWORD dwError;

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

{

if(!::WaitCommEvent(pComm->_hCommHandle, &dwMask, &pComm->_WaitOverlapped))

{

if(::GetLastError() == ERROR_IO_PENDING)

{

::GetOverlappedResult(pComm->_hCommHandle, &pComm->_WaitOverlapped, &dwLength, TRUE);

}

}

if(dwMask & EV_ERR) // == EV_ERR

::ClearCommError(pComm->_hCommHandle, &dwError, &Stat);

if(dwMask & EV_RXCHAR) // == EV_RXCHAR

{

::ClearCommError(pComm->_hCommHandle, &dwError, &Stat);

if(Stat.cbInQue > pComm->_dwNotifyNum)

pComm->OnReceive();

}

}

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- 王朝網路 版權所有