| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506 |
- // 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;
- }
- #ifdef WIN32
- //串口操作类,初始化
- SSerial::SSerial ( void )
- {
- m_cDataBit = 8;
- m_cParityBit = Parity_NO;
- m_cStopBit = 1;
- m_cFlow = Flow_NO;
- m_hCom = NULL;
- }
- SSerial::~SSerial ( void )
- {
- CloseHandle(m_hCom);
- m_hCom=0;
- }
- // //端口(如COM3),波特率(如9600)
- bool SSerial::Open (const char* sPort, const int baut )
- {
- if (m_hCom) return true;
- char sOpenPort[32];
- sprintf(sOpenPort,"\\\\.\\%s",sPort);
- m_hCom = CreateFileA(sOpenPort, GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
- if (m_hCom < 0 || m_hCom > (HANDLE)0x7fffffff ) {
- m_hCom = NULL;
- return false;
- }
- if( ! ::SetCommMask( m_hCom, 0 ) )
- {
- ::CloseHandle( m_hCom );
- return false;
- }
- ::SetCommMask(m_hCom, EV_RXCHAR | EV_CTS | EV_DSR | EV_RLSD | EV_BREAK | EV_ERR);
- if( ! ::SetupComm( m_hCom, 10000L, 10000L ) )
- {
- ::CloseHandle( m_hCom );
- return false;
- }
- // 超时时间参数设置
- COMMTIMEOUTS ComTim;
- ComTim.ReadIntervalTimeout = MAXDWORD;
- ComTim.ReadTotalTimeoutMultiplier = 0;
- ComTim.ReadTotalTimeoutConstant = 0;
- ComTim.WriteTotalTimeoutMultiplier = 0;
- ComTim.WriteTotalTimeoutConstant = 20000;
- // 设置超时
- if( ! ::SetCommTimeouts( m_hCom, &ComTim ) )
- {
- ::CloseHandle( m_hCom );
- return false;
- }
- DCB dcb;
- GetCommState(m_hCom, &dcb);
- dcb.fBinary = TRUE;
- dcb.fAbortOnError = TRUE;
- dcb.fNull = FALSE;
- m_nBaut = baut;
- dcb.BaudRate = m_nBaut;
- dcb.ByteSize = m_cDataBit;
- switch (m_cStopBit) {
- case 1: /*one stop bit*/
- dcb.StopBits = ONESTOPBIT;
- //SetCommConfig(m_hDeviceFile, &mConfig, sizeof(COMMCONFIG));
- break;
- case 2: /*two stop bits*/
- dcb.StopBits = TWOSTOPBITS;
- //SetCommConfig(m_hDeviceFile, &mConfig, sizeof(COMMCONFIG));
- break;
- default:
- dcb.StopBits = ONE5STOPBITS;
- }
- switch (m_cParityBit) {
- case Parity_NO: /*no parity*/
- dcb.fParity = NOPARITY;
- dcb.Parity = 0;
- break;
- case Parity_ODD: /*odd parity*/
- dcb.fParity = TRUE;
- dcb.Parity = 1; //None,Odd,Even,Mark,Space
- break;
- case Parity_EVEN: /*even parity*/
- dcb.fParity = TRUE;
- dcb.Parity = 2; //None,Odd,Even,Mark,Space
- break;
- default:
- dcb.fParity = NOPARITY;
- dcb.Parity = 0;
- }
- dcb.fRtsControl = RTS_CONTROL_ENABLE;
- dcb.fDtrControl = DTR_CONTROL_ENABLE;
- //硬件,流控参数
- dcb.fOutxCtsFlow = FALSE;
- dcb.fOutxDsrFlow = FALSE;
- dcb.fOutX = FALSE;
- dcb.fInX = FALSE;
- switch(m_cFlow) { //流控
- case Flow_NO: /*no flow control*/
- break;
- case Flow_XONOFF: /*software (XON/XOFF) flow control*/
- dcb.fOutxCtsFlow = FALSE;
- dcb.fOutxDsrFlow = FALSE;
- dcb.fOutX = TRUE;
- dcb.fInX = TRUE;
- break;
- case Flow_CTS: //CtsRtsFlowControl CtsDtrFlowControl:
- dcb.fOutxCtsFlow = TRUE;
- dcb.fOutxDsrFlow = FALSE;
- dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
- break;
- case Flow_DSR: // DsrRtsFlowControl DsrDtrFlowControl:
- dcb.fOutxCtsFlow = FALSE;
- dcb.fOutxDsrFlow = TRUE;
- dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
- break;
- default:
- break;
- }
- SetCommState(m_hCom, &dcb);
- PurgeComm(m_hCom, PURGE_TXABORT | PURGE_TXCLEAR);
- PurgeComm(m_hCom, PURGE_RXABORT | PURGE_RXCLEAR);
- return true;
- }
- bool SSerial::IsOpen()
- {
- return m_hCom!=NULL;
- }
- void SSerial::Close ()
- {
- if ( m_hCom )
- {
- CloseHandle(m_hCom);
- m_hCom = 0;
- }
- }
- //清除缓存
- void SSerial::Flush()
- {
- FlushFileBuffers(m_hCom);
- }
- //设置超时,单位毫秒
- void SSerial::SetTimeout(unsigned int msec)
- {
- if (msec<0) msec=100;
- if (msec>120000) msec=120000;
- int Timeout_Sec = msec/1000;
- int msec = (msec%1000);
- COMMTIMEOUTS mTimeouts;
- //ReadIntervalTimeout:指定通信线路上两个字符到达之间的最大时间
- //ReadTotalTimeoutMultiplier:用于设定读总超时时间的系数.
- //ReadTotalTimeoutConstant:设定读总超时时间的常量值.读总超时时间
- //WriteTotalTimeoutMultiplier:用于设定写总超时时间的系数.写总超时时间
- //WriteTotalTimeoutConstant:用于设定写总超时时间的常量值.写总超时时间
- mTimeouts.ReadIntervalTimeout = 0;
- mTimeouts.ReadTotalTimeoutMultiplier = 0;
- mTimeouts.ReadTotalTimeoutConstant = Timeout_Sec*1000+Timeout_Millisec;
- mTimeouts.WriteTotalTimeoutMultiplier = 0;
- mTimeouts.WriteTotalTimeoutConstant = Timeout_Sec*1000+Timeout_Millisec;
- SetCommTimeouts(m_hCom, &mTimeouts);
- }
- // 通过串口向外发N个字节
- // data: 发送字节首地址
- // datalen: 发送字节长度
- // Return: -1: 发送失败 >0:已经发送的字节
- int SSerial::SendOnce(const char *sData, int iLen, int timeout )
- {
- SetTimeout(timeout);
- unsigned long iWrite = 0;
- WriteFile(m_hCom, sData, iLen, &iWrite, NULL);
- return iWrite;
- }
- // 从串口读入N个字节
- // Input: data: 读入字节首地址
- // datalen: 发送字节长度
- // timeout: 超时时间,单位秒 <0 时代表无限期等待
- // Return: -1: 读入失败 >0:已经读入的字节
- int SSerial::ReceiveOnce ( char *sData, int iLen, int iTimeout )
- {
- COMSTAT stat;
- DWORD errmask=0;
- ClearCommError(m_hCom, &errmask, &stat);
- if (iTimeout < 0) iTimeout = 100;
- if (iTimeout > 120000) iTimeout = 120000;
- SetTimeout(iTimeout);
- unsigned long lRead = 0;
- ReadFile(m_hCom, (void*)(sData), (DWORD)iLen, &lRead, NULL);
- return lRead;
- }
- #else
- //串口操作类,初始化
- 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] = { 0 };
- 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);
- }
- #endif
- // 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;
- sData += nBytesThisTime;
- Sleep(10);
- iNow = GetSystemTime();
- }while(nBytesSent < iLen && 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;
- sData += nBytesThisTime;
- Sleep(10);
- iNow = GetSystemTime();
- }while(nBytesRead < iLen && iNow < iEnd);
- if (nBytesRead)
- return nBytesRead;
- else
- return 0;
- }
|