我想问一下,怎么监视一个被占用的串口的传输数据???包括接收的和发送的!!!写程序实现.....我暂时没有思路...
解决方案 »
- SystemParametersInfo函数的SPI_GETWORKAREA参数问题
- VC++谁做过电气监控系统?有问题请教
- 请问在使用SetWindowsHookEx安装钩子时,OpenProcess的idHook是属于什么?
- 关于udp的问题
- 1000 RMB 让你分
- 请问大虾,如何在钩子中把键盘的键值改掉?
- CMainFrame
- 一个关于cdaorecordset类的问题
- VB能调用用VC写的MFC扩展DLL吗?
- 低能儿的疑惑····
- win2000启动时候在进入第一个图形启动界面前,会有一个屏幕上显示底下很多3角的那个界面,这排三角上面还有行字:windows正在启动。
- 菜鸟问个土的关于CListBox的问题
另一个办法是编写设备驱动,因为在保护模式下可以虚拟化端口。在杨强、李堂秋编著的《Win9X 虚拟设备驱动程序编程指南》(清华大学出版社1999年出版,ISBN7-302-03324-2)有一个监视并口的例子,你可以参考。
举例:原来程序使用串口Com1连接终端。中转的时候你需要将COM1连接到COM2上,然后COM3连接到终端上。这样当COM1发送数据时,就被COM2接收到,这个时候因为COM2、COM3是你写的程序打开的,所以不管COM1中发过来什么数据,你的程序都可以记录下来,在COM2接收到数据以后直接将数据通过COM3发给终端,避免通讯超时。数据发出去以后可以将备份数据存入缓存,然后开一个线程慢慢处理。
#ifndef _MOONZWU_SUPER_SERIAL_PORT
#define _MOONZWU_SUPER_SERIAL_PORT#include <vector>
using namespace std;typedef struct WIN_ARG
{
UINT winId;
CWnd* pWin;
DWORD msg;
}WINARG, *pWINARG;
typedef vector<WIN_ARG> vWINLIST; // 窗口列表// 传输数据包
typedef struct tagPackage
{
enum emMaxSize
{ emMAX_SIZE = 1024 };
UINT iLen;
UINT iType;
BYTE pData[emMAX_SIZE]; tagPackage()
{
Clear();
} void Clear()
{
iLen = 0;
iType = 0;
ZeroMemory(pData, sizeof(*pData));
}
}PACKAGE, * pPACKAGE;class CSuperSerialPort : public CObject
{
public:
CSuperSerialPort();
virtual ~CSuperSerialPort(); //
BOOL Open(TCHAR* com,
UINT rate,
UINT parity,
BYTE dataBits,
float stopBits); //
BOOL IsOpen() { return m_bIsOpen; }
//
void Close(); //
UINT Attach(CWnd* pwin, DWORD msg);
void Detach(UINT winId);
//
BOOL SendData(pPACKAGE pPack); // 发送数据
BOOL StartReceive(LPVOID arg); // 启动接收, 参数为串口指针 //
COMSTAT* GetComState(); // 获取串口状态
HANDLE GetComHandle();// 获取串口句柄 //
ULONG GetWritedBytes() const;
ULONG GetReadedBytes() const;
// 设置输入输出缓存区
void SetInOutBuffer(DWORD inBuf, DWORD outBuf); // 获取错误信息
DWORD GetErrorCode();
const TCHAR* FormatErrorCodeToString(DWORD code);
static void SafeRelease(pPACKAGE pPack); // 释放包 typedef struct COM_ARG
{
TCHAR com[10];
HANDLE comHandle;
UINT comRate;
UINT comParity;
BYTE dataBits;
UINT stopBits; COM_ARG()
{
sprintf(com, _T("COM1"));
comHandle = INVALID_HANDLE_VALUE;
comRate = 9600;
comParity = 0;
dataBits = 8;
stopBits = 1;
}
}COMARG, *pCOMARG;
// 错误类型枚举
enum emErrorType
{
emET_SUCCEDED = 0,
emET_NO_OPEN,
emET_NO_HANDLE,
emET_OPENED,
emET_COM_UNNAMED,
emET_UNKNOW = 99
};
// 数据类型
enum emDataType
{
emDATA_TYPE_TEXT=0, emDATA_TYPE_BINARY
}; // 线程事件数量
enum emThreadEvent
{
emTHREAD_EXIT = 0,
emTHREAD_RUN = 1,
emMAX_EVENT_NUMBER = 2
};
protected:
// 接收线程
friend UINT WINAPI ReceiveThread(LPVOID pVoid);
friend void PostPackage(CSuperSerialPort* pCom, pPACKAGE pPack); BOOL WriteComm(pPACKAGE pPack);private:
COMARG m_com;
COMSTAT m_comState;
DWORD m_errorCode;
TCHAR m_errorInfo[128];
BOOL m_bIsOpen;
vWINLIST m_winList; /*------------------------------*/
OVERLAPPED m_ovReader; // Overlapped structure for ReadFile
OVERLAPPED m_ovWriter; // Overlapped structure for WriteFile
OVERLAPPED m_ovWaitEvent; // Overlapped structure for WaitCommEvent
HANDLE m_hWait;
HANDLE m_hReader;
HANDLE m_hWriter;
UINT m_nextWinId; // 返回附加的窗体Id ULONG m_WriteCount; // 已发送字节数
ULONG m_ReadCount; // 已接收字节数 HANDLE m_hEvent[emMAX_EVENT_NUMBER]; // 线程控制事件句柄
UINT m_threadId;
};
#endif
#include "stdafx.h"
#include "superSP.h"
#include <process.h>//////////////////////////////////////////////////////////////////////////
// 静态成员void CSuperSerialPort::SafeRelease(pPACKAGE pPack)
{
if (NULL != pPack)
{
delete pPack;
pPack = NULL;
}
}
// 这两个函数被设计成友元目的是可以访问类的私有变量
UINT WINAPI ReceiveThread(LPVOID pVoid)
{
long threadStatus;
DWORD dwMask, dwTrans;
DWORD dwErrFlag;
BOOL bExit = false;
CSuperSerialPort* pCom = (CSuperSerialPort *)pVoid;//
//
while (!bExit)
{
threadStatus =
WaitForMultipleObjects(CSuperSerialPort::emMAX_EVENT_NUMBER,
pCom->m_hEvent,
FALSE,
INFINITE);
threadStatus -= WAIT_OBJECT_0; if (threadStatus < 0 ||
threadStatus >= CSuperSerialPort::emMAX_EVENT_NUMBER)
{
bExit = true;
break;
}
//
// // 进行事件处理
switch (threadStatus)
{
case CSuperSerialPort::emTHREAD_EXIT:
bExit = true;
break;
//
case CSuperSerialPort::emTHREAD_RUN:
ClearCommError(pCom->GetComHandle(),
&dwErrFlag,
&pCom->m_comState); // 缓存队列中有数据
if (pCom->m_comState.cbInQue)
{
pPACKAGE pPack = new PACKAGE;
DWORD rdLen = pCom->m_comState.cbInQue;
pPack->iLen = rdLen;
// 根据长度读取指定字节到包中
if (ReadFile(pCom->GetComHandle(),
pPack->pData,
pPack->iLen,
&rdLen,
&pCom->m_ovReader))
{
// 发送包到win消息队列
pPack->iLen = rdLen;
pCom->m_ReadCount += pPack->iLen;
PostPackage(pCom, pPack);
continue;
}
} dwMask = 0;
if (!WaitCommEvent(pCom->GetComHandle(),
&dwMask,
&pCom->m_ovWaitEvent))
{
// GetLastError查找错误
DWORD errorCode = GetLastError();
if (errorCode == ERROR_IO_PENDING)
{
GetOverlappedResult(pCom->GetComHandle(),
&pCom->m_ovWaitEvent,
&dwTrans,
TRUE);
}
else // 非交叠操作,输出错误信息并退出
{
LPVOID lpMsg;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsg,
0,
NULL);
TRACE((LPCTSTR)lpMsg);
LocalFree(lpMsg);
bExit = true;
}
}
break;
default:
break;
}
}
return 0;
}void PostPackage(CSuperSerialPort* pCom, pPACKAGE pPack)
{
if (NULL != pCom)
{
vWINLIST::iterator it;
for (it = pCom->m_winList.begin();
it != pCom->m_winList.end();
it++)
{
it->pWin->PostMessage(it->msg, (WPARAM)pPack);
}
}
}
//////////////////////////////////////////////////////////////////////////
// 构造/析构CSuperSerialPort::CSuperSerialPort()
: m_nextWinId(1),
m_WriteCount(0),
m_ReadCount(0),
m_bIsOpen(false)
{
}CSuperSerialPort::~CSuperSerialPort()
{ CloseHandle(m_com.comHandle);
}//////////////////////////////////////////////////////////////////////////
// 操作控制//
// Open 函数
//
// 参数: TCHAR* com 串口名
// UINT rate 波特率
// UINT parity 校验位
// BYTE dataBits 数据位
// UINT stopBits 停止位
//
// 返回值: true 成功, false 失败
//
// 注意: 如果返回失败,请调用GetErrorCode来查找原因
//BOOL CSuperSerialPort::Open(TCHAR* com,
UINT rate,
UINT parity,
BYTE dataBits,
float stopBits)
{
m_errorCode = emET_SUCCEDED;
COMMTIMEOUTS cto = { 0, 0, 0, 0, 0}; if (NULL == com)
{
m_errorCode = emET_COM_UNNAMED;
return false;
} strcpy(m_com.com, com);
m_com.comRate = rate;
m_com.comParity = parity;
m_com.dataBits = dataBits;
if (stopBits == 1) {
stopBits = 0;
} else if (stopBits == 1.5){
stopBits = 1;
} else {
stopBits = 2;
} m_com.stopBits = stopBits;
// 串口已经打开
if (m_com.comHandle != INVALID_HANDLE_VALUE)
{
m_errorCode = emET_OPENED;
return FALSE;
} DCB dcb;
memset(&dcb, 0, sizeof(dcb));
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = m_com.comRate;
dcb.Parity = m_com.comParity;
dcb.fParity = m_com.comParity & 0; // 0&0 = 0, 1,2 & 0 = 1
dcb.StopBits = m_com.stopBits; // 0, 1, 2 = 1, 1.5, 2
dcb.ByteSize = m_com.dataBits; 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;
//
m_com.comHandle = CreateFile(m_com.com,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL); if (m_com.comHandle == INVALID_HANDLE_VALUE)
{
m_errorCode = emET_NO_OPEN;
return false;
} if (SetCommMask(m_com.comHandle, EV_RXCHAR | EV_BREAK) &&
SetCommTimeouts(m_com.comHandle, &cto) &&
SetCommState(m_com.comHandle, &dcb) &&
SetupComm(m_com.comHandle, 1024, 1024)) // 默认输入输出缓存大小
{
m_bIsOpen = true;
return true;
}
else
{
m_errorCode = emET_UNKNOW;
return false;
}
}
//
// Close 函数
//void CSuperSerialPort::Close()
{
CloseHandle(m_com.comHandle);
SetEvent(m_hEvent[emTHREAD_EXIT]);
ResetEvent(m_hEvent[emTHREAD_RUN]);
m_bIsOpen = false;
}
//
// Attach 函数
//
// 参数: CWnd* pwin 窗口指针
// DWORD msg 窗口消息
//
// 返回值: 返回一个附加到串口窗口列表的位置
//
// 注意: 窗口的附加Id(2^32)会用完,会导致程序崩溃
//
UINT CSuperSerialPort::Attach(CWnd* pwin, DWORD msg)
{
if (NULL == pwin)
{
return 0;
} WIN_ARG wa;
wa.winId = m_nextWinId++;
wa.msg = msg;
wa.pWin = pwin;
m_winList.push_back(wa); return wa.winId;
}
//
// Detach 函数
//
// 参数: UINT winId 窗口附加时的Id
//void CSuperSerialPort::Detach(UINT winId)
{
if (winId == 0 || winId >= m_nextWinId)
{
return;
} vWINLIST::iterator it;
for(it = m_winList.begin();
it != m_winList.end();
it++)
{
if (it->winId == winId)
{
m_winList.erase(it);
break;
}
}
}//
// SendData 函数
//
// 参数: pPACKAGE pPack 要发送的数据包
//
// 返回值: true 发送成, false 发送失败
//BOOL CSuperSerialPort::SendData(pPACKAGE pPack)
{
DWORD dwErrFlag;
COMSTAT comStat;
m_errorCode = emET_SUCCEDED; if (m_com.comHandle == INVALID_HANDLE_VALUE)
{
m_errorCode = emET_NO_HANDLE;
return false;
} ClearCommError(m_com.comHandle,
&dwErrFlag,
&comStat); BOOL bl;
UINT nums = 0;
UINT reserve = 0;
// 数据过大
if (pPack->iLen > pPack->emMAX_SIZE)
{
nums = pPack->iLen/pPack->emMAX_SIZE;
reserve = pPack->iLen%pPack->emMAX_SIZE;
// 分解传输
for (int i= 0; i<nums; i++)
{
PACKAGE pk;
pk.iLen = pk.emMAX_SIZE;
memcpy(pk.pData,
pPack->pData+i*pPack->emMAX_SIZE,
pPack->emMAX_SIZE*sizeof(BYTE)); bl = WriteComm(&pk);
} // 如果还有剩余的数据
if (reserve != 0)
{
PACKAGE pk;
pk.iLen = reserve;
memcpy(pk.pData,
pPack->pData+nums*pPack->emMAX_SIZE,
pPack->emMAX_SIZE*sizeof(BYTE));
bl = WriteComm(&pk);
}
}
else
{
bl = WriteComm(pPack);
}
return bl;
} BOOL CSuperSerialPort::WriteComm(pPACKAGE pPack)
{
DWORD wV;
BOOL bl; bl = WriteFile(m_com.comHandle,
pPack->pData,
pPack->iLen,
&wV,
&m_ovWriter);
if (!bl)
{
if (GetLastError() == ERROR_IO_PENDING)
{
bl = GetOverlappedResult(m_com.comHandle,
&m_ovWriter,
&wV,
TRUE);
}
}
m_WriteCount += pPack->iLen; // 统计
return bl;
}//
// StartReceive 函数
//
// 参数: LPVOID arg 传入对象,主要包含串口对象
//
// 返回值: true 启动成功, false 启动失败
//
// 注意: 传入的参数必须包含串口对象, 否则不能接收数据
//BOOL CSuperSerialPort::StartReceive(LPVOID arg)
{
m_errorCode = emET_SUCCEDED; if (NULL == arg)
{
m_errorCode = emET_NO_HANDLE;
return false;
} // 创建事件
m_hEvent[emTHREAD_EXIT] = CreateEvent(NULL, TRUE, FALSE, NULL);
m_hEvent[emTHREAD_RUN] = CreateEvent(NULL, TRUE, TRUE, NULL);
m_hReader = CreateEvent(NULL, TRUE, FALSE, NULL);
ZeroMemory(&m_ovReader, sizeof(m_ovReader));
m_ovReader.hEvent = m_hReader; m_hWriter = CreateEvent(NULL, TRUE, FALSE, NULL);
ZeroMemory(&m_ovWriter, sizeof(m_ovWriter));
m_ovWriter.hEvent = m_hWriter;
m_hWait = CreateEvent(NULL, TRUE, FALSE, NULL);
ZeroMemory(&m_ovWaitEvent, sizeof(m_ovWaitEvent));
m_ovWaitEvent.hEvent = m_hWait;
int success = _beginthreadex(NULL,
0,
ReceiveThread,
arg,
0,
&m_threadId);
if (success != 0)
{
return true;
}
else
{
return false;
}
}
//////////////////////////////////////////////////////////////////////////
// 类属性COMSTAT* CSuperSerialPort::GetComState()
{
return &m_comState;
}HANDLE CSuperSerialPort::GetComHandle()
{
return m_com.comHandle;
}void CSuperSerialPort::SetInOutBuffer(DWORD inBuf, DWORD outBuf)
{
SetupComm(m_com.comHandle, inBuf, outBuf);
}DWORD CSuperSerialPort::GetErrorCode()
{
return m_errorCode;
}ULONG CSuperSerialPort::GetWritedBytes() const
{
return m_WriteCount;
}ULONG CSuperSerialPort::GetReadedBytes() const
{
return m_ReadCount;
}
// 注意该函数
const TCHAR* CSuperSerialPort::FormatErrorCodeToString(DWORD code)
{
switch(code)
{
case emET_SUCCEDED:
sprintf(m_errorInfo, _T("操作成功!"));
break; case emET_NO_OPEN:
sprintf(m_errorInfo, _T("串口没打开"));
break; case emET_NO_HANDLE:
sprintf(m_errorInfo, _T("串口没有句柄"));
break; case emET_OPENED:
sprintf(m_errorInfo, _T("串口已经打开过"));
break; case emET_COM_UNNAMED:
sprintf(m_errorInfo, _T("串口没命名"));
break;
default:
sprintf(m_errorInfo,
_T("未定义的错误,请调用系统的GetLastError来查找"));
break;
} return m_errorInfo;
}