📄 serial.cpp
字号:
#include "Serial.h"#include <iostream>#ifdef WIN32#include <windows.h>#else#include <fcntl.h>#endifusing namespace std;namespace rtd{#ifdef LINUXint baud_attr[]={B115200, B38400, B19200, B9600, B4800, B2400, B1200, B300};int name_attr[]={115200, 38400, 19200, 9600, 4800, 2400, 1200, 300};#endifSerial::Serial(int nPort, int nBaudRate):m_nPort(nPort),m_nBaudRate(nBaudRate),m_hComm(INVALID_HANDLE_VALUE){}Serial::~Serial(void){ this->Close();}void Serial::ClearError(){#ifdef WIN32 DWORD dwError; COMSTAT comStat; if(ClearCommError(this->m_hComm, &dwError,&comStat) && dwError >0){ PurgeComm(this->m_hComm,PURGE_TXABORT |PURGE_RXABORT |PURGE_TXCLEAR |PURGE_RXCLEAR); }#else tcflush(m_hComm,TCIFLUSH);#endif}void Serial::ClearBuf(){#ifdef WIN32 DWORD dwError; COMSTAT comStat; ClearCommError(this->m_hComm, &dwError,&comStat); PurgeComm(this->m_hComm,PURGE_TXABORT |PURGE_RXABORT |PURGE_TXCLEAR |PURGE_RXCLEAR);#else tcflush(m_hComm,TCIFLUSH);#endif}bool Serial::Resume(){#ifdef LINUX char szPort[15]; sprintf(szPort, "/dev/ttyS%d", this->m_nPort); if (fork() == 0) { cout << ">>>>>>>>>>>>>>>>> open as O_RDONLY <<<<<<<<<<<<<<<<<<" << endl; int fd1 = open(szPort, O_RDONLY | O_NOCTTY); //|O_NDELAY); close(fd1); cout << ">>>>>>>>>>>>>>>>> open as O_RDONLY end<<<<<<<<<<<<<<<<<<" << endl; exit(0); } cout << ">>>>>>>>>>>>>>>>> open as O_RDWR <<<<<<<<<<<<<<<<<<" << endl; int fd1 = open(szPort, O_RDWR | O_NOCTTY); //|O_NDELAY); cout << ">>>>>>>>>>>>>>>>> open as O_RDWR end<<<<<<<<<<<<<<<<<<" << endl; close(fd1);#endif return true;}void ErrorExit(LPTSTR lpszFunction)
{
TCHAR szBuf[80];
LPVOID lpMsgBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf,
0, NULL );
wsprintf(szBuf,
"%s failed with error %d: %s",
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, szBuf, "Error", MB_OK);
LocalFree(lpMsgBuf);
//ExitProcess(dw);
}bool Serial::Open(){ if(this->IsOpen()) { return true; } char szPort[15];#ifdef WIN32 sprintf( szPort, "\\\\.\\COM%d", this->m_nPort); printf("%s\n",szPort); this->m_hComm = CreateFile(szPort, // 串口名称或设备路径 GENERIC_READ | GENERIC_WRITE, // 读写方式 0, // 共享方式:独占 NULL, // 默认的安全描述符 OPEN_EXISTING, // 创建方式 0, // 不需设置文件属性 NULL); // 不需参照模板文件 if(this->m_hComm == INVALID_HANDLE_VALUE){ ErrorExit("CreateFile"); printf("CreateFile fail.\n"); return false; // 打开串口失败 } COMMTIMEOUTS timeouts = { // 串口超时控制参数 100, // 读字符间隔超时时间: 100 ms 1, // 读操作时每字符的时间: 1 ms (n个字符总共为n ms) 500, // 基本的(额外的)读超时时间: 500 ms 1, // 写操作时每字符的时间: 1 ms (n个字符总共为n ms) 100}; // 基本的(额外的)写超时时间: 100 ms DCB dcb; // 串口控制块 if (!GetCommState(this->m_hComm, &dcb)) // 取DCB { ErrorExit("SetCommState"); CloseHandle(this->m_hComm); this->m_hComm = INVALID_HANDLE_VALUE; return false; } dcb.BaudRate = this->m_nBaudRate; dcb.ByteSize = 8; // Number of bits/byte, 4-8 dcb.Parity = 0; // 0-4=no,odd,even,mark,space dcb.StopBits = ONESTOPBIT; // 0,1,2 = 1, 1.5, 2 dcb.fDtrControl = 0; dcb.fRtsControl = 0; if(!SetCommState(this->m_hComm, &dcb)){ // 设置DCB ErrorExit("SetCommState"); printf("SetCommState fail.\n"); CloseHandle(this->m_hComm); this->m_hComm = INVALID_HANDLE_VALUE; return false; } if(!SetupComm(this->m_hComm, 4096, 1024)){ // 设置输入输出缓冲区大小 ErrorExit("SetupComm"); printf("SetupComm fail.\n"); CloseHandle(this->m_hComm); this->m_hComm = INVALID_HANDLE_VALUE; return false; } if(!SetCommTimeouts(this->m_hComm, &timeouts)){ // 设置超时 ErrorExit("SetCommTimeouts"); printf("SetCommTimeouts fail.\n"); CloseHandle(this->m_hComm); this->m_hComm = INVALID_HANDLE_VALUE; return false; } return true;#else //cout << "???????????????? " << this->m_nPort << endl; sprintf(szPort, "/dev/ttyS%d", this->m_nPort); //cout << ">>>>>>>>>>>>>>>> open " << szPort << endl; //open //m_hComm = open(szPort, O_RDWR | O_NOCTTY); //|O_NDELAY); m_hComm = open(szPort, O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY); if(m_hComm == INVALID_HANDLE_VALUE) { printf("Can't Open the Port %s\n",szPort); return false; } int fdflag; if((fdflag=fcntl(m_hComm,F_GETFL))==-1 || fcntl(m_hComm,F_SETFL,fdflag & ~O_NONBLOCK) < 0) { perror("fcntl"); return false; } //Set Baud struct termios Opt; tcgetattr(m_hComm, &Opt); memset(&initOptions,0,sizeof(termios)); memcpy(&initOptions,&Opt,sizeof(struct termios)); for(int j = 0; j < 2; j++) { for(size_t i = 0; i < sizeof(baud_attr)/sizeof(int); i++) { if(m_nBaudRate == name_attr[i]) { tcflush(m_hComm, TCIOFLUSH); cfsetispeed(&Opt, baud_attr[i]); cfsetospeed(&Opt, baud_attr[i]); int status = tcsetattr(m_hComm, TCSANOW, &Opt); //激活配置 if(status != 0) { perror("tcsetattr fail\n"); Close(); system("reboot"); return false; } tcflush(m_hComm, TCIOFLUSH); } } } //Set Parity int timeup = 1; struct termios options; if(tcgetattr(m_hComm, &options) != 0) { perror("tcgetattr fail\n"); return false; } options.c_cflag &=~CRTSCTS; options.c_cflag &= ~CSIZE; options.c_cflag |= CS8; options.c_cflag &= ~PARENB; /*Clear Parity enable*/ options.c_iflag &= ~INPCK; /*Clear parity checking*/ options.c_cflag &= ~CSTOPB; options.c_iflag =0; /*if tht port is not for moden, then set it as raw model*/ options.c_lflag &= ~(ICANON | ECHO | ECHOE |ISIG); /*Input*/ options.c_oflag = 0; //Clear All (Expecial: XOFF/XON) options.c_cflag ^= (CLOCAL | HUPCL);//for modem 20080403 tcflush(m_hComm, TCIOFLUSH); options.c_cc[VTIME] = timeup*10; /*set timeout of 15 seconds*/ options.c_cc[VMIN] = 0; /*Update the option and do it NOW*/ if(tcsetattr(m_hComm, TCSANOW, &options) != 0) { perror("Setup Serial Port\n"); Close(); return false; } return true;#endif}// 关闭串口void Serial::Close(){#ifdef WIN32 CloseHandle(this->m_hComm);#else tcsetattr(m_hComm,TCSANOW,&initOptions); close(m_hComm);#endif this->m_hComm = INVALID_HANDLE_VALUE;}bool Serial::Send(const char *buff,size_t len){ if(this->IsOpen()) {#ifdef WIN32 DWORD wd = 0; this->ClearError(); // printf("%d [",buff); //for (int cnt = 0 ; cnt < len; ++cnt) //{ // printf("%02x ",*(buff + cnt)); //} //printf("]\n"); if(WriteFile(this->m_hComm,buff,(DWORD)len,&wd,NULL)) { if(wd == 0) { printf("WriteFile..wd == 0 ERROE::%d\n", GetLastError()); return false; }else if(wd < len) { return Send(buff+wd,len-wd); }else { if(FlushFileBuffers(this->m_hComm)) { return true; }else{ printf("FlushFileBuffers fail\n"); return false; } } }else { printf("WriteFile..fail\n"); return false; }#else size_t nret; //cout << "!!!!!!!!!!!!!!!!!!!!!!before lock!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl; //m_mutex.Lock(); //cout << "!!!!!!!!!!!!!!!!!!!!!!after lock!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl; tcflush(m_hComm, TCOFLUSH); nret = write(m_hComm, buff, len); tcdrain(m_hComm); //cout << "!!!!!!!!!!!!!!!!!!!!!!before Unlock!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl; //m_mutex.Unlock(); //cout << "!!!!!!!!!!!!!!!!!!!!!!after Unlock!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl; if (nret == 0) return false; else if (nret == len) return true; else if (nret < len) return Send(buff + nret, len - nret); else return false;#endif } else { printf("IsOpen false\n"); return false; }}// 读串口// 输入: pData - 待读的数据缓冲区指针// nLength - 待读的最大数据长度// 返回: 实际读出的数据长度int Serial::Revice(void* pData, int nLength){ #ifdef WIN32 this->ClearError(); DWORD dwNumRead; // 串口收到的数据长度 ReadFile(this->m_hComm, pData, (DWORD)nLength, &dwNumRead, NULL); return (int)dwNumRead;#else int ret, bytes; ret = 0; bytes = 0; //m_mutex.Lock(); if(ioctl(m_hComm, FIONREAD, &bytes) == 0) { ret = read(m_hComm, pData, nLength); } //m_mutex.Unlock(); return ret;#endif}int Serial::ReceiveLine(char* buf, size_t size){ unsigned int nLen=0,nTotalLen=0; char nowChar; while(true) { //cout << "Before Revice >>>>>>>>>>>>" << nLen << endl; nLen = Revice(&nowChar,1); if(nLen > 0) { if(nowChar == 0x0A) { //cout << "nnowChar == 0x0A" << endl; buf[nTotalLen] = '\0'; break; }else if(nowChar!=0x00 && nowChar!=0x0D) { buf[nTotalLen++] = nowChar; //cout << "nowChar>>>>>" << nowChar << endl; if(nTotalLen >= size) { //cout << "nTotalLen >= size" << endl; break; } } } else { break; } } return nTotalLen;}bool Serial::IsOpen(){ return (this->m_hComm!=INVALID_HANDLE_VALUE);}int Serial::GetPort(){ return this->m_nPort;}int Serial::GetBaudRate(){ return this->m_nBaudRate;}}//~namespace
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -