Re: Receiving single bytes with MSComm
From: Joseph M. Newcomer (newcomer_at_flounder.com)
Date: 02/20/05
- Next message: Joseph M. Newcomer: "Re: Is a Thread appropriate?"
- Previous message: CheckAbdoul: "Re: Select Directory"
- In reply to: Ed: "Re: Receiving single bytes with MSComm"
- Messages sorted by: [ date ] [ thread ]
Date: Sat, 19 Feb 2005 19:22:24 -0500
There's a lot of unnecessary code going on here.
Lacking any documentation on MSCOMM (as I pointed out, if it was important and useful it
would be documented; given that I cannot find any documentation on it, it is hard to
figure out what it is doing).
I see an immensley complicated piece of code trying to solve a simple problem, or what
should be a simple problem.
First, what does the debugger tell you when you examine Value? You should be able to see
the characters in it.
Why are you declaring a buffer of 2048 bytes when you don't need any of them?
You are doing a V_BSTR cast, which I believe is casting to a pointer to a Unicode string,
then you are assigning this value to a CString. You have not said if you are using a
Unicode or 8-bit (ANSI) compilation of your app.
Point me at some documentation on MSCOMM and I might have a fraction of a chance of
offering an opinion on what is gong on. But lacking documentation, everything is a guess.
It looks like MSCOMM might be presuming that it is reading text strings. OTOH, a BSTR does
have an explicit length value, and it might be that you are seeing the length as the input
character. I don't know what a V_BSTR cast really does.
There is no need to have a buffer of 2048 bytes, or an array at all; what's wrong with
char ed;
which is sufficient. You are storing what yu think is the byte of the input into a single
byte of the buffer 'ed', then writing it out with an fwrite of 1 byte, so why do you need
2048 of them, or setting the one-ahead value to be a NUL byte? Then, you have a pointer
called 'current' whose scope is unknown (it should not be a global variable, for example),
and you are incrementing it, but I see no bounds check to see if it exceeds the value.
Then I see you writing the buffer for the length of current, so each time you write the
entire string over and over again, for what purpose I can't imagine, AND THEN YOU RETURN
FROM THE SUBROUTINE, which immediately destroys all the information in the local
variables, such as your buffer 'ed'.
If the FILE * is not used until late in the function, don't declare it until it is needed.
But without documentation it is impossible to guess what is going on here. I cannot find
any documentation in the MSDN, in the platform SDK, or anyplace else. I actually install
ALL of Visual Studio; as useless as it is, I actually install VB. There is no MSCOMM32.chm
file anywhere on my file system, and locating that as the source of the documentation was
already challenging.
I would say ditch this piece of crap and write the rather trivial code required to do the
job right. That way you know what is going on. I suspect that if the documentation of
MSCOMM is as good as the documentation I've seen on other ActiveX controls, it is going to
be hopelessly inadequate in addressing any serious questions (the view seems to be that VB
programmers are going to be using this stuff, and facts will only confuse them. Try
figuring out how an MSGRID control works, once you've uncovered the documentation, which
is very hard to find also)
joe
On Sat, 19 Feb 2005 01:44:35 GMT, "Ed" <Ed@whyshouldItell.me> wrote:
>Hi,
>
>I still cannot get the receive working.
>This is the last thing I have tried and all I get is garbage back.
>All I seem to get is 0x01 even when I am supposed to get text.
>Please take a look and feel free to suggest. I really need binary to work.
>
>void CPSMDlg::OnOnCommMscomm1()
>{
> Char ed[2048];
> FILE *in;
> COleVariant Value;
>
> if (m_comm.GetCommEvent() == 2)
> {
> Value = m_comm.GetInput();
> CString Buffer = V_BSTR(&Value);
> ed[current]=Buffer[0];
> ed[current+1]=0x00;
> in = fopen("c:\\psm\\a1.dat", "wb");
> fwrite(ed, current, 1, in);
> fclose(in);
> current++;
> AfxMessageBox(Buffer);
> }
>}
>
>current is a count thats reset before I request any data.
>
>Thanks in advance,
>Ed
>-----------------------------------------------------------------------------
>
>
>
>"Joseph M. Newcomer" <newcomer@flounder.com> wrote in message
>news:2h671151c6kbs7l3jikhkd9n35jtrs749b@4ax.com...
>>I guess I've never before seen such convoluted code whose sole purpose is
>>to receive a
>> single byte from a serial port. I tend to favor code that looks like
>>
>> ReadFile(h, &buffer, 1, &bytesRead, NULL);
>>
>> as being the most complicated code I want, and in addition, if I'm doing
>> asynchronous I/O,
>> I'll create an event to indicate the completion, e.g.,
>>
>> OVERLAPPED ovl;
>> BYTE buffer;
>> ovl.hEvent = event; // created a long time ago
>> if(!ReadFile(h, &buffer, 1, &bytesRead, NULL))
>> { /* error */
>> DWORD err = ::GetLastError();
>> if(err != ERROR_IO_PENDING)
>> { /* fatal error */
>> ... deal with it
>> } /* fatal error */
>> HANDLE waiters[2];
>> waiters[0] = shutdownEvent;
>> waiters[1] = event;
>> DWORD wait = WaitForSingleObject(2, waiters, FALSE, INFINITE);
>> switch(wait)
>> { /* wait */
>> case WAIT_OBJECT_0:
>> // shut down
>> break;
>> case WAIT_OBJECT_0+1:
>> break;
>> default:
>> ASSERT(FALSE);
>> ... deal with error
>> } /* wait */
>> } /* error */
>> wnd->PostMessage(UWM_BYTE_RECEIVED, buffer, NULL);
>>
>> I've used code like this in on the order of a dozen major applications,
>> all of which are
>> out there running right now. Had I used MSCOMM, I probably wouldn't have a
>> single running
>> app.
>>
>> I note that nowhere in your code is there any error detection. Nor is
>> there a way to
>> recover from a device that is hung waiting for a byte. Overall, there is
>> an amazing amount
>> of convoluted work to interface to what is probably an inappropriate
>> interface in the
>> first place. If you simply take as a premise that MSCOMM is the wrong
>> approach, the
>> problem becomes trivial by comparison. And it has issues such as
>> reliability and
>> robustness that appear to be absent in the MSCOMM solution.
>>
>> I suppose I might be able to offer more advice if MSCOMM were documented,
>> but I am unable
>> to locate any documentation in the MSDN. Probably one of the reasons I
>> don't use it; I
>> don't use undocumented interfaces. If it were an important control, there
>> would be
>> documentation on it. That is, I could type "MSCOMM" to the index, or
>> possibly to the
>> search window of the MSDN, and get an actual, real, live, document that
>> describes how to
>> use the control. (The best I found was a pointer to a nonexistent file,
>> comm98.chm, which
>> does not exist on my machine, and I have the full Visual Studio 6 and
>> Visual Studio 7
>> installations, the latest platform SDK, and the second-latest MSDN library
>> installed, so
>> the lack of documentation clearly means this is an inappropriate control).
>> In the absence
>> the the ability to find documentation, the presumption is that this
>> control is distributed
>> as a joke control, whose purpose is not to solve problems but to create
>> them. Why elect to
>> use something that is undocumented, hard to use, and probably completely
>> inappropriate,
>> and then try to force a solution out of it?
>> joe
>>
>>
>> On Wed, 16 Feb 2005 04:01:39 GMT, "Me" <me@right.her> wrote:
>>
>>>I got the transmit code working sending binary data for MSComm.
>>>
>>>I have the following code for receiving a string of bytes.
>>>
>>>bool CPSMDlg::GetChar()
>>>{
>>> COleVariant myVar;
>>> int hr;
>>> long lLen = 0;
>>> BYTE *pAccess;
>>> char buffer[255];
>>>
>>> myVar.Attach (m_Comm.GetInput());
>>>
>>> hr = SafeArrayGetUBound (myVar.parray, 1, &lLen); // Get the
>>> length
>>> if (hr == S_OK)
>>> {
>>> lLen++; // upper bound
>>> is
>>>zero based index
>>> hr = SafeArrayAccess (myVar.parray,(void**)&pAccess); // lock array
>>> so
>>>you can access it
>>> if (hr == S_OK)
>>> {
>>> for (int i 0; i < lLen; i++) // Make a copy
>>> of
>>>the data
>>> buffer[i] = pAccess[i];
>>> SafeArrayUnaccessData (myVar.parray); // unlock the
>>>data
>>> }
>>> }
>>> // COleVariant cleans itself up
>>>}
>>>
>>>How do I receive single bytes one at a time since the device may only send
>>>1
>>>byte in response to commands????
>>>
>>>Thanks
>>>eddie@eddie1.net
>>>
>>
>> Joseph M. Newcomer [MVP]
>> email: newcomer@flounder.com
>> Web: http://www.flounder.com
>> MVP Tips: http://www.flounder.com/mvp_tips.htm
>
Joseph M. Newcomer [MVP]
email: newcomer@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
- Next message: Joseph M. Newcomer: "Re: Is a Thread appropriate?"
- Previous message: CheckAbdoul: "Re: Select Directory"
- In reply to: Ed: "Re: Receiving single bytes with MSComm"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|