⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serial.cpp

📁 comtest 测试串口通信
💻 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 + -