Unfortunately, I have a project where I need to use the serial port to communicate with an older device on our shop floor. I have a SERIALIO class that used to work with VC 6, but now when I try to use it with VS 2K5 it does not seem to work anymore and I cannot figure out why. I am assuming that the issue is with how the port is being initialized, because the device is not always getting a signal. I can determine this by watching the communications LED on the device itself.
Essentially, the process is to
1. Initialize the port
2. Send data string to device (*ID-)
3. get response from device (coded in a timeout function so that if the process takes more than 5S, will return TIMEOUT string)
4. Process the return string
What is happening is that device is either returning "ER" or the function will return "TIMEOUT". The "ER" means that the device does recognize the command sent.
When I use Hyper-Terminal and set the properties to 4800, n,8,1,Flow Control to use XON/XOFF, I get response every time. But, the following code fails and I am lost. Can anyone help?
(Sorry for the lengthy code to follow)
Here is my configuration script to initialize the serial port:
<br />
SerialIO::SerialIO( LPCWSTR port,<br />
long baud,<br />
LPCSTR parity,<br />
long data,<br />
long stop){<br />
USES_CONVERSION;<br />
char initstr[256];<br />
char errmsg[256];<br />
COMMTIMEOUTS timeouts;<br />
bf="";<br />
buffer[0]='\0';<br />
DCB dcb={0};<br />
<br />
<br />
sprintf_s(initstr,"baud=%ld parity=%s data=%ld stop=%ld",<br />
baud,parity,data,stop);<br />
idCommDev=CreateFileW( port,<br />
GENERIC_READ|GENERIC_WRITE,<br />
0,<br />
NULL,<br />
OPEN_EXISTING,<br />
0,<br />
NULL);<br />
<br />
if(idCommDev!=INVALID_HANDLE_VALUE) {<br />
if(baud){<br />
SecureZeroMemory(&dcb, sizeof(DCB));<br />
dcb.DCBlength = sizeof(DCB);<br />
if(GetCommState(idCommDev, &dcb))<br />
{<br />
dcb.BaudRate = CBR_4800;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.fInX=FALSE;<br />
dcb.fOutX=FALSE; <br />
dcb.fOutxCtsFlow=FALSE; <br />
dcb.fRtsControl=RTS_CONTROL_DISABLE;<br />
dcb.fOutxDsrFlow=FALSE;<br />
if(!SetCommState(idCommDev, &dcb))<br />
{<br />
CString lpMsgBuf;<br />
char lpDisplayBuf[512];<br />
DWORD dw = GetLastError(); <br />
FormatMessage(<br />
FORMAT_MESSAGE_ALLOCATE_BUFFER | <br />
FORMAT_MESSAGE_FROM_SYSTEM |<br />
FORMAT_MESSAGE_IGNORE_INSERTS,<br />
NULL,<br />
dw,<br />
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),<br />
(LPTSTR) &lpMsgBuf,<br />
0, NULL );<br />
sprintf_s(lpDisplayBuf, "SetCommState failed with error:\r\n(%d): %s",dw,W2A(lpMsgBuf));<br />
MessageBoxW(NULL, A2W(lpDisplayBuf), L"Error", MB_OK); <br />
}<br />
if(!GetCommState(idCommDev, &dcb))<br />
{<br />
CString lpMsgBuf;<br />
char lpDisplayBuf[512];<br />
DWORD dw = GetLastError(); <br />
FormatMessage(<br />
FORMAT_MESSAGE_ALLOCATE_BUFFER | <br />
FORMAT_MESSAGE_FROM_SYSTEM |<br />
FORMAT_MESSAGE_IGNORE_INSERTS,<br />
NULL,<br />
dw,<br />
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),<br />
(LPTSTR) &lpMsgBuf,<br />
0, NULL );<br />
sprintf_s(lpDisplayBuf, "GetCommState after SetCommState with error:\r\n(%d): %s",dw,W2A(lpMsgBuf));<br />
MessageBoxW(NULL, A2W(lpDisplayBuf), L"Error", MB_OK); <br />
}<br />
}<br />
else<br />
{<br />
CString lpMsgBuf;<br />
char lpDisplayBuf[512];<br />
DWORD dw = GetLastError(); <br />
FormatMessage(<br />
FORMAT_MESSAGE_ALLOCATE_BUFFER | <br />
FORMAT_MESSAGE_FROM_SYSTEM |<br />
FORMAT_MESSAGE_IGNORE_INSERTS,<br />
NULL,<br />
dw,<br />
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),<br />
(LPTSTR) &lpMsgBuf,<br />
0, NULL );<br />
sprintf_s(lpDisplayBuf, "GetCommState (Initial) failed with error:\r\n (%d): %s",dw,W2A(lpMsgBuf));<br />
MessageBoxW(NULL, A2W(lpDisplayBuf), L"Error", MB_OK); <br />
}<br />
}<br />
<br />
SetupComm(idCommDev,(DWORD)1600,(DWORD)1600);<br />
timeouts.ReadIntervalTimeout=MAXDWORD;<br />
timeouts.ReadTotalTimeoutMultiplier=MAXDWORD;<br />
timeouts.ReadTotalTimeoutConstant=10000;<br />
timeouts.WriteTotalTimeoutMultiplier=0;<br />
timeouts.ReadTotalTimeoutConstant=0;<br />
SetCommTimeouts(idCommDev,&timeouts);<br />
ReadMutex=NULL;<br />
}<br />
else {<br />
CString lpMsgBuf;<br />
char lpDisplayBuf[512];<br />
DWORD dw = GetLastError(); <br />
FormatMessage(<br />
FORMAT_MESSAGE_ALLOCATE_BUFFER | <br />
FORMAT_MESSAGE_FROM_SYSTEM |<br />
FORMAT_MESSAGE_IGNORE_INSERTS,<br />
NULL,<br />
dw,<br />
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),<br />
(LPTSTR) &lpMsgBuf,<br />
0, NULL );<br />
sprintf_s(lpDisplayBuf, "Error Creating SERIALIO Comm Object with error:\r\n (%d): %s",dw,W2A(lpMsgBuf));<br />
MessageBoxW(NULL, A2W(lpDisplayBuf), L"Error", MB_OK); <br />
}<br />
}<br />
When I send a data packet to the device, I am expecting to receive the response immediately. So, I have a function called SendForResponce, which is as follows:
<br />
LPCSTR SerialIO::SendforResponse(LPCSTR outstr,<br />
char abortc,<br />
DWORD Timeout,<br />
DWORD ch_delay){<br />
DWORD count,mask;<br />
char c='\0';<br />
int i, canceled=0;<br />
DWORD cTime=GetTickCount();
COMMTIMEOUTS timeouts,oldtimeouts;<br />
DWORD pauset;<br />
if(abortc!='\0'){<br />
dcb.EvtChar=abortc;<br />
SetCommState(idCommDev,&dcb);<br />
mask=EV_RXCHAR|EV_RXFLAG;<br />
}<br />
else {mask=EV_RXCHAR;}<br />
SetCommMask(idCommDev,mask);<br />
GetCommTimeouts(idCommDev,&oldtimeouts);<br />
timeouts=oldtimeouts;<br />
timeouts.ReadIntervalTimeout=0;<br />
timeouts.ReadTotalTimeoutMultiplier=0;<br />
timeouts.ReadTotalTimeoutConstant=Timeout;<br />
SetCommTimeouts(idCommDev,&timeouts);<br />
<br />
PurgeComm(idCommDev,PURGE_RXCLEAR|PURGE_TXCLEAR);<br />
buffer[0]='\0';<br />
if(strlen(outstr)){<br />
if(ch_delay){<br />
for(i=0;(unsigned)i<strlen(outstr) && !canceled;i++){<br />
pauset=GetTickCount();<br />
if(!WriteFile(idCommDev,(LPCVOID)(&(outstr[i])),(DWORD)1L, &count,NULL)){ <br />
canceled=1;<br />
}<br />
while((GetTickCount()-pauset)<ch_delay);
}<br />
}<br />
else if(!WriteFile(idCommDev,(LPCVOID )outstr,(DWORD)strlen(outstr), &count,NULL)){canceled=1;}<br />
if(!canceled && (GetTickCount()-cTime)<Timeout){<br />
for(i=0;c!='\r' && c!='\n' && c!=abortc;i++){<br />
if(!ReadFile(idCommDev,&c,1,&count,NULL)){MessageBoxW(NULL,(LPCTSTR)"SERIALIO Read Failed",(LPCTSTR)"Debug",MB_OK);;}<br />
else{<br />
if((GetTickCount()-cTime)>=Timeout){<br />
strcpy_s(buffer,TIMEOUT_STR);<br />
c=abortc;<br />
}<br />
else if(c==abortc){<br />
buffer[0]='\0';<br />
canceled=1;<br />
}<br />
else if((int)c==8 && i>0){<br />
i-=2;<br />
buffer[i+1]='\0';<br />
}<br />
else if(c!='\r' && c!='\n'){<br />
buffer[i]=c;<br />
buffer[i+1]='\0';<br />
}<br />
}<br />
}
}
}
else {<br />
if(canceled){PurgeComm(idCommDev,PURGE_RXCLEAR);}<br />
SetCommTimeouts(idCommDev,&oldtimeouts);<br />
return buffer;<br />
}<br />
There are 10 kinds of people, those that understand binary and those that don't.
|