Serial Ports In A Windoze World

One of my indispensable pieces of test equipment is a Tektronix TDS 210 oscilloscope.  It was built back in the days before USB.  Well actually no... USB was available but instrument manufactures were slow to embrace the USB.  Consequently the TDS210 has a GPIB port and an RS-232 port for communicating with the outside world.

While GPIB communication is fine, it requires a special interface, the cables are large and stiff, and it is also expensive.

So... RS-232 it will be.

Now there are software packages for running the TDS 210... but if they are not pricey, they are not useful... so I thought I would write my own.

One of the things I would need to do, to communicate with my scope, is gain access to a serial port.  Oddly many desktop PCs still come with at least one serial port.  Most laptops long ago abandoned RS-232 for USB.  However, USB to serial ports are cheap, and still available.

Wherever the serial port (a.k.a COM port) is located, any computer program I might write, will need to be able to send information to and fro using it.

One of the ways to do that is through the legacy Win32 system call CreateFile( ).  In my program it looks like this:

   hToComPort1 = CreateFile( str,
                    GENERIC_READ | GENERIC_WRITE,
                    0,    // must be opened with exclusive-access
                    0, // default security attributes
                    OPEN_EXISTING, // must use OPEN_EXISTING
                    0,    // not overlapped I/O
                    //FILE_FLAG_OVERLAPPED,
                    NULL  // hTemplate must be NULL for comm devices
                    );

Unfortunately the compiler didn't like this function call because the first parameter str was of type String^ and the call wants an LPCTSTR type.

Now the subject of string types is a long and boring one, the point here is that the String^ type is easy to use in modern programming but the function call wants its first parameter in a much simpler form, which is not compatible with the String^ type.

There are many ways to have one data type look like another data type.  One way is called coercion, which will not work in this case, anther way is conversion, which will work in this case.  The question then becomes how to convert?  The means of conversion depends on the string type, of which the software industry has been prolific over the years, and therefore some means of conversion can be used and others cannot.

Fortunately the Internet can often provide answer.  I found an answer at:

  http://bytes.com/topic/net/answers/281851-how-convert-string-lpctstr-i-found-threads-about-but-dont-work

In practice I used the following:


.
.
.
   IntPtr ptr = Marshal::StringToHGlobalAnsi(str);
   LPCTSTR fileString = reinterpret_cast<LPCTSTR>(ptr.ToPointer());
.
.
.
   Marshal::FreeHGlobal(ptr);
.
.
.


This code converts my
str into an LPCTSTR called fileString which will play nice with the function call CreateFile( ).  It looks like this:

   hToComPort1 = CreateFile( fileString,
                    GENERIC_READ | GENERIC_WRITE,
                    0,    // must be opened with exclusive-access
                    0, // default security attributes
                    OPEN_EXISTING, // must use OPEN_EXISTING
                    0,    // not overlapped I/O
                    //FILE_FLAG_OVERLAPPED,
                    NULL  // hTemplate must be NULL for comm devices
                    );

After I am finished with the conversion, I free the memory it occupied with the call:

.
.
.
   Marshal::FreeHGlobal(ptr);
.
.
.


Image thanks to ARRL