| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- // SerialClass.cpp: implementation of the SSerialClass class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "serial.h"
- #include "public.h"
- // #include <string.h>
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- //数据位 停止位 校验位 流控
- void SSerial::SetCtrl (int iDataBit, int iStopBit, Parity ParityBit, FlowCtl iFlow)
- {
- m_cDataBit = iDataBit;
- m_cParityBit = ParityBit;
- m_cStopBit = iStopBit;
- m_cFlow = iFlow;
- }
- //串口操作类,初始化
- SSerial::SSerial ( void )
- {
- m_cDataBit = 8;
- m_cParityBit = Parity_NO;
- m_cStopBit = 1;
- m_cFlow = Flow_NO;
- m_hCom = -1;
- }
- SSerial::~SSerial ( void )
- {
- if ( m_hCom != -1 )
- close(m_hCom);
- }
- //端口(如ttymxc3),波特率(如9600)
- bool SSerial::Open (const char* sPort, const int iBaut )
- {
- if ( m_hCom != -1 )
- {
- close(m_hCom);
- m_hCom = -1;
- }
- char sPortstr[32];
- sprintf ( sPortstr, "/dev/%s", sPort );
- //打开串口
- //O_NOCTTY: 通知系统,该程序不想成为此端口的“控制终端”。
- // 如果不设,则任何输入(如键盘的中断信号)都会影响程序的运行
- //O_NODELAY: 该程序不关注DCD信号线所处的状态,即不管对端设备是在运行还是挂起。
- // 若不设置,则程序会被置为睡眠状态,直到DCD信号低为止(可能无流控制时无效)
- //非阻塞模式: read没有读到数据立即返回-1
- //超时0秒时: read没有读到数据立即返回 0 (设置了超时的阻塞模式)
- m_hCom = open ( sPortstr, O_RDWR | O_NOCTTY ); //O_NDELAY 非阻塞,未读到数据立即返回
- if ( m_hCom == -1 )
- return false;
- tcflush(m_hCom, TCIOFLUSH); //溢出的数据可以接收,但不读
- m_nBaut = iBaut;
- int iSpeed = 0;
- int iSpeedSet[] =
- {
- B50, B75, B110, B134, B150,
- B200, B300, B600, B1200, B1800,
- B2400, B4800, B9600, B19200, B38400,
- B57600, B115200,B230400,B460800,B576000,
- B1152000
- };
- int iSpeedIn[] =
- {
- 50, 75, 110, 134, 150,
- 200, 300, 600, 1200, 1800,
- 2400, 4800, 9600, 19200, 38400,
- 57600, 115200, 230400, 460800, 576000,
- 1152000
- };
- for (int ipos = 0; ipos < sizeof(iSpeedSet); ipos++)
- {
- if (iBaut == iSpeedIn[ipos])
- {
- iSpeed = iSpeedSet[ipos];
- break;
- }
- }
- termios tios;
- //------------设置端口属性----------------
- //baudrates
- memset(&tios, 0, sizeof(tios));
- tcgetattr(m_hCom, &tios); //get the serial port attributions
- cfsetispeed(&tios, iSpeed); //填入串口输入端的波特率
- cfsetospeed(&tios, iSpeed); //填入串口输出端的波特率
- tios.c_cflag &= ~CSIZE; //3、以下为设置串口属性
- //控制模式,data bits
- tios.c_cflag &= ~CSIZE; //控制模式,屏蔽字符大小位
- switch(m_cDataBit)
- {
- case 5:
- tios.c_cflag |= CS5;
- case 6:
- tios.c_cflag |= CS6;
- case 7:
- tios.c_cflag |= CS7;
- default:
- tios.c_cflag |= CS8;
- }
- //控制模式 奇偶检验位
- switch(m_cParityBit)
- {
- case Parity_ODD:
- tios.c_cflag |= (PARODD | PARENB);
- tios.c_iflag |= (INPCK);
- break;
- case Parity_EVEN:
- tios.c_cflag |= PARENB;
- tios.c_cflag &= ~PARODD;
- tios.c_iflag |= (INPCK); //Disnable parity checking
- break;
- default:
- tios.c_cflag &= ~PARENB; //no parity check
- tios.c_iflag &= ~INPCK; //Disnable parity checking
- break;
- }
- //控制模式,stop bits
- switch ( m_cStopBit )
- {
- case 2:
- tios.c_cflag |= CSTOPB; //2 stop bits
- break;
- default:
- tios.c_cflag &= ~CSTOPB; //1 stop bits
- break;
- }
- //*
- tios.c_cflag &= ~CRTSCTS; //no flow control
- tios.c_iflag &= ~(IXON | IXOFF | IXANY); //software flow control
- // 控制模式,flow control
- switch(m_cFlow)
- {
- case Flow_CTS:
- tios.c_cflag |= CRTSCTS; //hardware flow control
- break;
- case Flow_XONOFF:
- tios.c_iflag |= (IXON | IXOFF | IXANY); //software flow control
- break;
- default:
- break;
- }
- tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*Input*/
- tios.c_oflag &= ~OPOST; /*Output*/
- tios.c_oflag &= ~(ONLCR | OCRNL);
- tios.c_iflag &= ~(INLCR | ICRNL);
- //other attributions default
- tios.c_cc[VMIN] = 0; //控制字符, 所要读取字符的最小数量
- tios.c_cc[VTIME] = 0; //控制字符, 读取第一个字符的等待时间 unit: (1/10)second
- if (tcsetattr(m_hCom, TCSANOW, &tios) < 0)
- {
- close(m_hCom);
- m_hCom = -1;
- return false;
- } //8、使以上设置的属性立即生效
- int modemcontrl;
- modemcontrl = TIOCM_DTR;
- ioctl(m_hCom,TIOCMBIS,&modemcontrl);
- modemcontrl = TIOCM_RTS;
- ioctl(m_hCom,TIOCMBIS,&modemcontrl);
- return true;
- }
- bool SSerial::IsOpen()
- {
- return m_hCom != -1;
- }
- // 串口清理
- void SSerial::Close ()
- {
- if ( m_hCom != -1 )
- {
- close(m_hCom);
- m_hCom = -1;
- }
- }
- //清除缓存
- void SSerial::Flush()
- {
- tcflush(m_hCom, TCIOFLUSH);
- }
- // 通过串口向外发N个字节
- // data: 发送字节首地址
- // datalen: 发送字节长度
- // Return: -1: 发送失败 >0:已经发送的字节
- int SSerial::SendOnce(const char *sData, int iLen, int timeout )
- {
- // SetTimeout(timeout);
- return write( m_hCom, sData, iLen); //实际写入的长度
- }
- // 从串口读入N个字节
- // Input: data: 读入字节首地址
- // datalen: 发送字节长度
- // timeout: 超时时间,单位秒 <0 时代表无限期等待
- // Return: -1: 读入失败 >0:已经读入的字节
- int SSerial::ReceiveOnce ( char *sData, int iLen, int iTimeout )
- {
- SetTimeout(iTimeout);
- return read(m_hCom, sData, iLen);
- }
- //设置超时,单位毫秒
- void SSerial::SetTimeout(unsigned int msec)
- {
- fd_set fs_read;
- struct timeval tv_timeout;
- FD_ZERO(&fs_read);
- FD_SET(m_hCom, &fs_read);
- if (msec < 0) msec = 100;
- if (msec > 120000) msec = 120000;
- tv_timeout.tv_sec = msec / 1000; //time out : unit sec
- tv_timeout.tv_usec = (msec % 1000) * 1000;
- select( m_hCom+1, &fs_read, NULL, NULL, &tv_timeout);
- }
- // data: 发送字节首地址
- // datalen: 发送字节长度
- // Return: -1: 发送失败 >0:已经发送的字节
- int SSerial::Send(const char *sData, int iLen, int iTimeout)
- {
- if (IsOpen() == false) //串口未被打开
- return -1;
- int nBytesSent = 0;
- int nBytesThisTime;
- if (iTimeout <= 0) iTimeout = 100;
- INT64 iNow = GetSystemTime();
- INT64 iEnd = iNow + iTimeout;
- do{
- int iTimeWait = iEnd - iNow;
- if (iTimeWait < 100) iTimeWait = 100;
- nBytesThisTime = SendOnce(sData, iLen - nBytesSent, iTimeWait);
- if (nBytesThisTime < 0) return -1;
- nBytesSent += nBytesThisTime;
- if (nBytesSent >= iLen) break;
- sData += nBytesThisTime;
- Sleep(10);
- iNow = GetSystemTime();
- }while(iNow < iEnd);
- return nBytesSent;
- }
- // Input: data: 读入字节首地址
- // datalen: 发送字节长度
- // timeout: 超时时间,单位ms <0 时代表无限期等待
- // Return: -1: 读入失败 >0:已经读入的字节
- int SSerial::Receive ( char *sData, int iLen, int iTimeout )
- {
- int nBytesRead = 0;
- int nBytesThisTime=0;
- if (iTimeout <= 0) iTimeout = 100;
- INT64 iNow = GetSystemTime();
- INT64 iEnd = iNow + iTimeout;
- do{
- int iTimeWait = iEnd - iNow;
- if (iTimeWait < 100) iTimeWait = 100;
- nBytesThisTime = ReceiveOnce(sData, iLen - nBytesRead, iTimeWait);
- if (nBytesThisTime < 0) return nBytesRead;
- nBytesRead += nBytesThisTime;
- if (nBytesRead >= iLen) break;
- sData += nBytesThisTime;
- Sleep(10);
- iNow = GetSystemTime();
- }while(iNow < iEnd);
- if (nBytesRead)
- return nBytesRead;
- else
- return 0;
- }
|