Hello Scott and everyone else who will read this post.

After many messages that I posted on the news groups about rs232, I have
come up with functional code which reads in as many as 25 characters in one
operation, meaning that a micro-controller can send 25 bytes to the PC and
VC++ has no problem reading this. The code can be altered to read many more
bytes than 25 if required, however I only tested up to 25. All you need to do
is to change the first defined statement > BYTESTOREAD!

Scott, I have learnt a lot form our exchage of posts, so I figure I would
like to share with you, what I have come up with, and I would appreciate your
opinion â?¦ However, I know that the code can probably be made more efficient,
however I think, for me, for now, its quite okay!

This is not the way I will leave the code, there will be some final touches
such as better placement of #define statements and so forth!

I will put comments under every line of code, so if you disagree with the
commentary feel free to correct it.

//////////////////////////////////////////////////////////////////////
#include <windows.h>

CSerialWnd MySerial;
//Create an object of Cserial type.

LRESULT CALLBACK WndProc_CW1 (HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{

//RS232 *Receive mode

#define BYTESTOREAD 25 //Depicts the amount of bytes to read!
#define OB_BYTES ((BYTESTOREAD*2)+1) //Number of bytes for official Buffer !

static DWORD dwBytesRead;
//Declaration of variable to indicate actual bytes that are
//read in within the time limit that windows allowed!

static byte CatchByte_BUFFER[BYTESTOREAD+1];
//Bytes returned from the MySerial.Read() function, will be
//immediatelly assigned to this array.

static byte Accum_BUFFER[BYTESTOREAD+1];
//Since windows cannot assure a constant amount of bytes
//returned from the MySerial.Read() function(which come
// from the rs232 port), then when CatchByteBUFFER
//is full, I transfer its bytes to the Accum_BUFFER. So
//now, CatchByteBUFFER is ready for another, set of bytes
//returned from the next MySerial.Read() function.
static TCHAR Official_BUFFER[OB_BYTES];
//This array holds the final and complete string that was read
in .

int k,n,j;
//General purpose variables used to loop and index arrays


//RS232 SERIAL PORT MONITOR
if (message == CSerialWnd::mg_nDefaultComMsg)
{
const CSerialWnd::EEvent eEvent = SerialWnd::EEvent(LOWORD(wParam));
const CSerialWnd::EError eError = CSerialWnd::EError(HIWORD(wParam));

switch (eEvent)
{
case CSerialWnd::EEventRecv:
// A serial message occurred
j = 0;
//Holds Accumulative array index value

do
{
MySerial.Read(CatchByte_BUFFER,
sizeof(CatchByte_BUFFER),
&dwBytesRead);
//Read the port, and the third parameter
//will hold the amount of bytes read in!

CatchByte_BUFFER[dwBytesRead] = '\0';
//Null Terminate the CatchByte_BUFFER array!

n = dwBytesRead;
//Re-assign the amount of bytes read in to another
variableâ?¦
//The reason for this was that I would get the
following error, if I
//were to put this variable straight into the for
loop command:
//c:\_DTS_PROGRAMMING\C_PROGRAMMING\vc++\MY_APPS_LAB
// \XPPLC\WndProc_CW1.cpp(220) : warning C4018: '<' :
//signed/unsigned mismatch.
//So for now, I just re-assigned it!

for(k=0;k<n;k++)
{
Accum_BUFFER[k+j] = CatchByte_BUFFER[k];
//Store the bytes that were just read in into an
//accummulator array!
}

j = j + dwBytesRead;
//Advance the index for the Accum_BUFFER array
//so we can append the next bytes which reside in the
//CatchByte_BUFFER array in the next iteration!
}
while(j != (BYTESTOREAD) && j != 0);
//If all the bytes were read in, then , j will
be equal to
//BYTESTOREAD and will break out of the while
loop, and
//also, for unneccessary subsequent port reads
where
//dwBytesRead will equal to 0, meaning that no
bytes were
//read, then this will cause the breaking out
//of the while loop aswell!


MultiByteToWideChar(CP_ACP,0, (LPCSTR)Accum_BUFFER,-1,Official_BUFFER,OB_BYTES);
//Finally, assign the fully accumulated bytes
//to a TCHAR string array, which are
converted
//to unicode, if I am not mistaken!
break;
default:
break;
}
return 0;
}


switch(message)
{
case WM_CREATE:
MySerial.Open(TEXT("COM1"),hwnd,WM_NULL,lParam,0,0);
//Open the rs232 port

MySerial.Setup(CSerial::EBaud9600,CSerial::EData8,
CSerial::EParNone,CSerial::EStop1);
//Set up the rs232 port
return 0;

case WM_CLOSE:
MySerial.Close(); //Close Port!
break;
return 0;
}

return DefWindowProc(hwnd, message,wParam,lParam);
}

/////////////////////////////////////////////////////////////////////////////////////////////

The above code has been extensively tested, many times and has never failed.
After spending many hours on the subject, I thought I could shine some light
on rs232 in a laymens kind of way, I know for many of you, this is probably
unworthy of your time or knowledge, however, if I would of have had this type
of post 3 months ago, it really would of made the rs232 implementation curve
a lot simpler for me! I invite anyone that is a beginer and finds rs232
complicated just as I did, (and still do! Because I am sure there is much
more to this) to use it and improve upon it!

I have one question though! What is the advantage of using the Wndserial
class as opposed to using functions like CreateFile, WriteFile, ReadFile, and
CloseHandle.

Would I be better off, or is it because in Windows it would be too
complicated!
Just asking!

I thank Scott and all members of the news groups that have helped me on the
subject!

You guys, are a great resource on the subjects of C,C++,VC++.

--
Best regards
Robert

Re: rs232... by Stuart

Stuart
Fri Sep 22 04:18:39 CDT 2006

Robby wrote:
> Hello Scott and everyone else who will read this post.
>
> After many messages that I posted on the news groups about rs232, I have
> come up with functional code which reads in as many as 25 characters in one
> operation, meaning that a micro-controller can send 25 bytes to the PC and
> VC++ has no problem reading this.

[snipped code of sample application]

> The above code has been extensively tested, many times and has never failed.
[snip]
>
> I have one question though! What is the advantage of using the Wndserial
> class as opposed to using functions like CreateFile, WriteFile, ReadFile, and
> CloseHandle.

I think this is properly explained at the codeproject homepage. Maybe I
should add that this piece of software is quite sophisticated (as
opposed to the wrapper class I used to use), so you don't have to worry
about that you don't see through it at once (neither do I).

> Would I be better off, or is it because in Windows it would be too
> complicated!

It depends. If you don't need software handshaking, asynchronous
notifications, and suchlike, you can use the plain old Read/WriteFile API.

Else it gets a bit complicated, I'm afraid. Since Read/WriteFile is not
specifically designed with communication devices that can have large
latency (as RS323 can have, depending on which device you're talking
with), it's a but unhandy to use. One could say, that this form of
communicating doesn't fit into the event driven model of data processing
under Windows.

Regards,
Stuart

Re: rs232... by Alexander

Alexander
Fri Sep 22 08:02:41 CDT 2006

Being "extensively tested" as opposed to "thoroughly reviewed" doesn't make
the code correct, sorry. There is no test that can catch problems a review
can.

One thing: you're overriding after end of CatchByte_BUFFER, because you pass
sizeof(CatchByte_BUFFER) as max bytes to read, and then zero a byte after
the last read. Another thing: you need to check that Accum_BUFFER is not
full EVERY TIME you're trying to save A BYTE to it. You CANNOT simply check
'j' for non-equality to BYTESTOREAD in the end of 'do' loop, because it
might cross over this value between checks.

"Robby" <Robby@discussions.microsoft.com> wrote in message
news:1FDBB7FF-2E39-4AF9-B112-750BE633E669@microsoft.com...
> Hello Scott and everyone else who will read this post.
>
> After many messages that I posted on the news groups about rs232, I have
> come up with functional code which reads in as many as 25 characters in
> one
> operation, meaning that a micro-controller can send 25 bytes to the PC and
> VC++ has no problem reading this. The code can be altered to read many
> more
> bytes than 25 if required, however I only tested up to 25. All you need to
> do
> is to change the first defined statement > BYTESTOREAD!
>
> Scott, I have learnt a lot form our exchage of posts, so I figure I would
> like to share with you, what I have come up with, and I would appreciate
> your
> opinion : However, I know that the code can probably be made more
> efficient,
> however I think, for me, for now, its quite okay!
>
> This is not the way I will leave the code, there will be some final
> touches
> such as better placement of #define statements and so forth!
>
> I will put comments under every line of code, so if you disagree with the
> commentary feel free to correct it.
>
> //////////////////////////////////////////////////////////////////////
> #include <windows.h>
>
> CSerialWnd MySerial;
> //Create an object of Cserial type.
>
> LRESULT CALLBACK WndProc_CW1 (HWND hwnd, UINT message,
> WPARAM wParam, LPARAM lParam)
> {
>
> //RS232 *Receive mode
>
> #define BYTESTOREAD 25 //Depicts the amount of bytes to read!
> #define OB_BYTES ((BYTESTOREAD*2)+1) //Number of bytes for official
> Buffer !
>
> static DWORD dwBytesRead;
> //Declaration of variable to indicate actual bytes that are
> //read in within the time limit that windows allowed!
>
> static byte CatchByte_BUFFER[BYTESTOREAD+1];
> //Bytes returned from the MySerial.Read() function, will be
> //immediatelly assigned to this array.
>
> static byte Accum_BUFFER[BYTESTOREAD+1];
> //Since windows cannot assure a constant amount of bytes
> //returned from the MySerial.Read() function(which come
> // from the rs232 port), then when CatchByteBUFFER
> //is full, I transfer its bytes to the Accum_BUFFER. So
> //now, CatchByteBUFFER is ready for another, set of bytes
> //returned from the next MySerial.Read() function.
> static TCHAR Official_BUFFER[OB_BYTES];
> //This array holds the final and complete string that was
> read
> in .
>
> int k,n,j;
> //General purpose variables used to loop and index arrays
>
>
> //RS232 SERIAL PORT MONITOR
> if (message == CSerialWnd::mg_nDefaultComMsg)
> {
> const CSerialWnd::EEvent eEvent = SerialWnd::EEvent(LOWORD(wParam));
> const CSerialWnd::EError eError = CSerialWnd::EError(HIWORD(wParam));
>
> switch (eEvent)
> {
> case CSerialWnd::EEventRecv:
> // A serial message occurred
> j = 0;
> //Holds Accumulative array index value
>
> do
> {
> MySerial.Read(CatchByte_BUFFER,
> sizeof(CatchByte_BUFFER),
>
> &dwBytesRead);
> //Read the port, and the third parameter
> //will hold the amount of bytes read in!
>
> CatchByte_BUFFER[dwBytesRead] = '\0';
> //Null Terminate the CatchByte_BUFFER array!
>
> n = dwBytesRead;
> //Re-assign the amount of bytes read in to another
> variable:
> //The reason for this was that I would get the
> following error, if I
> //were to put this variable straight into the for
> loop command:
> //c:\_DTS_PROGRAMMING\C_PROGRAMMING\vc++\MY_APPS_LAB
> // \XPPLC\WndProc_CW1.cpp(220) : warning C4018: '<'
> :
> //signed/unsigned mismatch.
> //So for now, I just re-assigned it!
>
> for(k=0;k<n;k++)
> {
> Accum_BUFFER[k+j] = CatchByte_BUFFER[k];
> //Store the bytes that were just read in into an
> //accummulator array!
> }
>
> j = j + dwBytesRead;
> //Advance the index for the Accum_BUFFER array
> //so we can append the next bytes which reside in
> the
> //CatchByte_BUFFER array in the next iteration!
> }
> while(j != (BYTESTOREAD) && j != 0);
> //If all the bytes were read in, then , j will
> be equal to
> //BYTESTOREAD and will break out of the while
> loop, and
> //also, for unneccessary subsequent port reads
> where
> //dwBytesRead will equal to 0, meaning that no
> bytes were
> //read, then this will cause the breaking out
> //of the while loop aswell!
>
>
> MultiByteToWideChar(CP_ACP,0,
> (LPCSTR)Accum_BUFFER,-1,Official_BUFFER,OB_BYTES);
> //Finally, assign the fully accumulated bytes
> //to a TCHAR string array, which are
> converted
> //to unicode, if I am not mistaken!
> break;
> default:
> break;
> }
> return 0;
> }
>
>
> switch(message)
> {
> case WM_CREATE:
> MySerial.Open(TEXT("COM1"),hwnd,WM_NULL,lParam,0,0);
> //Open the rs232 port
>
> MySerial.Setup(CSerial::EBaud9600,CSerial::EData8,
> CSerial::EParNone,CSerial::EStop1);
> //Set up the rs232 port
> return 0;
>
> case WM_CLOSE:
> MySerial.Close(); //Close Port!
> break;
> return 0;
> }
>
> return DefWindowProc(hwnd, message,wParam,lParam);
> }
>
> /////////////////////////////////////////////////////////////////////////////////////////////
>
> The above code has been extensively tested, many times and has never
> failed.
> After spending many hours on the subject, I thought I could shine some
> light
> on rs232 in a laymens kind of way, I know for many of you, this is
> probably
> unworthy of your time or knowledge, however, if I would of have had this
> type
> of post 3 months ago, it really would of made the rs232 implementation
> curve
> a lot simpler for me! I invite anyone that is a beginer and finds rs232
> complicated just as I did, (and still do! Because I am sure there is much
> more to this) to use it and improve upon it!
>
> I have one question though! What is the advantage of using the Wndserial
> class as opposed to using functions like CreateFile, WriteFile, ReadFile,
> and
> CloseHandle.
>
> Would I be better off, or is it because in Windows it would be too
> complicated!
> Just asking!
>
> I thank Scott and all members of the news groups that have helped me on
> the
> subject!
>
> You guys, are a great resource on the subjects of C,C++,VC++.
>
> --
> Best regards
> Robert



Re: rs232... by Scott

Scott
Fri Sep 22 08:10:32 CDT 2006

Robby wrote:
> I have one question though! What is the advantage of using the Wndserial
> class as opposed to using functions like CreateFile, WriteFile, ReadFile, and
> CloseHandle.
>
> Would I be better off, or is it because in Windows it would be too
> complicated!
> Just asking!
>

I have not looked at that class. If you look at it - the advantage is
that you did not have to write whatever stuff is within it! If it
creates a serial thread for you that is a big advantage. Serial calls
should be done in a secondary thread so they won't block your GUI.


> I thank Scott and all members of the news groups that have helped me on the
> subject!
>
> You guys, are a great resource on the subjects of C,C++,VC++.
>

Yer welcome, Robby. Glad you got it working.

--
Scott McPhillips [VC++ MVP]


Re: rs232... by Robby

Robby
Fri Sep 22 11:38:02 CDT 2006

Thankyou all for your feedback!

Yes Alexander! I will look into this... glad you can point it out buddy!

Much appreciated!

You all have a nice day!

--
Best regards
Robert


"Stuart Redmann" wrote:

> Robby wrote:
> > Hello Scott and everyone else who will read this post.
> >
> > After many messages that I posted on the news groups about rs232, I have
> > come up with functional code which reads in as many as 25 characters in one
> > operation, meaning that a micro-controller can send 25 bytes to the PC and
> > VC++ has no problem reading this.
>
> [snipped code of sample application]
>
> > The above code has been extensively tested, many times and has never failed.
> [snip]
> >
> > I have one question though! What is the advantage of using the Wndserial
> > class as opposed to using functions like CreateFile, WriteFile, ReadFile, and
> > CloseHandle.
>
> I think this is properly explained at the codeproject homepage. Maybe I
> should add that this piece of software is quite sophisticated (as
> opposed to the wrapper class I used to use), so you don't have to worry
> about that you don't see through it at once (neither do I).
>
> > Would I be better off, or is it because in Windows it would be too
> > complicated!
>
> It depends. If you don't need software handshaking, asynchronous
> notifications, and suchlike, you can use the plain old Read/WriteFile API.
>
> Else it gets a bit complicated, I'm afraid. Since Read/WriteFile is not
> specifically designed with communication devices that can have large
> latency (as RS323 can have, depending on which device you're talking
> with), it's a but unhandy to use. One could say, that this form of
> communicating doesn't fit into the event driven model of data processing
> under Windows.
>
> Regards,
> Stuart
>