Serialib ::: Simple Serial Library v1.2

serialib.cpp

00001 
00018 #include "serialib.h"
00019 
00020 
00021 
00022 
00026 // Class constructor
00027 serialib::serialib()
00028 {}
00029 
00030 
00034 // Class desctructor
00035 serialib::~serialib()
00036 {
00037     Close();
00038 }
00039 
00040 
00041 
00042 //_________________________________________
00043 // ::: Configuration and initialization :::
00044 
00045 
00046 
00090 char serialib::Open(const char *Device,const unsigned int Bauds)
00091 {
00092 #if defined (_WIN32) || defined( _WIN64)
00093 
00094     // Open serial port
00095     hSerial = CreateFileA(  Device,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
00096     if(hSerial==INVALID_HANDLE_VALUE) {
00097         if(GetLastError()==ERROR_FILE_NOT_FOUND)
00098             return -1;                                                  // Device not found
00099         return -2;                                                      // Error while opening the device
00100     }
00101 
00102     // Set parameters
00103     DCB dcbSerialParams = {0};                                          // Structure for the port parameters
00104     dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
00105     if (!GetCommState(hSerial, &dcbSerialParams))                       // Get the port parameters
00106         return -3;                                                      // Error while getting port parameters
00107     switch (Bauds)                                                      // Set the speed (Bauds)
00108     {
00109     case 110  :     dcbSerialParams.BaudRate=CBR_110; break;
00110     case 300  :     dcbSerialParams.BaudRate=CBR_300; break;
00111     case 600  :     dcbSerialParams.BaudRate=CBR_600; break;
00112     case 1200 :     dcbSerialParams.BaudRate=CBR_1200; break;
00113     case 2400 :     dcbSerialParams.BaudRate=CBR_2400; break;
00114     case 4800 :     dcbSerialParams.BaudRate=CBR_4800; break;
00115     case 9600 :     dcbSerialParams.BaudRate=CBR_9600; break;
00116     case 14400 :    dcbSerialParams.BaudRate=CBR_14400; break;
00117     case 19200 :    dcbSerialParams.BaudRate=CBR_19200; break;
00118     case 38400 :    dcbSerialParams.BaudRate=CBR_38400; break;
00119     case 56000 :    dcbSerialParams.BaudRate=CBR_56000; break;
00120     case 57600 :    dcbSerialParams.BaudRate=CBR_57600; break;
00121     case 115200 :   dcbSerialParams.BaudRate=CBR_115200; break;
00122     case 128000 :   dcbSerialParams.BaudRate=CBR_128000; break;
00123     case 256000 :   dcbSerialParams.BaudRate=CBR_256000; break;
00124     default : return -4;
00125 }    
00126     dcbSerialParams.ByteSize=8;                                         // 8 bit data
00127     dcbSerialParams.StopBits=ONESTOPBIT;                                // One stop bit
00128     dcbSerialParams.Parity=NOPARITY;                                    // No parity
00129     if(!SetCommState(hSerial, &dcbSerialParams))                        // Write the parameters
00130         return -5;                                                      // Error while writing
00131 
00132     // Set TimeOut
00133     timeouts.ReadIntervalTimeout=0;                                     // Set the Timeout parameters
00134     timeouts.ReadTotalTimeoutConstant=MAXDWORD;                         // No TimeOut
00135     timeouts.ReadTotalTimeoutMultiplier=0;
00136     timeouts.WriteTotalTimeoutConstant=MAXDWORD;
00137     timeouts.WriteTotalTimeoutMultiplier=0;
00138     if(!SetCommTimeouts(hSerial, &timeouts))                            // Write the parameters
00139         return -6;                                                      // Error while writting the parameters
00140     return 1;                                                           // Opening successfull
00141 
00142 #endif
00143 #ifdef __linux__    
00144     struct termios options;                                             // Structure with the device's options
00145 
00146 
00147     // Open device
00148     fd = open(Device, O_RDWR | O_NOCTTY | O_NDELAY);                    // Open port
00149     if (fd == -1) return -2;                                            // If the device is not open, return -1
00150     fcntl(fd, F_SETFL, FNDELAY);                                        // Open the device in nonblocking mode
00151 
00152     // Set parameters
00153     tcgetattr(fd, &options);                                            // Get the current options of the port
00154     bzero(&options, sizeof(options));                                   // Clear all the options
00155     speed_t         Speed;
00156     switch (Bauds)                                                      // Set the speed (Bauds)
00157     {
00158     case 110  :     Speed=B110; break;
00159     case 300  :     Speed=B300; break;
00160     case 600  :     Speed=B600; break;
00161     case 1200 :     Speed=B1200; break;
00162     case 2400 :     Speed=B2400; break;
00163     case 4800 :     Speed=B4800; break;
00164     case 9600 :     Speed=B9600; break;
00165     case 19200 :    Speed=B19200; break;
00166     case 38400 :    Speed=B38400; break;
00167     case 57600 :    Speed=B57600; break;
00168     case 115200 :   Speed=B115200; break;
00169     default : return -4;
00170 }
00171     cfsetispeed(&options, Speed);                                       // Set the baud rate at 115200 bauds
00172     cfsetospeed(&options, Speed);
00173     options.c_cflag |= ( CLOCAL | CREAD |  CS8);                        // Configure the device : 8 bits, no parity, no control
00174     options.c_iflag |= ( IGNPAR | IGNBRK );
00175     options.c_cc[VTIME]=0;                                              // Timer unused
00176     options.c_cc[VMIN]=0;                                               // At least on character before satisfy reading
00177     tcsetattr(fd, TCSANOW, &options);                                   // Activate the settings
00178     return (1);                                                         // Success
00179 #endif
00180 }
00181 
00182 
00186 void serialib::Close()
00187 {
00188 #if defined (_WIN32) || defined( _WIN64)
00189     CloseHandle(hSerial);
00190 #endif
00191 #ifdef __linux__
00192     close (fd);
00193 #endif
00194 }
00195 
00196 
00197 
00198 
00199 //___________________________________________
00200 // ::: Read/Write operation on characters :::
00201 
00202 
00203 
00210 char serialib::WriteChar(const char Byte)
00211 {
00212 #if defined (_WIN32) || defined( _WIN64)
00213     DWORD dwBytesWritten;                                               // Number of bytes written
00214     if(!WriteFile(hSerial,&Byte,1,&dwBytesWritten,NULL))                // Write the char
00215         return -1;                                                      // Error while writing
00216     return 1;                                                           // Write operation successfull
00217 #endif
00218 #ifdef __linux__
00219     if (write(fd,&Byte,1)!=1)                                           // Write the char
00220         return -1;                                                      // Error while writting
00221     return 1;                                                           // Write operation successfull
00222 #endif
00223 }
00224 
00225 
00226 
00227 //________________________________________
00228 // ::: Read/Write operation on strings :::
00229 
00230 
00237 char serialib::WriteString(const char *String)
00238 {
00239 #if defined (_WIN32) || defined( _WIN64)
00240     DWORD dwBytesWritten;                                               // Number of bytes written
00241     if(!WriteFile(hSerial,String,strlen(String),&dwBytesWritten,NULL))  // Write the string
00242         return -1;                                                      // Error while writing
00243     return 1;                                                           // Write operation successfull
00244 #endif
00245 #ifdef __linux__
00246     int Lenght=strlen(String);                                          // Lenght of the string
00247     if (write(fd,String,Lenght)!=Lenght)                                // Write the string
00248         return -1;                                                      // error while writing
00249     return 1;                                                           // Write operation successfull
00250 #endif
00251 }
00252 
00253 // _____________________________________
00254 // ::: Read/Write operation on bytes :::
00255 
00256 
00257 
00265 char serialib::Write(const void *Buffer, const unsigned int NbBytes)
00266 {
00267 #if defined (_WIN32) || defined( _WIN64)
00268     DWORD dwBytesWritten;                                               // Number of byte written
00269     if(!WriteFile(hSerial, Buffer, NbBytes, &dwBytesWritten, NULL))     // Write data
00270         return -1;                                                      // Error while writing
00271     return 1;                                                           // Write operation successfull
00272 #endif
00273 #ifdef __linux__
00274     if (write (fd,Buffer,NbBytes)!=(ssize_t)NbBytes)                              // Write data
00275         return -1;                                                      // Error while writing
00276     return 1;                                                           // Write operation successfull
00277 #endif
00278 }
00279 
00280 
00281 
00292 char serialib::ReadChar(char *pByte,unsigned int TimeOut_ms)
00293 {
00294 #if defined (_WIN32) || defined(_WIN64)
00295 
00296     DWORD dwBytesRead = 0;
00297     timeouts.ReadTotalTimeoutConstant=TimeOut_ms;                       // Set the TimeOut
00298     if(!SetCommTimeouts(hSerial, &timeouts))                            // Write the parameters
00299         return -1;                                                      // Error while writting the parameters
00300     if(!ReadFile(hSerial,pByte, 1, &dwBytesRead, NULL))                 // Read the byte
00301         return -2;                                                      // Error while reading the byte
00302     if (dwBytesRead==0) return 0;                                       // Return 1 if the timeout is reached
00303     return 1;                                                           // Success
00304 #endif
00305 #ifdef __linux__
00306     TimeOut         Timer;                                              // Timer used for timeout
00307     Timer.InitTimer();                                                  // Initialise the timer
00308     while (Timer.ElapsedTime_ms()<TimeOut_ms || TimeOut_ms==0)          // While Timeout is not reached
00309     {
00310         switch (read(fd,pByte,1)) {                                     // Try to read a byte on the device
00311         case 1  : return 1;                                             // Read successfull
00312         case -1 : return -2;                                            // Error while reading
00313         }
00314     }
00315     return 0;
00316 #endif
00317 }
00318 
00319 
00320 
00331 int serialib::ReadStringNoTimeOut(char *String,char FinalChar,unsigned int MaxNbBytes)
00332 {
00333     unsigned int    NbBytes=0;                                          // Number of bytes read
00334     char            ret;                                                // Returned value from Read
00335     while (NbBytes<MaxNbBytes)                                          // While the buffer is not full
00336     {                                                                   // Read a byte with the restant time
00337         ret=ReadChar(&String[NbBytes]);
00338         if (ret==1)                                                     // If a byte has been read
00339         {
00340             if (String[NbBytes]==FinalChar)                             // Check if it is the final char
00341             {
00342                 String  [++NbBytes]=0;                                  // Yes : add the end character 0
00343                 return NbBytes;                                         // Return the number of bytes read
00344             }
00345             NbBytes++;                                                  // If not, just increase the number of bytes read
00346         }
00347         if (ret<0) return ret;                                          // Error while reading : return the error number
00348     }
00349     return -3;                                                          // Buffer is full : return -3
00350 }
00351 
00364 int serialib::ReadString(char *String,char FinalChar,unsigned int MaxNbBytes,unsigned int TimeOut_ms)
00365 {
00366     if (TimeOut_ms==0)
00367         return ReadStringNoTimeOut(String,FinalChar,MaxNbBytes);
00368 
00369     unsigned int    NbBytes=0;                                          // Number of bytes read
00370     char            ret;                                                // Returned value from Read
00371     TimeOut         Timer;                                              // Timer used for timeout
00372     long int        TimeOutParam;
00373     Timer.InitTimer();                                                  // Initialize the timer
00374 
00375     while (NbBytes<MaxNbBytes)                                          // While the buffer is not full
00376     {                                                                   // Read a byte with the restant time
00377         TimeOutParam=TimeOut_ms-Timer.ElapsedTime_ms();                 // Compute the TimeOut for the call of ReadChar
00378         if (TimeOutParam>0)                                             // If the parameter is higher than zero
00379         {
00380             ret=ReadChar(&String[NbBytes],TimeOutParam);                // Wait for a byte on the serial link            
00381             if (ret==1)                                                 // If a byte has been read
00382             {
00383 
00384                 if (String[NbBytes]==FinalChar)                         // Check if it is the final char
00385                 {
00386                     String  [++NbBytes]=0;                              // Yes : add the end character 0
00387                     return NbBytes;                                     // Return the number of bytes read
00388                 }
00389                 NbBytes++;                                              // If not, just increase the number of bytes read
00390             }
00391             if (ret<0) return ret;                                      // Error while reading : return the error number
00392         }
00393         if (Timer.ElapsedTime_ms()>TimeOut_ms) {                        // Timeout is reached
00394             String[NbBytes]=0;                                          // Add the end caracter
00395             return 0;                                                   // Return 0
00396         }
00397     }
00398     return -3;                                                          // Buffer is full : return -3
00399 }
00400 
00401 
00412 int serialib::Read (void *Buffer,unsigned int MaxNbBytes,unsigned int TimeOut_ms)
00413 {
00414 #if defined (_WIN32) || defined(_WIN64)
00415     DWORD dwBytesRead = 0;
00416     timeouts.ReadTotalTimeoutConstant=(DWORD)TimeOut_ms;                // Set the TimeOut
00417     if(!SetCommTimeouts(hSerial, &timeouts))                            // Write the parameters
00418         return -1;                                                      // Error while writting the parameters
00419     if(!ReadFile(hSerial,Buffer,(DWORD)MaxNbBytes,&dwBytesRead, NULL))  // Read the bytes from the serial device
00420         return -2;                                                      // Error while reading the byte
00421     if (dwBytesRead!=(DWORD)MaxNbBytes) return 0;                       // Return 0 if the timeout is reached
00422     return 1;                                                           // Success
00423 #endif
00424 #ifdef __linux__
00425     TimeOut          Timer;                                             // Timer used for timeout
00426     Timer.InitTimer();                                                  // Initialise the timer
00427     unsigned int     NbByteRead=0;
00428     while (Timer.ElapsedTime_ms()<TimeOut_ms || TimeOut_ms==0)          // While Timeout is not reached
00429     {
00430         unsigned char* Ptr=(unsigned char*)Buffer+NbByteRead;           // Compute the position of the current byte
00431         int Ret=read(fd,(void*)Ptr,MaxNbBytes-NbByteRead);              // Try to read a byte on the device
00432         if (Ret==-1) return -2;                                         // Error while reading
00433         if (Ret>0) {                                                    // One or several byte(s) has been read on the device
00434             NbByteRead+=Ret;                                            // Increase the number of read bytes
00435             if (NbByteRead>=MaxNbBytes)                                 // Success : bytes has been read
00436                 return 1;
00437         }
00438     }
00439     return 0;                                                           // Timeout reached, return 0
00440 #endif
00441 }
00442 
00443 
00444 
00445 
00446 // _________________________
00447 // ::: Special operation :::
00448 
00449 
00450 
00455 void serialib::FlushReceiver()
00456 {
00457 #ifdef __linux__
00458     tcflush(fd,TCIFLUSH);
00459 #endif
00460 }
00461 
00462 
00463 
00468 int serialib::Peek()
00469 {
00470     int Nbytes=0;
00471 #ifdef __linux__
00472     ioctl(fd, FIONREAD, &Nbytes);
00473 #endif
00474     return Nbytes;
00475 }
00476 
00477 // ******************************************
00478 //  Class TimeOut
00479 // ******************************************
00480 
00481 
00485 // Constructor
00486 TimeOut::TimeOut()
00487 {}
00488 
00492 //Initialize the timer
00493 void TimeOut::InitTimer()
00494 {
00495     gettimeofday(&PreviousTime, NULL);
00496 }
00497 
00503 //Return the elapsed time since initialization
00504 unsigned long int TimeOut::ElapsedTime_ms()
00505 {
00506     struct timeval CurrentTime;
00507     int sec,usec;
00508     gettimeofday(&CurrentTime, NULL);                                   // Get current time
00509     sec=CurrentTime.tv_sec-PreviousTime.tv_sec;                         // Compute the number of second elapsed since last call
00510     usec=CurrentTime.tv_usec-PreviousTime.tv_usec;                      // Compute
00511     if (usec<0) {                                                       // If the previous usec is higher than the current one
00512         usec=1000000-PreviousTime.tv_usec+CurrentTime.tv_usec;          // Recompute the microseonds
00513         sec--;                                                          // Substract one second
00514     }
00515     return sec*1000+usec/1000;
00516 }
00517 
 All Classes Functions