Advertisement
Guest User

lib

a guest
Mar 15th, 2013
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.31 KB | None | 0 0
  1. /*!
  2. \file serialib.cpp
  3. \brief Class to manage the serial port
  4. \author Philippe Lucidarme (University of Angers) <serialib@googlegroups.com>
  5. \version 1.2
  6. \date 28 avril 2011
  7.  
  8. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  9. INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  10. PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM,
  11. DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  12. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  13.  
  14.  
  15. This is a licence-free software, it can be used by anyone who try to build a better world.
  16. */
  17.  
  18. #include "serialib.h"
  19.  
  20.  
  21.  
  22.  
  23. /*!
  24. \brief Constructor of the class serialib.
  25. */
  26. // Class constructor
  27. serialib::serialib()
  28. {}
  29.  
  30.  
  31. /*!
  32. \brief Destructor of the class serialib. It close the connection
  33. */
  34. // Class desctructor
  35. serialib::~serialib()
  36. {
  37. Close();
  38. }
  39.  
  40.  
  41.  
  42. //_________________________________________
  43. // ::: Configuration and initialization :::
  44.  
  45.  
  46.  
  47. /*!
  48. \brief Open the serial port
  49. \param Device : Port name (COM1, COM2, ... for Windows ) or (/dev/ttyS0, /dev/ttyACM0, /dev/ttyUSB0 ... for linux)
  50. \param Bauds : Baud rate of the serial port.
  51.  
  52. \n Supported baud rate for Windows :
  53. - 110
  54. - 300
  55. - 600
  56. - 1200
  57. - 2400
  58. - 4800
  59. - 9600
  60. - 14400
  61. - 19200
  62. - 38400
  63. - 56000
  64. - 57600
  65. - 115200
  66. - 128000
  67. - 256000
  68.  
  69. \n Supported baud rate for Linux :\n
  70. - 110
  71. - 300
  72. - 600
  73. - 1200
  74. - 2400
  75. - 4800
  76. - 9600
  77. - 19200
  78. - 38400
  79. - 57600
  80. - 115200
  81.  
  82. \return 1 success
  83. \return -1 device not found
  84. \return -2 error while opening the device
  85. \return -3 error while getting port parameters
  86. \return -4 Speed (Bauds) not recognized
  87. \return -5 error while writing port parameters
  88. \return -6 error while writing timeout parameters
  89. */
  90. char serialib::Open(const char *Device,const unsigned int Bauds)
  91. {
  92. #if defined (_WIN32) || defined( _WIN64)
  93.  
  94. // Open serial port
  95. hSerial = CreateFileA( Device,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
  96. if(hSerial==INVALID_HANDLE_VALUE) {
  97. if(GetLastError()==ERROR_FILE_NOT_FOUND)
  98. return -1; // Device not found
  99. return -2; // Error while opening the device
  100. }
  101.  
  102. // Set parameters
  103. DCB dcbSerialParams = {0}; // Structure for the port parameters
  104. dcbSerialParams.DCBlength=sizeof(dcbSerialParams);
  105. if (!GetCommState(hSerial, &dcbSerialParams)) // Get the port parameters
  106. return -3; // Error while getting port parameters
  107. switch (Bauds) // Set the speed (Bauds)
  108. {
  109. case 110 : dcbSerialParams.BaudRate=CBR_110; break;
  110. case 300 : dcbSerialParams.BaudRate=CBR_300; break;
  111. case 600 : dcbSerialParams.BaudRate=CBR_600; break;
  112. case 1200 : dcbSerialParams.BaudRate=CBR_1200; break;
  113. case 2400 : dcbSerialParams.BaudRate=CBR_2400; break;
  114. case 4800 : dcbSerialParams.BaudRate=CBR_4800; break;
  115. case 9600 : dcbSerialParams.BaudRate=CBR_9600; break;
  116. case 14400 : dcbSerialParams.BaudRate=CBR_14400; break;
  117. case 19200 : dcbSerialParams.BaudRate=CBR_19200; break;
  118. case 38400 : dcbSerialParams.BaudRate=CBR_38400; break;
  119. case 56000 : dcbSerialParams.BaudRate=CBR_56000; break;
  120. case 57600 : dcbSerialParams.BaudRate=CBR_57600; break;
  121. case 115200 : dcbSerialParams.BaudRate=CBR_115200; break;
  122. case 128000 : dcbSerialParams.BaudRate=CBR_128000; break;
  123. case 256000 : dcbSerialParams.BaudRate=CBR_256000; break;
  124. default : return -4;
  125. }
  126. dcbSerialParams.ByteSize=8; // 8 bit data
  127. dcbSerialParams.StopBits=ONESTOPBIT; // One stop bit
  128. dcbSerialParams.Parity=NOPARITY; // No parity
  129. if(!SetCommState(hSerial, &dcbSerialParams)) // Write the parameters
  130. return -5; // Error while writing
  131.  
  132. // Set TimeOut
  133. timeouts.ReadIntervalTimeout=0; // Set the Timeout parameters
  134. timeouts.ReadTotalTimeoutConstant=MAXDWORD; // No TimeOut
  135. timeouts.ReadTotalTimeoutMultiplier=0;
  136. timeouts.WriteTotalTimeoutConstant=MAXDWORD;
  137. timeouts.WriteTotalTimeoutMultiplier=0;
  138. if(!SetCommTimeouts(hSerial, &timeouts)) // Write the parameters
  139. return -6; // Error while writting the parameters
  140. return 1; // Opening successfull
  141.  
  142. #endif
  143. #ifdef __linux__
  144. struct termios options; // Structure with the device's options
  145.  
  146.  
  147. // Open device
  148. fd = open(Device, O_RDWR | O_NOCTTY | O_NDELAY); // Open port
  149. if (fd == -1) return -2; // If the device is not open, return -1
  150. fcntl(fd, F_SETFL, FNDELAY); // Open the device in nonblocking mode
  151.  
  152. // Set parameters
  153. tcgetattr(fd, &options); // Get the current options of the port
  154. bzero(&options, sizeof(options)); // Clear all the options
  155. speed_t Speed;
  156. switch (Bauds) // Set the speed (Bauds)
  157. {
  158. case 110 : Speed=B110; break;
  159. case 300 : Speed=B300; break;
  160. case 600 : Speed=B600; break;
  161. case 1200 : Speed=B1200; break;
  162. case 2400 : Speed=B2400; break;
  163. case 4800 : Speed=B4800; break;
  164. case 9600 : Speed=B9600; break;
  165. case 19200 : Speed=B19200; break;
  166. case 38400 : Speed=B38400; break;
  167. case 57600 : Speed=B57600; break;
  168. case 115200 : Speed=B115200; break;
  169. default : return -4;
  170. }
  171. cfsetispeed(&options, Speed); // Set the baud rate at 115200 bauds
  172. cfsetospeed(&options, Speed);
  173. options.c_cflag |= ( CLOCAL | CREAD | CS8); // Configure the device : 8 bits, no parity, no control
  174. options.c_iflag |= ( IGNPAR | IGNBRK );
  175. options.c_cc[VTIME]=0; // Timer unused
  176. options.c_cc[VMIN]=0; // At least on character before satisfy reading
  177. tcsetattr(fd, TCSANOW, &options); // Activate the settings
  178. return (1); // Success
  179. #endif
  180. }
  181.  
  182.  
  183. /*!
  184. \brief Close the connection with the current device
  185. */
  186. void serialib::Close()
  187. {
  188. #if defined (_WIN32) || defined( _WIN64)
  189. CloseHandle(hSerial);
  190. #endif
  191. #ifdef __linux__
  192. close (fd);
  193. #endif
  194. }
  195.  
  196.  
  197.  
  198.  
  199. //___________________________________________
  200. // ::: Read/Write operation on characters :::
  201.  
  202.  
  203.  
  204. /*!
  205. \brief Write a char on the current serial port
  206. \param Byte : char to send on the port (must be terminated by '\0')
  207. \return 1 success
  208. \return -1 error while writting data
  209. */
  210. char serialib::WriteChar(const char Byte)
  211. {
  212. #if defined (_WIN32) || defined( _WIN64)
  213. DWORD dwBytesWritten; // Number of bytes written
  214. if(!WriteFile(hSerial,&Byte,1,&dwBytesWritten,NULL)) // Write the char
  215. return -1; // Error while writing
  216. return 1; // Write operation successfull
  217. #endif
  218. #ifdef __linux__
  219. if (write(fd,&Byte,1)!=1) // Write the char
  220. return -1; // Error while writting
  221. return 1; // Write operation successfull
  222. #endif
  223. }
  224.  
  225.  
  226.  
  227. //________________________________________
  228. // ::: Read/Write operation on strings :::
  229.  
  230.  
  231. /*!
  232. \brief Write a string on the current serial port
  233. \param String : string to send on the port (must be terminated by '\0')
  234. \return 1 success
  235. \return -1 error while writting data
  236. */
  237. char serialib::WriteString(const char *String)
  238. {
  239. #if defined (_WIN32) || defined( _WIN64)
  240. DWORD dwBytesWritten; // Number of bytes written
  241. if(!WriteFile(hSerial,String,strlen(String),&dwBytesWritten,NULL)) // Write the string
  242. return -1; // Error while writing
  243. return 1; // Write operation successfull
  244. #endif
  245. #ifdef __linux__
  246. int Lenght=strlen(String); // Lenght of the string
  247. if (write(fd,String,Lenght)!=Lenght) // Write the string
  248. return -1; // error while writing
  249. return 1; // Write operation successfull
  250. #endif
  251. }
  252.  
  253. // _____________________________________
  254. // ::: Read/Write operation on bytes :::
  255.  
  256.  
  257.  
  258. /*!
  259. \brief Write an array of data on the current serial port
  260. \param Buffer : array of bytes to send on the port
  261. \param NbBytes : number of byte to send
  262. \return 1 success
  263. \return -1 error while writting data
  264. */
  265. char serialib::Write(const void *Buffer, const unsigned int NbBytes)
  266. {
  267. #if defined (_WIN32) || defined( _WIN64)
  268. DWORD dwBytesWritten; // Number of byte written
  269. if(!WriteFile(hSerial, Buffer, NbBytes, &dwBytesWritten, NULL)) // Write data
  270. return -1; // Error while writing
  271. return 1; // Write operation successfull
  272. #endif
  273. #ifdef __linux__
  274. if (write (fd,Buffer,NbBytes)!=(ssize_t)NbBytes) // Write data
  275. return -1; // Error while writing
  276. return 1; // Write operation successfull
  277. #endif
  278. }
  279.  
  280.  
  281.  
  282. /*!
  283. \brief Wait for a byte from the serial device and return the data read
  284. \param pByte : data read on the serial device
  285. \param TimeOut_ms : delay of timeout before giving up the reading
  286. If set to zero, timeout is disable (Optional)
  287. \return 1 success
  288. \return 0 Timeout reached
  289. \return -1 error while setting the Timeout
  290. \return -2 error while reading the byte
  291. */
  292. char serialib::ReadChar(char *pByte,unsigned int TimeOut_ms)
  293. {
  294. #if defined (_WIN32) || defined(_WIN64)
  295.  
  296. DWORD dwBytesRead = 0;
  297. timeouts.ReadTotalTimeoutConstant=TimeOut_ms; // Set the TimeOut
  298. if(!SetCommTimeouts(hSerial, &timeouts)) // Write the parameters
  299. return -1; // Error while writting the parameters
  300. if(!ReadFile(hSerial,pByte, 1, &dwBytesRead, NULL)) // Read the byte
  301. return -2; // Error while reading the byte
  302. if (dwBytesRead==0) return 0; // Return 1 if the timeout is reached
  303. return 1; // Success
  304. #endif
  305. #ifdef __linux__
  306. TimeOut Timer; // Timer used for timeout
  307. Timer.InitTimer(); // Initialise the timer
  308. while (Timer.ElapsedTime_ms()<TimeOut_ms || TimeOut_ms==0) // While Timeout is not reached
  309. {
  310. switch (read(fd,pByte,1)) { // Try to read a byte on the device
  311. case 1 : return 1; // Read successfull
  312. case -1 : return -2; // Error while reading
  313. }
  314. }
  315. return 0;
  316. #endif
  317. }
  318.  
  319.  
  320.  
  321. /*!
  322. \brief Read a string from the serial device (without TimeOut)
  323. \param String : string read on the serial device
  324. \param FinalChar : final char of the string
  325. \param MaxNbBytes : maximum allowed number of bytes read
  326. \return >0 success, return the number of bytes read
  327. \return -1 error while setting the Timeout
  328. \return -2 error while reading the byte
  329. \return -3 MaxNbBytes is reached
  330. */
  331. int serialib::ReadStringNoTimeOut(char *String,char FinalChar,unsigned int MaxNbBytes)
  332. {
  333. unsigned int NbBytes=0; // Number of bytes read
  334. char ret; // Returned value from Read
  335. while (NbBytes<MaxNbBytes) // While the buffer is not full
  336. { // Read a byte with the restant time
  337. ret=ReadChar(&String[NbBytes]);
  338. if (ret==1) // If a byte has been read
  339. {
  340. if (String[NbBytes]==FinalChar) // Check if it is the final char
  341. {
  342. String [++NbBytes]=0; // Yes : add the end character 0
  343. return NbBytes; // Return the number of bytes read
  344. }
  345. NbBytes++; // If not, just increase the number of bytes read
  346. }
  347. if (ret<0) return ret; // Error while reading : return the error number
  348. }
  349. return -3; // Buffer is full : return -3
  350. }
  351.  
  352. /*!
  353. \brief Read a string from the serial device (with timeout)
  354. \param String : string read on the serial device
  355. \param FinalChar : final char of the string
  356. \param MaxNbBytes : maximum allowed number of bytes read
  357. \param TimeOut_ms : delay of timeout before giving up the reading (optional)
  358. \return >0 success, return the number of bytes read
  359. \return 0 timeout is reached
  360. \return -1 error while setting the Timeout
  361. \return -2 error while reading the byte
  362. \return -3 MaxNbBytes is reached
  363. */
  364. int serialib::ReadString(char *String,char FinalChar,unsigned int MaxNbBytes,unsigned int TimeOut_ms)
  365. {
  366. if (TimeOut_ms==0)
  367. return ReadStringNoTimeOut(String,FinalChar,MaxNbBytes);
  368.  
  369. unsigned int NbBytes=0; // Number of bytes read
  370. char ret; // Returned value from Read
  371. TimeOut Timer; // Timer used for timeout
  372. long int TimeOutParam;
  373. Timer.InitTimer(); // Initialize the timer
  374.  
  375. while (NbBytes<MaxNbBytes) // While the buffer is not full
  376. { // Read a byte with the restant time
  377. TimeOutParam=TimeOut_ms-Timer.ElapsedTime_ms(); // Compute the TimeOut for the call of ReadChar
  378. if (TimeOutParam>0) // If the parameter is higher than zero
  379. {
  380. ret=ReadChar(&String[NbBytes],TimeOutParam); // Wait for a byte on the serial link
  381. if (ret==1) // If a byte has been read
  382. {
  383.  
  384. if (String[NbBytes]==FinalChar) // Check if it is the final char
  385. {
  386. String [++NbBytes]=0; // Yes : add the end character 0
  387. return NbBytes; // Return the number of bytes read
  388. }
  389. NbBytes++; // If not, just increase the number of bytes read
  390. }
  391. if (ret<0) return ret; // Error while reading : return the error number
  392. }
  393. if (Timer.ElapsedTime_ms()>TimeOut_ms) { // Timeout is reached
  394. String[NbBytes]=0; // Add the end caracter
  395. return 0; // Return 0
  396. }
  397. }
  398. return -3; // Buffer is full : return -3
  399. }
  400.  
  401.  
  402. /*!
  403. \brief Read an array of bytes from the serial device (with timeout)
  404. \param Buffer : array of bytes read from the serial device
  405. \param MaxNbBytes : maximum allowed number of bytes read
  406. \param TimeOut_ms : delay of timeout before giving up the reading
  407. \return 1 success, return the number of bytes read
  408. \return 0 Timeout reached
  409. \return -1 error while setting the Timeout
  410. \return -2 error while reading the byte
  411. */
  412. int serialib::Read (void *Buffer,unsigned int MaxNbBytes,unsigned int TimeOut_ms)
  413. {
  414. #if defined (_WIN32) || defined(_WIN64)
  415. DWORD dwBytesRead = 0;
  416. timeouts.ReadTotalTimeoutConstant=(DWORD)TimeOut_ms; // Set the TimeOut
  417. if(!SetCommTimeouts(hSerial, &timeouts)) // Write the parameters
  418. return -1; // Error while writting the parameters
  419. if(!ReadFile(hSerial,Buffer,(DWORD)MaxNbBytes,&dwBytesRead, NULL)) // Read the bytes from the serial device
  420. return -2; // Error while reading the byte
  421. if (dwBytesRead!=(DWORD)MaxNbBytes) return 0; // Return 0 if the timeout is reached
  422. return 1; // Success
  423. #endif
  424. #ifdef __linux__
  425. TimeOut Timer; // Timer used for timeout
  426. Timer.InitTimer(); // Initialise the timer
  427. unsigned int NbByteRead=0;
  428. while (Timer.ElapsedTime_ms()<TimeOut_ms || TimeOut_ms==0) // While Timeout is not reached
  429. {
  430. unsigned char* Ptr=(unsigned char*)Buffer+NbByteRead; // Compute the position of the current byte
  431. int Ret=read(fd,(void*)Ptr,MaxNbBytes-NbByteRead); // Try to read a byte on the device
  432. if (Ret==-1) return -2; // Error while reading
  433. if (Ret>0) { // One or several byte(s) has been read on the device
  434. NbByteRead+=Ret; // Increase the number of read bytes
  435. if (NbByteRead>=MaxNbBytes) // Success : bytes has been read
  436. return 1;
  437. }
  438. }
  439. return 0; // Timeout reached, return 0
  440. #endif
  441. }
  442.  
  443.  
  444.  
  445.  
  446. // _________________________
  447. // ::: Special operation :::
  448.  
  449.  
  450.  
  451. /*!
  452. \brief Empty receiver buffer (UNIX only)
  453. */
  454.  
  455. void serialib::FlushReceiver()
  456. {
  457. #ifdef __linux__
  458. tcflush(fd,TCIFLUSH);
  459. #endif
  460. }
  461.  
  462.  
  463.  
  464. /*!
  465. \brief Return the number of bytes in the received buffer (UNIX only)
  466. \return The number of bytes in the received buffer
  467. */
  468. int serialib::Peek()
  469. {
  470. int Nbytes=0;
  471. #ifdef __linux__
  472. ioctl(fd, FIONREAD, &Nbytes);
  473. #endif
  474. return Nbytes;
  475. }
  476.  
  477. // ******************************************
  478. // Class TimeOut
  479. // ******************************************
  480.  
  481.  
  482. /*!
  483. \brief Constructor of the class TimeOut.
  484. */
  485. // Constructor
  486. TimeOut::TimeOut()
  487. {}
  488.  
  489. /*!
  490. \brief Initialise the timer. It writes the current time of the day in the structure PreviousTime.
  491. */
  492. //Initialize the timer
  493. void TimeOut::InitTimer()
  494. {
  495. gettimeofday(&PreviousTime, NULL);
  496. }
  497.  
  498. /*!
  499. \brief Returns the time elapsed since initialization. It write the current time of the day in the structure CurrentTime.
  500. Then it returns the difference between CurrentTime and PreviousTime.
  501. \return The number of microseconds elapsed since the functions InitTimer was called.
  502. */
  503. //Return the elapsed time since initialization
  504. unsigned long int TimeOut::ElapsedTime_ms()
  505. {
  506. struct timeval CurrentTime;
  507. int sec,usec;
  508. gettimeofday(&CurrentTime, NULL); // Get current time
  509. sec=CurrentTime.tv_sec-PreviousTime.tv_sec; // Compute the number of second elapsed since last call
  510. usec=CurrentTime.tv_usec-PreviousTime.tv_usec; // Compute
  511. if (usec<0) { // If the previous usec is higher than the current one
  512. usec=1000000-PreviousTime.tv_usec+CurrentTime.tv_usec; // Recompute the microseonds
  513. sec--; // Substract one second
  514. }
  515. return sec*1000+usec/1000;
  516. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement