【发布时间】:2017-03-29 14:03:34
【问题描述】:
我正在调用一个通过串行端口操作 I/O 板的函数,以检查它是否在我的主类的实例中进行通信。
我知道这是有风险的,但不幸的是,这是一段已经使用了一段时间的旧代码,所以当我被要求改进它时,我无法更改功能。
如果没有通信问题,应用程序将启动,使用该功能并继续没有问题。
当 I/O 板出现通信故障时会出现问题,我发现读取功能在大多数情况下都挂起并阻止应用程序启动。有时,应用程序会加载并报告存在通信故障。
我想要实现的是每次出现通信故障时应用程序都能成功加载。
comport 最初是使用 COMMTIMEOUT 设置的,我预计当没有可读取的内容时该端口会超时。我试图改变时间,但无济于事。
我还尝试为读取函数使用线程,这样它就不会阻止启动,但它仍然挂起。
目前端口是同步设置的。
有人有什么建议吗?如果需要,我可以放一些代码示例。
Main.cpp
extern COMPort comPort;
BOOL Main::InitInstance()
{
int i = comPort.DoorLatchOff();
If(i<0) printf("Error checksum. COM port?\n");
else printf("checksum ok.\n");
}
COMPort.h
class CCOMPort
{
public:
CCOMPort (COM_PORT port = NULL_COM, DCB * state = NULL);
BOOL SetPortNumber (COM_PORT port = NULL_COM, DCB * state = NULL);
void Read(BYTE* buff, int count);
int DoorLatchOff(void);
protected:
HANDLE m_hPort;
};
static HANDLE m_hPortThreaded;
typedef struct readParam{BYTE* readBuff;int readCount;}RP, *PRP;
DWORD WINAPI ThreadedRead( LPVOID lpParam );
COMPort.cpp
CCOMPort::CCOMPort (COM_PORT port, DCB * state) : m_portNum (port), m_hPort(INVALID_HANDLE_VALUE)
{
SetPortNumber (port, state);
}
BOOL CCOMPort::SetPortNumber (COM_PORT port, DCB * state)
{
if (m_hPort != INVALID_HANDLE_VALUE){
::CloseHandle (m_hPort);
m_hPort = INVALID_HANDLE_VALUE;
}
m_portNum = port;
m_currState = m_defState;
m_originState = m_defState;
if (m_portNum != NULL_COM){
stringstream ssPortName;
ssPortName << "COM" << (m_portNum + 1) << ":" << flush;
m_hPort = ::CreateFile (ssPortName.str().c_str(),
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL);
if (m_hPort == INVALID_HANDLE_VALUE)
return FALSE;
else
{
GetState (& m_originState);
if (state)
m_currState = * state;
SetState (& m_currState);
GetCommTimeouts(m_hPort, &timeouts);
timeouts.ReadIntervalTimeout = 75; //15
timeouts.ReadTotalTimeoutMultiplier = 5; //1
timeouts.ReadTotalTimeoutConstant = 1250; //250
timeouts.WriteTotalTimeoutMultiplier = 5; //1
timeouts.WriteTotalTimeoutConstant = 1250; //250
SetCommTimeouts(m_hPort, &timeouts);
FlushOutput ();
FlushInput ();
PurgeOutput ();
PurgeInput ();
}
}
return TRUE;
}
void CCOMPort::Read(BYTE* buff, int count)
{
PRP pReadArray[1];
DWORD dwThreadArray[1];
HANDLE hThreadArray[1];
m_hPortThreaded = m_hPort;
pReadArray[0] = (PRP) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RP));
if(pReadArray[0] == NULL){
ExitProcess(2);
}
pReadArray[0]->readBuff = buff;
pReadArray[0]->readCount = count;
hThreadArray[0] = CreateThread(NULL,
0,
ThreadedRead,
pReadArray[0],
0,
&dwThreadArray[0]);
if(hThreadArray[0] == NULL){
ExitProcess(3);
}
WaitForSingleObject(hThreadArray[0],500/*INFINITE*/);
CloseHandle(hThreadArray[0]);
if(pReadArray[0] != NULL){
HeapFree(GetProcessHeap(), 0, pReadArray[0]);
pReadArray[0] = NULL;
}
}
DWORD WINAPI ThreadedRead(LPVOID lpParam)
{
BOOL bDone = FALSE, bResult;
//int buff_idx = 0;
DWORD dwCommModemStatus;
DWORD dwBytesTransfered;
PRP pReadArray;
pReadArray = (PRP)lpParam;
SetCommMask(m_hPortThreaded, EV_RXCHAR);
while(!bDone){
WaitCommEvent(m_hPortThreaded, &dwCommModemStatus, 0);
if(dwCommModemStatus == 0){
bDone = TRUE;
break;
}
if(dwCommModemStatus & EV_RXCHAR){
bResult = ReadFile(m_hPortThreaded, pReadArray[0].readBuff, pReadArray[0].readCount, &dwBytesTransfered, 0);
bDone = TRUE;
}
}
return(bResult);
}
int COMPort::DoorLatchOff(void)
{
unsigned char comm_str[10];
int chksum, chksum1;
DWORD count = 6;
WriteComm(21, 7, 0);
comm.Read(comm_str, count);
chksum = comm_str[0] + comm_str[2] + comm_str[3];
chksum1 = comm_str[4];
chksum1 = (chksum1 << 8) | comm_str[5];
if(chksum == chksum1)
return(0);
else
return(-1);
}
【问题讨论】:
标签: c++ windows serial-port c++98