Unless you are going to help with the code I have, please dont simply tear
dont waste your time.
I know for sure I am NOT an expert programmer, but I do learn by example.
I have been using with much luck the ComDrvLib by Willies Computer.
"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
See below...
On Wed, 31 Dec 2008 08:24:47 -0500, "Me" <me@right.her> wrote:
//I am using Visual C++ 6 (working on upgrading soon)
//At the top I have:
UINT SerialThread( LPVOID Param );
//In the BEGIN_MESSAGE_MAP(...) I added:
ON_MESSAGE(MY_SERIAL, DataPresent)
ON_MESSAGE(MY_UNIT, DataUnit)
//In OnInitDialog() I have added:
AfxBeginThread(SerialThread,(LPVOID)m_hWnd);
//Actual thread to monitor serial activity:
UINT SerialThread( LPVOID Param ) //Thread to monitor serial activity
{
HWND hDlg = (HWND)Param;
int DataByte=0x00;
int i;
ercount=0;
while(TRUE){
ercount=0;
while(ercount == 0){
ercount = BytesInReceiveBuffer(m_Port);
Sleep(50);
****
Generally, as soon as I see a Sleep() like this, I know the design is
wrong. This whole
piece of code is pointless. If you want to receive data on a serial port,
you do a
ReadFile with an Event object in the OVERLAPPED structure. The above code
is a classic
newbie polling design, the wrong approach.
****
}
DataByte=GetByte(m_Port);
if (DataByte == 0x10){ // if 1st byte was 10h ignore next
33 bytes
for (i=0; i<33; i++){
DataByte=GetByte(m_Port);
}
}
if (DataByte == 0x11){ // if 1st byte was 11h read and
save
next 33 bytes
for (i=0; i<33; i++){
DataByte=GetByte(m_Port);
Bar[i]=(DataByte & 0xff); // Bar[] is a global unsigned char
string of 33 bytes
****
Already there is a problem here. Why is a global variable used? This is
an obvious
design error. There is no reason to use a global variable, and especially
not in a case
like this. IN FACT, by the time the PostMessage is seen, you might have
received another
0x11 and be OVERWRITING the global buffer. This is VERY poor design!
****
}
RunRead=1; // global variable I look for in
some loops to wait for data
****
Dangerous. Very dangerous. Bad design.
****
::PostMessage(hDlg, MY_SERIAL, (WPARAM)0, (LPARAM)0);
****
Why not post a message with a pointer to the buffer?
****
}
if (DataByte == 0x20){ // if 1st byte was 20h read and
save
next 1 byte
DataByte=GetByte(m_Port);
UnitSel=DataByte;
::PostMessage(hDlg, MY_UNIT, (WPARAM)0, (LPARAM)0);
}
}
return TRUE;
}
//RunRead is what I tried to us to let another routing know when data was
received.
****
Why should you care? If you think you care, you have made a few other
design errors. For
example, the notion that you need to "check this" in "loops" means you
have loops that are
blocking the message pump, and that's already a significant red flag about
the design. If
it is not anywhere near reasonable to have the main GUI thread blocked
long enough to
require this kind of flag.
****
//MY_SERIAL - updates a bargraph with the 33 bytes received
//MY_UNIT - updates a unit number
//How do I temporarily stop this thread so another area of the dialog can
control the serial port ??
*****
By not putting the "serial port" under "control" of a dialog! You would
report the
message back, and route it to whomever is interested in that message.
This indicates that
you have some very serious design errors.
*****
//Example: I have a routing that sends a byte out the serial port to an
external microcontroller
// and I want to wait for the response within this routine...
****
I have a design that does this, and it controls up to 16383 possible
external
microcontrollers simultaneously (in realistic environments, it typically
runs a few
hundred). The key to the design was that NOBODY "owns" the serial port;
the serial port
is just there, and messages are routed upon receipt to whomever wants
them. So you need
to (a) do a FAR better design of the serial port [see my essay on serial
ports] and (b)
decouple the idea of serial traffic from the idea of someone "owning" the
port.
For example, what I do is PostMessage a message *which contains the buffer
pointer to a
heap-allocated buffer* to the main window. The WPARAM contains the length
(limits to 32K
per message, and the longest possible message is 8K) and the "id" of the
target. The main
window just calls SendMessageToDescendants, and the views filter based on
the ID. Solves
a lot of problems.
By the way, if you are thinking that passing a heap-allocated buffer is
"inefficient", it
is VASTLY more efficient that the sleep-poll loop which involves several
kernel calls,
whereas the buffer allocation requires ZERO kernel calls to do the
allocation. So it is
impossible to argue that a global variable is "more efficient" if a design
is created that
does not involve sleep and polling.
joe
*****
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm