serial.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. // SerialClass.cpp: implementation of the SSerialClass class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "serial.h"
  5. #include "public.h"
  6. // #include <string.h>
  7. ////////////////////////////////////////////////////////////////////////////////////////////////////
  8. //数据位 停止位 校验位 流控
  9. void SSerial::SetCtrl (int iDataBit, int iStopBit, Parity ParityBit, FlowCtl iFlow)
  10. {
  11. m_cDataBit = iDataBit;
  12. m_cParityBit = ParityBit;
  13. m_cStopBit = iStopBit;
  14. m_cFlow = iFlow;
  15. }
  16. //串口操作类,初始化
  17. SSerial::SSerial ( void )
  18. {
  19. m_cDataBit = 8;
  20. m_cParityBit = Parity_NO;
  21. m_cStopBit = 1;
  22. m_cFlow = Flow_NO;
  23. m_hCom = -1;
  24. }
  25. SSerial::~SSerial ( void )
  26. {
  27. if ( m_hCom != -1 )
  28. close(m_hCom);
  29. }
  30. //端口(如ttymxc3),波特率(如9600)
  31. bool SSerial::Open (const char* sPort, const int iBaut )
  32. {
  33. if ( m_hCom != -1 )
  34. {
  35. close(m_hCom);
  36. m_hCom = -1;
  37. }
  38. char sPortstr[32];
  39. sprintf ( sPortstr, "/dev/%s", sPort );
  40. //打开串口
  41. //O_NOCTTY: 通知系统,该程序不想成为此端口的“控制终端”。
  42. // 如果不设,则任何输入(如键盘的中断信号)都会影响程序的运行
  43. //O_NODELAY: 该程序不关注DCD信号线所处的状态,即不管对端设备是在运行还是挂起。
  44. // 若不设置,则程序会被置为睡眠状态,直到DCD信号低为止(可能无流控制时无效)
  45. //非阻塞模式: read没有读到数据立即返回-1
  46. //超时0秒时: read没有读到数据立即返回 0 (设置了超时的阻塞模式)
  47. m_hCom = open ( sPortstr, O_RDWR | O_NOCTTY ); //O_NDELAY 非阻塞,未读到数据立即返回
  48. if ( m_hCom == -1 )
  49. return false;
  50. tcflush(m_hCom, TCIOFLUSH); //溢出的数据可以接收,但不读
  51. m_nBaut = iBaut;
  52. int iSpeed = 0;
  53. int iSpeedSet[] =
  54. {
  55. B50, B75, B110, B134, B150,
  56. B200, B300, B600, B1200, B1800,
  57. B2400, B4800, B9600, B19200, B38400,
  58. B57600, B115200,B230400,B460800,B576000,
  59. B1152000
  60. };
  61. int iSpeedIn[] =
  62. {
  63. 50, 75, 110, 134, 150,
  64. 200, 300, 600, 1200, 1800,
  65. 2400, 4800, 9600, 19200, 38400,
  66. 57600, 115200, 230400, 460800, 576000,
  67. 1152000
  68. };
  69. for (int ipos = 0; ipos < sizeof(iSpeedSet); ipos++)
  70. {
  71. if (iBaut == iSpeedIn[ipos])
  72. {
  73. iSpeed = iSpeedSet[ipos];
  74. break;
  75. }
  76. }
  77. termios tios;
  78. //------------设置端口属性----------------
  79. //baudrates
  80. memset(&tios, 0, sizeof(tios));
  81. tcgetattr(m_hCom, &tios); //get the serial port attributions
  82. cfsetispeed(&tios, iSpeed); //填入串口输入端的波特率
  83. cfsetospeed(&tios, iSpeed); //填入串口输出端的波特率
  84. tios.c_cflag &= ~CSIZE; //3、以下为设置串口属性
  85. //控制模式,data bits
  86. tios.c_cflag &= ~CSIZE; //控制模式,屏蔽字符大小位
  87. switch(m_cDataBit)
  88. {
  89. case 5:
  90. tios.c_cflag |= CS5;
  91. case 6:
  92. tios.c_cflag |= CS6;
  93. case 7:
  94. tios.c_cflag |= CS7;
  95. default:
  96. tios.c_cflag |= CS8;
  97. }
  98. //控制模式 奇偶检验位
  99. switch(m_cParityBit)
  100. {
  101. case Parity_ODD:
  102. tios.c_cflag |= (PARODD | PARENB);
  103. tios.c_iflag |= (INPCK);
  104. break;
  105. case Parity_EVEN:
  106. tios.c_cflag |= PARENB;
  107. tios.c_cflag &= ~PARODD;
  108. tios.c_iflag |= (INPCK); //Disnable parity checking
  109. break;
  110. default:
  111. tios.c_cflag &= ~PARENB; //no parity check
  112. tios.c_iflag &= ~INPCK; //Disnable parity checking
  113. break;
  114. }
  115. //控制模式,stop bits
  116. switch ( m_cStopBit )
  117. {
  118. case 2:
  119. tios.c_cflag |= CSTOPB; //2 stop bits
  120. break;
  121. default:
  122. tios.c_cflag &= ~CSTOPB; //1 stop bits
  123. break;
  124. }
  125. //*
  126. tios.c_cflag &= ~CRTSCTS; //no flow control
  127. tios.c_iflag &= ~(IXON | IXOFF | IXANY); //software flow control
  128. // 控制模式,flow control
  129. switch(m_cFlow)
  130. {
  131. case Flow_CTS:
  132. tios.c_cflag |= CRTSCTS; //hardware flow control
  133. break;
  134. case Flow_XONOFF:
  135. tios.c_iflag |= (IXON | IXOFF | IXANY); //software flow control
  136. break;
  137. default:
  138. break;
  139. }
  140. tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
  141. tios.c_oflag &= ~OPOST; /*Output*/
  142. tios.c_oflag &= ~(ONLCR | OCRNL);
  143. tios.c_iflag &= ~(INLCR | ICRNL);
  144. //other attributions default
  145. tios.c_cc[VMIN] = 0; //控制字符, 所要读取字符的最小数量
  146. tios.c_cc[VTIME] = 0; //控制字符, 读取第一个字符的等待时间 unit: (1/10)second
  147. if (tcsetattr(m_hCom, TCSANOW, &tios) < 0)
  148. {
  149. close(m_hCom);
  150. m_hCom = -1;
  151. return false;
  152. } //8、使以上设置的属性立即生效
  153. int modemcontrl;
  154. modemcontrl = TIOCM_DTR;
  155. ioctl(m_hCom,TIOCMBIS,&modemcontrl);
  156. modemcontrl = TIOCM_RTS;
  157. ioctl(m_hCom,TIOCMBIS,&modemcontrl);
  158. return true;
  159. }
  160. bool SSerial::IsOpen()
  161. {
  162. return m_hCom != -1;
  163. }
  164. // 串口清理
  165. void SSerial::Close ()
  166. {
  167. if ( m_hCom != -1 )
  168. {
  169. close(m_hCom);
  170. m_hCom = -1;
  171. }
  172. }
  173. //清除缓存
  174. void SSerial::Flush()
  175. {
  176. tcflush(m_hCom, TCIOFLUSH);
  177. }
  178. // 通过串口向外发N个字节
  179. // data: 发送字节首地址
  180. // datalen: 发送字节长度
  181. // Return: -1: 发送失败 >0:已经发送的字节
  182. int SSerial::SendOnce(const char *sData, int iLen, int timeout )
  183. {
  184. // SetTimeout(timeout);
  185. return write( m_hCom, sData, iLen); //实际写入的长度
  186. }
  187. // 从串口读入N个字节
  188. // Input: data: 读入字节首地址
  189. // datalen: 发送字节长度
  190. // timeout: 超时时间,单位秒 <0 时代表无限期等待
  191. // Return: -1: 读入失败 >0:已经读入的字节
  192. int SSerial::ReceiveOnce ( char *sData, int iLen, int iTimeout )
  193. {
  194. SetTimeout(iTimeout);
  195. return read(m_hCom, sData, iLen);
  196. }
  197. //设置超时,单位毫秒
  198. void SSerial::SetTimeout(unsigned int msec)
  199. {
  200. fd_set fs_read;
  201. struct timeval tv_timeout;
  202. FD_ZERO(&fs_read);
  203. FD_SET(m_hCom, &fs_read);
  204. if (msec < 0) msec = 100;
  205. if (msec > 120000) msec = 120000;
  206. tv_timeout.tv_sec = msec / 1000; //time out : unit sec
  207. tv_timeout.tv_usec = (msec % 1000) * 1000;
  208. select( m_hCom+1, &fs_read, NULL, NULL, &tv_timeout);
  209. }
  210. // data: 发送字节首地址
  211. // datalen: 发送字节长度
  212. // Return: -1: 发送失败 >0:已经发送的字节
  213. int SSerial::Send(const char *sData, int iLen, int iTimeout)
  214. {
  215. if (IsOpen() == false) //串口未被打开
  216. return -1;
  217. int nBytesSent = 0;
  218. int nBytesThisTime;
  219. if (iTimeout <= 0) iTimeout = 100;
  220. INT64 iNow = GetSystemTime();
  221. INT64 iEnd = iNow + iTimeout;
  222. do{
  223. int iTimeWait = iEnd - iNow;
  224. if (iTimeWait < 100) iTimeWait = 100;
  225. nBytesThisTime = SendOnce(sData, iLen - nBytesSent, iTimeWait);
  226. if (nBytesThisTime < 0) return -1;
  227. nBytesSent += nBytesThisTime;
  228. if (nBytesSent >= iLen) break;
  229. sData += nBytesThisTime;
  230. Sleep(10);
  231. iNow = GetSystemTime();
  232. }while(iNow < iEnd);
  233. return nBytesSent;
  234. }
  235. // Input: data: 读入字节首地址
  236. // datalen: 发送字节长度
  237. // timeout: 超时时间,单位ms <0 时代表无限期等待
  238. // Return: -1: 读入失败 >0:已经读入的字节
  239. int SSerial::Receive ( char *sData, int iLen, int iTimeout )
  240. {
  241. int nBytesRead = 0;
  242. int nBytesThisTime=0;
  243. if (iTimeout <= 0) iTimeout = 100;
  244. INT64 iNow = GetSystemTime();
  245. INT64 iEnd = iNow + iTimeout;
  246. do{
  247. int iTimeWait = iEnd - iNow;
  248. if (iTimeWait < 100) iTimeWait = 100;
  249. nBytesThisTime = ReceiveOnce(sData, iLen - nBytesRead, iTimeWait);
  250. if (nBytesThisTime < 0) return nBytesRead;
  251. nBytesRead += nBytesThisTime;
  252. if (nBytesRead >= iLen) break;
  253. sData += nBytesThisTime;
  254. Sleep(10);
  255. iNow = GetSystemTime();
  256. }while(iNow < iEnd);
  257. if (nBytesRead)
  258. return nBytesRead;
  259. else
  260. return 0;
  261. }