⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.html

📁 这是一个串口调试程序,带有源代码的,还是比较好用的.
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<!--------------------------------------------------------------------------->  
<!--                           INTRODUCTION                                

 The Code Project article submission template (HTML version)

Using this template will help us post your article sooner. To use, just 
follow the 3 easy steps below:
 
     1. Fill in the article description details
     2. Add links to your images and downloads
     3. Include the main article text

That's all there is to it! All formatting will be done by our submission
scripts and style sheets. 

-->  
<!--------------------------------------------------------------------------->  
<!--                        IGNORE THIS SECTION                            -->
<html>
<head>
<title>The Code Project</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<Style>
BODY, P, TD { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10pt }
H2,H3,H4,H5 { color: #ff9900; font-weight: bold; }
H2 { font-size: 13pt; }
H3 { font-size: 12pt; }
H4 { font-size: 10pt; color: black; }
PRE { BACKGROUND-COLOR: #FBEDBB; FONT-FAMILY: "Courier New", Courier, mono; 
      WHITE-SPACE: pre; }
CODE { COLOR: #990000; FONT-FAMILY: "Courier New", Courier, mono; }
</style>
</head>
<body bgcolor="#FFFFFF" color=#000000>
<!--------------------------------------------------------------------------->  


<!-------------------------------     STEP 1      --------------------------->
<!--  Fill in the details (CodeProject will reformat this section for you) -->

<pre>
Title:       Serial library for C++
Author:      Ramon de Klein
Email:       R.de.Klein@iaf.nl
Environment: VC++ 6.0, Windows NT v4.0, Windows 98/ME, Windows 2000
Keywords:    Serial, RS232, COM-port
Level:       Intermediate
Description: A high-performance, complete and compact serial library for C++
Section      System
SubSection   General
</pre>

<hr width=100% noshade>

<!-------------------------------     STEP 2      --------------------------->
<!--  Include download and sample image information.                       --> 

<li class=download><a href="Serial.zip">Download demo project (with source) - XXX Kb </a></li>

<!--  <p><img src="SerialScreenDump.gif" alt="Sample Image" width=740 height=532></p> -->


<!-------------------------------     STEP 3      --------------------------->
<!--  Add the article text. Please use simple formatting (<h2>, <p> etc)   --> 

<h2>
 Introduction
</h2>

<p>
 Serial communications is needed in several types of applications, but
 the Win32 API isn't a very easy to use API to implement it. Things get
 even more complicated when you want to use serial communication in an
 MFC based program. The classes provided in the library try to make
 life a little easier. Its documentation is extensive, because I want
 to give you a good background. Serial communication is hard and good
 knowledge of its implementation saves you a lot of work, both now and
 in the future...
</p>

<p>
 First I'll briefly discuss why serial communications is hard. After
 reading that chapter you'll probably be convinced as well that you
 need a class which deals with serial communication. The classes
 provided in the library are not the only classes, which handle the
 serial communication. Many other programmers wrote their own classes,
 but I found many of them too inefficient or they weren't robust,
 scalable or suitable for non-MFC programs. I tried to make these
 classes as efficient, reliable and robust as possible, without
 sacrificing ease of use too much.
</p>

<p>
 The library has been developed as a public domain library some time
 ago, but it has been used in several commercial applications. I think
 most bugs have been solved, but unfortunately I cannot guarantee that
 there are no bugs left. If you find one (or correct a bug), please
 inform me so I can update the library.
</p>


<h2>
 Why is serial communication that hard?
</h2>

<p>
 Serial communication in Win32 uses the standard ReadFile/WriteFile
 functions to receive and transmit data, so why should serial
 communication be any harder then just plain file I/O? There are
 several reasons, which I'll try to explain. Some problems are solved
 in this library, but some others cannot be solved by a library.
</p>

<h3>
 Baudrates, parity, databits, handshaking, etc...
</h3>

<p>
 Serial communication uses different formats to transmit data on the
 wire. If both endpoints doesn't use the same setting you get garbled
 data. Unfortunately, no class can help you with these problems. The
 only way to cope with this is that you understand what these settings
 are all about. Baudrate, parity, databits and stopbits are often quite
 easy to find out, because when they match with the other endpoint, you
 won't have any problems (if your computer is fast enough to handle the
 amount of data at higher baudrates).
</p>

<p>
 Handshaking is much more difficult, because it's more difficult to
 detect problems in this area. Handshaking is being used to control the
 amount of data that can be transmitted. If the sending machine can
 send data more quickly then the receiving machine can process we get
 more and more data in the receiver's buffer, which will overflow at a
 certain time. It would be nice when the receiving machine could tell
 the sending machine to stop sending data for a while, so it won't
 overflow the receiver's buffers. This process of controlling the
 transmission of data is called handshaking and there are basically
 three forms of handshaking: 
 <ol>
  <li>
   No handshaking, so data is always send even if the receiver cannot
   handle the data anymore. This can lead to data loss, when the sender
   is able to transmit data faster then the receiver can handle. Of
   course this option isn't recommended, but it can be used for
   situations where only a few bytes are transmitted once in a while.
  </li>
  <li>
   Hardware handshaking, where the RTS/CTS lines are used to indicate
   if data can be sent. This mode requires that both ports and the
   cable support hardware handshaking. Hardware handshaking is the most
   reliable and efficient form of handshaking available, but is
   hardware dependant. Make sure you have a proper cable, which is
   fully wired. There are a lot of wrong cables around, so make sure
   you use the right one.
  </li>
  <li>
   Software handshaking, where the XON/XOFF characters are used to
   throttle the data. A major drawback of this method is that these
   characters cannot be used for data anymore. The XON/XOFF characters
   are the CTRL-S/CTRL-Q characters, which cannot be used in the data
   stream anymore. This makes software handshaking pretty useless, when
   you want to send binary data. For ASCII data it's pretty useful.
   It's being used on the old UNIX terminals as well. Scrolling starts
   and stops with CTRL-S/CTRL-Q on these, so the user provides its own
   handshaking there (without even knowing it perhaps).
  </li>
 </ol>

<p>
 Problems with handshaking are pretty hard to find, because it will
 often only fail in cases where buffers overflow. These situations are
 hard to reproduce so make sure that you did setup handshaking
 correctly and that the used cable is working correct (if you're using
 hardware handshaking) before you continue.
</p>

<p>
 The Win32 API provides more handshaking options, which aren't directly
 supported by this library. These types of handshaking are rarely used,
 so it would probably only complicate the classes. If you do need these
 handshaking options, then you can use the Win32 API to do that and
 still use the classes provided by the library.
</p>

<h3>Asynchronous I/O makes things more complex</h3>

<p>
 File I/O is relatively fast so if the call blocks for a while, this
 will probably only be a few milliseconds which is acceptable for most
 programs. Serial I/O is much slower, which causes unacceptable delays
 in your program. Another problem is that you don't know when the data
 arrives and often you don't even know how much data will arrive.
</p>

<p>
 Win32 provides asynchronous function calls (also known as overlapped
 operations) to circumvent these problems. Asynchronous programming is
 often an excellent way to increase performance, but it certainly
 increases complexity as well. This complexity is the reason that a lot
 of programs have bugs in their serial communication routines. This
 library solves some asynchronous I/O problems by allowing the
 programmer to use overlapped and non-overlapped operations mixed
 throughout the code, which is often quite convenient.
</p>

<h3>The event driven programming model doesn't fit</h3>

<p>
 Things get even more complex in GUI applications, which uses the event
 driven model that they're used to. This programming model is a
 heritage of the old 16-bit days and it isn't even that bad. The basic
 rule is simple... All events are send using a windows message, so you
 need at least one window to receive the events. Most GUI applications
 are single-threaded (which is often the best solution to avoid a lot
 of complexity) and they use the following piece of code in the
 <code>WinMain</code> function to process all messages:
</p>

<pre>
// Start the message-pump until a WM_QUIT is received
MSG msg;
while (::GetMessage(&amp;msg,0,0,0))
{
    ::TranslateMessage(&amp;msg);
    ::DispatchMessage(&amp;msg);
}
</pre>

<p>
 Because the <code>GetMessage</code> function blocks until there is a
 message in the message queue, there's no way to wake up when a serial
 event occurs. Of course you can set a timer and check the ports
 there, but this kind of polling is bad design and certainly doesn't
 scale well. Unfortunately the Win32 serial communication API doesn't
 fit in this event driven model. It would be easier for GUI
 applications that the Win32 API posted a message to a window when a
 communication event occurred (this is exactly what the 16-bit
 implementation looked like).
</p>

<p>
 If you implement your own message-pump, you can use the
 <code>MsgWaitForMultipleObjects</code> to wait for a windows message
 or a windows object to become signaled. The following piece of code
 demonstrates how to do this (it assumes that the event handle that is
 being used for asynchronous events is stored in the variable
 <code>hevtCommEvent</code>):
</p>

<pre>
bool fQuit = false;
while (!fQuit)
{
    // Wait for a communication event or windows message
    switch (::MsgWaitForMultipleObjects(1,&amp;hevtCommEvent,FALSE,INFINITE,QS_ALLEVENTS))
    {
    case WAIT_OBJECT_0:
        {
            // There is a serial communication event, handle it...
            HandleSerialEvent();
        }
        break;

    case WAIT_OBJECT_0+1:
        {
            // There is a windows message, handle it...
            MSG msg;
            if (::PeekMessage(&amp;msg,0,0,0,PM_REMOVE))
            {
                // Abort on a WM_QUIT message
                if (msg.message == WM_QUIT) { fQuit = true; break; }

                // Translate and dispatch the message
                ::TranslateMessage(&amp;msg);
                ::DispatchMessage(&amp;msg);
            }
        }
        break;

    default:
        {
            // Error handling...
        }
        break;
    }
}
</pre>

<p>
 This code is much more complex then the simple message pump displayed
 above. This isn't that bad, but there is another problem with this
 code which is much more serious. The message pump is normally in one
 of the main modules of your program. You don't want to pollute that
 piece of code with serial communication from a completely different
 module. The handle is probably not even valid at all times, which can
 cause problems of its own. This solution is therefore not recommended.
 MFC and WTL programmers cannot implement this at all, because these
 frameworks  already their own message pumps. You might be able to
 override that message pump, but it probably requires a lot of tricky
 code and undocumented tricks.
</p>

<p>
 Using serial communications in a single-threaded event-driven program
 is difficult as I've just explained, but you probably found that out
 yourself. How can we solve this problem for these types of
 applications? The answer is in the <code>CSerialWnd</code> class,
 which posts a message to a window (both the message and window can be
 specified by the programmer) whenever a serial event occurs. This
 makes using a serial port in GUI based applications much easier.
 There is also a very thin MFC wrapper class, which is called
 <code>CSerialMFC</code> but it's that thin, that it's hardly worth
 mentioning.
</p>

<p>
 This library cannot perform magic, so how can it send messages without
 blocking the message pump? The answer is pretty simple. It uses a
 separate thread, which waits on communication events. If such an event
 occurs, it will notify the appropriate window. This is a very common
 approach, which is used by a lot of other (serial) libraries. It's not
 the best solution (in terms of performance), but it is suitable for
 99% of the GUI based communication applications. The communication
 thread is entirely hidden for the programmer and doesn't need to
 affect your architecture in any way.
</p>

<h2>
 Which class you should use in your code
</h2>

<p>
 The current implementation contains three different classes, which all
 have their own purpose. The following three classes are available.
</p>

<ul>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -