|
Yes, and what is the problem ? What did you expect as output ?
|
|
|
|
|
Are you doing something like:
double d = atof("1077162803.0");
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Man who follows car will be exhausted." - Confucius
|
|
|
|
|
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.
|
|
|
|
|
Try using the a port monitor such as PortMon which will show you exactly what instructions the port is getting (rather than code showing what you think it is getting) and it will also show exatly what is being sent/received.
|
|
|
|
|
rick7423 wrote: 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.
Shouldn't then the following be set to TRUE?
dcb.fInX=FALSE;
dcb.fOutX=FALSE;
|
|
|
|
|
Yes, but when I set those state values the utility just hangs.
I am using the PORT monitor and I am starting to think that the input timeouts/buffer receive portion may be the issue. I can replicate the port settings exactly to what Hyper-terminal is doing but it appears as though the receive portion is just hanging now (open comm state acts like an application hang).
Port Monitor is a godsend, that tool is helping alot.
There are 10 kinds of people, those that understand binary and those that don't.
|
|
|
|
|
Would it help if I send you my code? It is not complete (and not if one fuction either)and may confuse the issue.
I am currently working on COM application and it should be done using "assynchronous code". Your ReadFile last parameter should point to OVELLAPED structure to do so.
FYI I have found two conflicting API descriptions of ReadFile when used for COM port. As far as I can tell you code look OK, however, I have learn that one needs to keep track of various API retrun values.
I for example check the last error of ReadFile before even looking at the return value.
Vaclav
|
|
|
|
|
Actually, yes, that would be good. I have looked at several classes found online but most were written years ago and have issues with VC2K5.
Even if your code points me in the right direction, that is good.
send to: rickr at nurserysupplies dot com
There are 10 kinds of people, those that understand binary and those that don't.
|
|
|
|
|
Could this be a problem with the WIDE characters? With the original application (Visual Studio 6), I did not use wide chars at all. This one has it turned on by default. I never thought it would cause a problem, but it may here.
Any thoughts on this?
There are 10 kinds of people, those that understand binary and those that don't.
|
|
|
|
|
By default, the VS2K5 project set the Character set to "Use Unicode Character set". Could this be part of the problem?
If so, is there any way to force the Serial Comm class to NOT be Uni-Code?
There are 10 kinds of people, those that understand binary and those that don't.
|
|
|
|
|
Could you use PortMon to logdata from your app, then look at it with DEBUG to see exactly what hex data is in there? If the data is not what you (or the receiving device) wants then yes, unicode could be a problem. Can't you disable unicode for the entire application if it's not needed?
|
|
|
|
|
I am in the process of converting to non-Unicode now, but man, it generated HUNDREDS of errors. This will take awhile to resolve.
I was hoping that it would be easier to force the data string to ANSI, but am not sure exactly how to do that.
There are 10 kinds of people, those that understand binary and those that don't.
|
|
|
|
|
Take a look at W2A() and T2A() macros and see if they might help.
|
|
|
|
|
I want to fill a structure and then print it.
How to print the values of the structue?
The structure is:
#define UINT32 unsigned int
#define INT32 int
#define UCHAR unsigned char
typedef struct CheckSumPair
{
UINT32 weakcs; // The weak, rolling Adler32 checksum.
UCHAR StrongCS[10];
};
I have dynamically allocated memory to it as folows.
CheckSumPair* CSPair = (CheckSumPair*)malloc(sizeof(CheckSumPair)*10);
for(int x = 0;x < 10;x++)
{
CSPair->weakcs = (UINT32)x+1;
strncpy((char*)CSPair->StrongCS,(char*)"XYZ",10);
strncpy((char*)CSPair->StrongCSString,(char*)"CEDVCD",10*2+1);
}
Now print the values
for(int x = 0;x < 10;x++)
printf("%d %s %s\n\n",CSPair[x]->.weakcs,CSPair[x]->StrongCS,CSPair[x]->StrongCSString);
While printing the values I get the following error:
error C2232: '->CheckSumPair::StrongCS' : left operand has 'struct' type, use '.'
error C2819: type 'CheckSumPair' does not have an overloaded member 'operator ->'
see declaration of 'CheckSumPair'
|
|
|
|
|
Try this access in your loops :
{
CheckSumPair* psTempPair = (CheckSumPair*) ((BYTE*)CSPair + sizeof(CheckSumPair) * x);
}
virtual void BeHappy() = 0;
|
|
|
|
|
Eugen Podsypalnikov wrote: CheckSumPair* psTempPair = (CheckSumPair*) ((BYTE*)CSPair + sizeof(CheckSumPair) * x);
All this casting is unnecessary and prone to error, the compiler handles pointer arithmetic automatically.
txtspeak is the realm of 9 year old children, not developers. Christian Graus
|
|
|
|
|
In this case - it is necessary,
since sizeof(CheckSumPair*) != sizeof(CheckSumPair) !
virtual void BeHappy() = 0;
|
|
|
|
|
Pointers to structures can be incremented by simple expressions thus:
CSPair++;
that is all that is needed to point to the next entry in the array.
txtspeak is the realm of 9 year old children, not developers. Christian Graus
|
|
|
|
|
|
thanks eugen for the reply
that was a typing mistake
issue is resolved by using
CheckSumpair[x].memberN;
.
.
.
since i am using [] operator to access pointer no need of using ->
|
|
|
|
|
The address CSPair[x] is a structure reference not a pointer, hence use the '.' member access operator.
txtspeak is the realm of 9 year old children, not developers. Christian Graus
|
|
|
|
|
Your code is really ugly.
rupeshkp728 wrote: #define UINT32 unsigned int
#define INT32 int
#define UCHAR unsigned char
Why do you use #define instead of typedef ?
rupeshkp728 wrote: typedef struct CheckSumPair
{
UINT32 weakcs; // The weak, rolling Adler32 checksum.
UCHAR StrongCS[10];
};
Typedef what?
rupeshkp728 wrote: CheckSumPair* CSPair = (CheckSumPair*)malloc(sizeof(CheckSumPair)*10);
Why are you using malloc? Do you really need to use C memory allocation functions?
rupeshkp728 wrote: strncpy((char*)CSPair->StrongCSString,(char*)"CEDVCD",10*2+1);
struct CheckSumPair has no StrongCSString member.
rupeshkp728 wrote: printf("%d %s %s\n\n",CSPair[x]->.weakcs,CSPair[x]->StrongCS,CSPair[x]->StrongCSString);
This is the ugliest part. What are you trying to do?
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
I think you have to print the values as follows:
for(int x = 0; x < 10; x++)
printf("%d %s %s\n\n",CSPair[x].weakcs, CSPair[x].StrongCS, CSPair[x].StrongCSString);
or
for(int x = 0; x < 10; x++)
{
printf("%d %s %s\n\n",CSPair->weakcs,CSPair->StrongCS,CSPair->StrongCSString);
CSPair++;
}
|
|
|
|
|
Don't you have a warning "warning C4091: 'typedef ' : ignored on left of 'CheckSumPair' when no variable is declared"?
Don't you have an error "error C2039: 'StrongCSString' : is not a member of 'CheckSumPair'"?
Type of CSPair[x] is CheckSumPair not CheckSumPair*, so you can't use "->", use "." instead.
Instruction "CSPair[x]->.weakcs" contains "->" and ".".
Why malloc? use the new operator instead:
CheckSumPair* CSPair = new CheckSumPair[10];
or better, if possible:
CheckSumPair CSPair[10];
And finally, you have to explain what are you trying to do with the two strncpy, maybe your code has to be like:
#define UINT32 unsigned int
#define INT32 int
#define UCHAR unsigned char
typedef struct
{
UINT32 weakcs;
UCHAR StrongCS[10 + 1];
UCHAR StrongCSString[10 + 1];
} CheckSumPair;
int main()
{
CheckSumPair CSPair[10];
for(int x = 0; x < 10; x++)
{
CSPair[x].weakcs = (UINT32)x+1;
strncpy((char*)CSPair[x].StrongCS, "XYZ", 10);
strncpy((char*)CSPair[x].StrongCSString, "CEDVCD", 10);
}
for(int x = 0; x < 10; x++)
{
printf("%d %s %s\n\n", CSPair[x].weakcs, CSPair[x].StrongCS, CSPair[x].StrongCSString);
}
return 0;
}
|
|
|
|
|
Hello Friends
While compiling 32bit code on 64 bit compiler,I came across one error is
error C2664: 'SetTimer' : cannot convert parameter 4 from 'void (__cdecl *)(HWND,UINT,UINT,DWORD)' to 'TIMERPROC'
Do u have any Ideas to resolve this?
Regards
Yogesh
|
|
|
|
|