PRODUITS

RESSOURCES

INFO TETRAEDRE

PLATEFORME WEB DE DEMO

Developer's resource site / FAQ

Serial communication for WIN32.

Updated October 25th 2005

GENERAL COMMENT

if the software that you have downloaded on Tetraedre's web site is not working correctly, be sure that you have the latest version before sending questions or comments.


Q: COM10 and above

I have been using your serial communication code for some time and recently I have been facing a problem. I have not been successful in connecting to ports that are above 9 (com10, com11,...). I always get a error = 8. I tested the port on Hyper Terminal and it works. Have you seen this before? Can you help me?

Answer:

Try "\\\\.\\COM10" or "\\.\COM10" (depends from your programming language)


Q: Getting 40-byte strings

we are trying to get a string from the serial port. With serial2 demo we get a single byte
How can we get a string with a length of 40 char ?

Answer:

You can set Rx size (setRxSize()) to 40. But I strongly discourage this since your application might be stuck waiting for incoming data (what happen if you receive 39 bytes (1 byte lost) followed by 40 bytes ???)
You should always set Rx size at 1, create a reception buffer and fill it we incoming data. So, you can handle erroneous frames as they arrive.


Q: _beginthreadex error

When I try to compile I get the following error:

Borland C++ 5.6.4 for Win32 Copyright (c) 1993, 2002 Borland
..\wcallerid\resources\ns\tserial_event.cpp:
"tserial_event.cpp": E2268 Call to undefined function '_beginthreadex' 
in function Tserial_event::connect(char *,int,int,char,bool) at line 294

Answer:

When you write borland projects, you can choose between single-threaded and multi-threaded library
_beginthreadex is only available in multi-threaded library

This is really not well done in Borland. Either you can find the right option in you project, otherwise you need to edit the .bpr file manually.

There is an option -tWM Try to replace it with -tWM-
Replace also cw32.lib with cw32mt.lib

I hope this will solve your problems


Q: Working with Hyperterminal, but not with serial library

I have device that works with Hyperterminal, but I cannot make it work with your library. Any idea ?

Answer:

This is a problem of serial port configuration. I have modified the library on May 16th 2005 to solve this problem.
In details here is what is happening:
In version prior to 2005-05-16, we had, in Tserial_event.cpp

        dcb.fDtrControl     = DTR_CONTROL_DISABLE;
        dcb.fRtsControl     = RTS_CONTROL_DISABLE;
This means that we don't use hardware handshake and we disable the DTR and RTS lines. This was not very wise since some devices, don't work if DTR and RTS are disabled even if they don't use hardware handshake (for example a modem, will disconnect from the phone line when these lines go low)


In version after to 2005-05-16, we have, in Tserial_event.cpp
        dcb.fDtrControl     = DTR_CONTROL_ENABLE;
        dcb.fRtsControl     = RTS_CONTROL_ENABLE;
This means that we don't use hardware handshake and we enable the DTR and RTS lines. If you want hardware handshake, set the hard_handshake to true. This will set
        dcb.fDtrControl     = DTR_CONTROL_HANDSHAKE;
        dcb.fRtsControl     = RTS_CONTROL_HANDSHAKE;

I hope this will solve your problems


Q: OnCharArrival & OnCharSent

The OnCharSent() function seems to be CERTAIN that it is called once for every byte that is sent, no more no less.  Is this true?  And most imortant, is It so as well with the OnCharArrival ?

Answer:

The serial event module was written to simulate microcontrollers on Win32. Windows hides a certain number of features so that you can access to the serial port like any other file. This is not what I needed for my application.

So, the OnCharArrival callback function represents the interrupt call that occurs on microcontroller when the input buffer is full. In a similar way, the OnCharSent callback function represents the interrupt call when the output buffer is empty.

To implement that on Windows, I've used two methods that both used the OVERLAPPED reading and writing functions:

For the OnCharArrival, I perform a permanent non-blocking read of a single byte (line 445)

success = (char) ReadFile(serial_handle,&data,1,&read_nbr,&ovReader);

For each byte read I call the OnCharArrival Callback function. If several bytes are sent very fast, Windows will put them inside a buffer so they will not be lost. Of course, you must not exceed Windows' limitations (buffer size,....)

For the OnCharSent, I use another trick. When you call sendChar, I simply but the data inside a 1-byte buffer and generate a SIG_DATA_IN signal inside the serial_event object. So, the next time the serial_event checks that event, it will make a write to the serial file (line 508)
success = (char) WriteFile(serial_handle, &data_to_send, 1,  &result_nbr, &ovWriter);

This call writes only one byte. After that, the OnCharSent callback function is sent.

IMPORTANT: The call of OnCharSent doesn't mean that the data has reached the other computer. It means only that you can send the next data. This might sound surprising the way every communication program works. To be sure that the peer has received the data, you must wait an acknowledge of it (this is the way TCP works). By flushing the serial file you can ask Windows to send the data immediately but you will never be sure of this. You must also consider the case of the data beeing corruptes while transmitted.


Q: Event driven programmation

 I am trying to test your event-driven serial port program (April 29th 2001 version) in MFC. When I click a button on a ialog, several bytes are sent to serial port. There is a loop plug on the serial port of my computer. So the bytes are feed back at once and displayed in the dialog. I find that when I click the button, only the last one byte can be received and displayed in the dialog.
...
I also notice that the "tx_in_progress" variable is only set but not checked in your program. This variable indicates whether the current byte is sent out. Why don't you check it in your program? I changed the above function to this:

void Tserial_event::sendChar (char data)
{
    do {
    } while (tx_in_progress);

    tx_in_progress = 1;
    data_to_send = data;
    SetSignal(SIG_DATA_IN);
}

Then it seems that all the bytes are received and displayed. But if I click the button too frequently, my program will halt.

Answer:

The event driven program must be used completely in an event driven manner. For instance, you should never send a byte until the OnCharSent event occurs. In your application, you should not allow the user to send another byte (by clicking) until the previous byte hsa been sent.

As you have seen, there is not output buffer. This is a known limitation. You have to implement it into your software by using the OnCharSent event. This is not too complicated. Anyway, if you need a high throughput, you should consider rewriting some parts of the code so that you can send a complete buffer and not only byte after byte. The software I presented was in fact used primarly to simulate small microcontrollers which doesn't have complex output buffer and which are byte oriented.

Another point is regarding the extra code you have added: DO NEVER EVER PUT A BUSY LOOP IN YOUR EVENT DRIVEN APPLICATION !!!!!!!

What you are doing with the while loop is in fact waiting for the CharSent event. I know that writting software that are really event driven is sometimes painful but this is the price to pay. So you application will never block anymore.


Q: ByteSize parameter

I am wondering what this ByteSize is used for !

Answer:

The ByteSize is used to define if 7-bit or 8-bit data must be transmitted on the serial line. In the RS-232 specification you can send 5,6, 7 or 8-bit data words. I've added this feature to the Tserial_event.cpp code because I used it on an application here
it was required to send 7-bit data.





Q: Visual C++ compilation

I am new to Visual C++, trying to compile the serial communication project under Microsoft Visual C++ is killing me. Can you kindly provide a VC++6.0 project file for this sample program ?

Answer:

The project was originally created to be compiled with the Borland C++ Builder development environment. In order to permit compilation  with Microsoft's Visual C++, I've modified a little the source code. A "#ifdef __BORLANDC__" has been inserted in the header part of the sertest.cpp and sertest2.cpp files in order to skip some Borland's specific pre-compiler commands.

IMPORTANT
But more important. The event-driven application uses multithreading in order to generate the events. So Visual C++ projects that use multithreading must be compiled with the appropriate setting. In your project settings, you MUST choose the multithreaded run-time library, otherwise the programme will not compile

Project settings
   |
   *--- C/C++
          |
          *--- Code generation
                       |
                       *---- Use run-time library
                                     |
                                     *---- Multithreaded


Q: Baudrate Setting

I need to create a simple program to connect to an external device at 10400 bps (about 1/11th of the maximum 115200 speed of my 16550 UART) through my COM port. I've just downloaded all your very well documented routines from zdnet but I cannot understand whether I can set any baud rate or just the standard ones (9600, 19200, ecc.). Could you give me any suggestion ?

Answer:

The technical document of Microsoft indicates the following:  
BaudRate
re>Specifies the baud rate at which the communications device  operates. This member can be an actual baud rate value,  or one of the following baud rate indexes:
CBR_110, CBR_19200, CBR_300, CBR_38400, CBR_600, CBR_56000, CBR_1200, CBR_57600, CBR_2400, CBR_115200, CBR_4800, CBR_128000, CBR_9600, CBR_256000, CBR_14400.

This doesn't tell if it will work with 10400. I've never tried with "exotic" values. You should try and tell us if it works. Anyway, before doing that you could check if the UART chip can work at such frequency. To do that, you must make the calculation of the division ratio for the UART's baudrate generator. Check the site www.beyondlogic.org for more information about the UART chip.