discussion on the design of serial communication architecture----and its implementation in VS 2010
The serial port is widely used in microcomputer communication because of its few physical circuits, long transmission distance, stable and reliable operation. Recently because of opportunistic coincidence, have the opportunity to get real through the serial communication control LED display and induction card reader controller opportunities, this hope can get some useful guidance on the Internet, but in the online search for many days, saw some of the basic serial port, emphasis on the programming aspects of the article, rarely involved in its architecture design, So liberty, put some real practical experience, essays into this article, talk to fill the heart, sincere hope that the same fellow human many correct.
A. Interface Design
1. Serial Interface Design
Serial port, its most basic function is the communication, from the appearance view, namely is reads, writes the throttle, therefore its interface design is as follows:
#pragma once
#include "SerialMessage.h"
Class Cserialport:publiccobject
{
Public
Cserialport (void);
Virtual~cserialport (void);
Virtualbool Connect (
Const DWORD Desiredaccess =generic_read| Generic_write,
Const DWORD ShareMode = 0,
Const DWORD flagsandattributes = 0,
Const DWORD bandrate = 19200,
Const BYTE ByteSize = 8,
Const BYTE parity = evenparity,
Const BYTE StopBits = Onestopbit
) Const = 0;
Virtualvoid disconnect (void) const = 0;
Virtualbool Portread (cserialmessage *message) const= 0;
Virtualbool portwrite (const cserialmessage *message) const = 0;
};
Pure virtual function Connect is used to create a serial connection, and also set the mode of operation, like, the choice of asynchronous mode of operation, as well as the baud rate, data bits, stop bits and check mode, etc. disconnect is used to disconnect the serial port, when the program exits or changes the communication parameters need to use Portread and Portwrite are used for reading and writing throttling, whose parameter message is read and write buffer, and its expected read, write length and actual read and write lengths are included.
2. Communication protocol Interface Design
As the RS485 only specifies the electrical characteristics of the serial port, as for the transmission of the bitstream interpretation, communication between the two sides how to answer, it is not hard to set. Therefore, the application of the equipment is a variety of applications, the communication protocols used are also various, such as for the device controller, but also for the LED display, but in the final analysis, the agreement to complete only two pieces of work, one is based on some rules and certain input conditions to produce a "correct" message, that is, a byte stream The second is to verify the received response message according to its default rules, or to report that the operation was successful, or to indicate that some kind of error occurred. So the interface of the communication protocol takes two pure virtual function as the main body, Producemessage generates a "correct" message which conforms to the communication protocol, serialcheckout the response message and reports the result, The return value class Creturncode contains the possible error codes and their Chinese and English explanations. In addition, the commonly used such as the header code, the tail code and error code, such as static constants defined here, its subclasses can be directly applied.
#pragma once
#include "Afx.h"
#include "ReturnCode.h"
#include "SerialMessage.h"
Class Cserialprotocol:
Publiccobject
{
Public
Cserialprotocol (void);
Virtual~cserialprotocol (void);
Virtualconst cserialmessage *producemessage (void) const = 0;
Virtualcreturncode serialcheckout (constcserialmessage *message) const = 0;
Protected
The Returncodes
static const Creturncode return_code[];
static const unsigned short return_codes = 22;
Forcontrolling
static const unsigned CHAR-STX = 0x02;
static const unsigned char ETX = 0x03;
static const unsigned char ACK = 0x06;
static const unsigned char NACK = 0x07;
};
As shown above, note that the statement static const creturncodereturn_code[] defines a static constant object array that must be initialized in its corresponding. cpp file. The definition of its related class and its initialization code are as follows:
#pragma once
Class Creturncode
{
Public
Creturncode (void);
Creturncode (Shortreturnid, CString enexplanation, CString cnexplanation);
~creturncode (void);
Private
The Returnid retruned by the device through the serial port
Shortmreturnid;
Theenglish explanation for the return ID
CString menglishexplanation;
The chieseexplanation for the return ID
CString mchinesexplanation;
Public
Shortgetreturnid (void) const;
Constcstring getenglishexplanation (void) const;
Constcstring getchinesexplanation (void) const;
Voidsetreturnid (const Shortretrunid);
Voidsetenglishexplanation (const CString ENEXP);
Voidsetchinesexplanation (const CString CNEXP);
};
Initializing an array of static constant objects
Const Creturncode CSERIALPROTOCOL::RETURN_CODE[2] =
{
Thereturnid being less than or equal to zero indicates that some error occurred
Creturncode (1, _t ("successful!"), _t ("Success")),
To Returnzero represents, the serial port is not available
Creturncode (0, _t ("Errors in Opening the Serial port!"), _t ("Open serial Failure"))
}
The instantiation of Creturncode here is not possible with new, because new is allocating storage space in the heap, while static constants can only allocate storage space in the static storage area.
3. Device Interface Design
In practice, a RS485 serial port can be connected to multi-channel devices, involving such as inductive card reader controller, LED display, video monitor and other equipment, but from an abstract point of view, the device has only two functions, one is to execute the command, that is, from the serial port received a message and to parse the execution, The other is to report on the results of their implementation. It is therefore abstracted as an abstract virtual device, as follows:
#pragma once
#include "SerialMessage.h"
#include "SerialPort.h"
#include "serialprotocol.h"
Class Cvirtualdevice:
Publiccobject
{
Public
Cvirtualdevice (void);
Virtual~cvirtualdevice (void);
Virtualbool Execute (const cserialmessage *message) const;
Virtualcserialmessage *response (void) const;
Virtualcserialport *getport () const;
Virtualvoid Setport (Cserialport * port);
Virtualcserialprotocol *getprotocol () const;
Virtualvoid Setprotocol (CSERIALPROTOCOL * protocol);
Virtualvoid SetDateTime (constcserialmessage *datetime,const cserialmessage*week) const = 0;
Private
Cserialport *mpcom;
Cserialprotocol *mpprotocol;
};
In the above code, because the device must be attached to a serial port, and must specify an applicable communication protocol, so the member pointer variable mpcom point to its attached serial port, the member pointer variable mpprotocol point to its corresponding communication protocol. With these two member variables, execute and response can directly give their implementation code, so here is not defined as a pure virtual function, the implementation code is as follows:
Boolcvirtualdevice::execute (const cserialmessage*message) const
{
Returnmpcom->portwrite (message);
}
Cserialmessage*cvirtualdevice::response (void) const
{
Cserialmessage *message = new Cserialmessage ();
Message->setbuffer ();
Mpcom->portread (message);
ReturnMessage;
}
The code above will be able to function for all devices, such as the setdatetime used to control the center and various types of devices, defined as pure virtual function, because the various types of devices set the date time of the instruction format is different, you need to define a specific implementation in its subclasses.
two. Architecture Design
As shown above, the specific serial port such as COM1, COM2 and other implementation of the interface Cserialport, thus constituting a serial port system; In the same way, the specific communication protocol realizes the interface Cserialprotocol, which forms a system of the communication protocol. , through the implementation of the virtual device interface Cvirtualdevice, constitutes a system of access equipment, the three systems unified by the Cmanager to manage. The Cmanager, Ccomeone, Ccometwo, and communication protocols Cscreenprotocol and CCONTROLLERPROTOCOL are designed using the singleton design pattern, so that only one instance of each class works, Effectively avoid possible conflicts.
Since each access device needs to be connected to a serial port and a protocol, so the initialization of the system needs to first establish a serial port and communication protocol instances, and then create a variety of access equipment instances, these work unified by Cmanager responsible, the code is as follows:
Cmanager *pmanager =cmanager::getinstance ();
Pmanager->init ();
The function init () is used for system initialization with the following code:
void Cmanager::init (void)
{
to Initializethe ports
Cserialport *pcom1 =ccomone::getinstance ();
Pcom1->connect ();
Toinitialize The Protocols
Cserialprotocol * Pscreenprotocol =cscreenprotocol::getinstance ();
Cserialprotocol * Pcontrollerprotocol =ccontrollerprotocol::getinstance ();
Toinitialize the Led screens
Cledscreen *pscreen = new Cledscreen ();
Pscreen->setport (PCOM1);
Pscreen->setprotocol (Pscreenprotocol);
Toinitialize the Controllers
Ccontroller *pcontroller = new Ccontroller ();
Pcontroller->setport (PCOM1);
Pcontroller->setprotocol (Pcontrollerprotocol);
}
Because the LED display and the inductive reader controller are connected to the COM1 port, so the above code will be connected to the PCOM1 pointer, so in sequence to create a variety of objects, to complete the initialization of the system. All of these objects will be destroyed uniformly at the time the object is Pmanager, that is, the only instance of Cmanager.
Here, pay special attention to the use of singleton design patterns in C + +, the only instance being referenced by a static pointer variable, with the following code examples:
Class Cmanager
{
Public
Virtual~cmanager (void);
Staticcmanager *getinstance (void);
Private
Cmanager (void);
Staticcmanager *mpmanager;
};
The constructor is defined as private, i.e. the object instance cannot be created in the outside world through new, and once an object instance is obtained through the static function getinstance, it is important to note that the value of the static pointer variable mpmanager is actually equal to the value of the this pointer of the instance. Therefore, when destroying the object instance, you must never use delete Mpmanager in its destructor, because that is actually equivalent to destroying the same object instance two times. A destructor example is as follows:
Cmanager::~cmanager (void)
{
Mpmanager = NULL;
}
It is important to assign its value to null in the destructor as above, since the static variable is not destroyed with the destruction of the object instance and becomes a wild pointer if the value is not re-assigned. And our programming habits are as follows:
Unsignedchar *p;
DoSomething
Deletep;
p = NULL;
The habit of always delete immediately after the re-assignment, this is a good habit of preventing the wild pointer, but here can not use Delete, so specifically proposed to attract special attention.
three. Thoughts and Experiences
Seemingly simpler serial communication program, but spent one months of time, has not reached the ideal level, carefully aftertaste the whole process, is the interface design and architecture design is not the first to do, but in two large refactoring gradually summed up, from this point of view, according to the order of this article to do development is better, First, the interface design from a more abstract point of view, through the inheritance of the interface to build the basic architecture, and then as the center of the expansion and architecture, mainly through the combination, aggregation of various objects to organize, the creation, use, destruction of the unified planning management, so that the formation of a complete class diagram, so that the architecture design , the detailed design, the code, the test can one go, actually is the programming joy also.
Above a little sentiment and experience, right when bait, sincerely hope you many advice. Dochehui read. My personal website http://www.entrigle.com/article has my technical novel "My Computer I Master" and my immediate sentiment and experience, welcome patronage.