linux串口收发

#ifndef CSERIAL_H_
#define CSERIAL_H_

#include 	 <time.h>
#include 	 <stdio.h>
#include     <sys/types.h>
#include     <sys/stat.h>
#include     <fcntl.h>      /*文件控制定义*/
#include     <termios.h>    /*PPSIX 终端控制定义*/
#include     <errno.h>      /*错误号定义*/
#include <sys/select.h>
#include <sys/time.h>
#include <stdlib.h>
#include <unistd.h>

#include <string.h>
#include <pthread.h>
#include"ParseConfig.h"

#define      BUFFER_LENGTH 512

void  *ComThreadR(void *pPM);
void  *ComThreadW(void *pPM);
class CSerial
{	
public:
     CSerial();
     virtual ~CSerial();
     int        		m_fd;
     char        *m_ReadBuffer;
	 int         m_ReadSize;
	 int OnLine;
	void		StartMonitoring();
	void  		ReceiveChar();
	void 		WriteChar();
	pthread_t m_Thread[2];
     int InitPort(char* PortName = "3",int baudrate = 38400,int databits = 8,int stopbits = 1,char parity = 'E');

private:
	void set_speed(int fd, int speed);
	int  set_Parity(int fd,int databits,int stopbits,char parity);
};



#endif /* CSERIAL_H_ */
#include "CSerial.h"
extern int g_event[2];
extern char TcpRecv[512];
extern char ComRecv[512];
extern int  TcpRecvNum;
extern int  ComRecvNum;
int speed_arr[] = {B115200,B57600,B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400,
		B19200, B9600, B4800, B2400, B1200, B300, };
int name_arr[] = {115200,57600,38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200,
		9600, 4800, 2400, 1200, 300, };

CSerial::CSerial()
{
	OnLine = 0;
	m_ReadSize = 0;
	
	m_ReadBuffer = new char[BUFFER_LENGTH];
}
CSerial::~CSerial()
{
	if (m_ReadBuffer != NULL)
		delete [] m_ReadBuffer;
	close(m_fd);
}

int CSerial::InitPort(char* PortName, int baudrate, int databits,int stopbits, char parity)
{
	char ComName[100]= {0};
	char ComBaud[100] = {0};
	    
	ParseConfig("/root/Desktop/TCP/configure.txt","ComName",ComName);
	ParseConfig("/root/Desktop/TCP/configure.txt","ComBaud",ComBaud);
	printf("ComName = %s,ComBaud = %s\n",ComName,ComBaud);
    while(1)
    {
        m_fd = open(ComName, O_RDWR|O_NDELAY|O_NOCTTY);
        if (-1 == m_fd)
        {
            perror(" com open ..");
			OnLine = 0;
            sleep(2);
            continue;
        } else
        {
            set_speed(m_fd, atoi(ComBaud));
            set_Parity(m_fd, databits, stopbits, parity);
			OnLine = 1;
            printf("com open  ok m_fd = %d, ComName = %s,baud = %d\n",m_fd,ComName,atoi(ComBaud));
            break;
        }
    }
	return 0;
}
void CSerial::StartMonitoring()
{
	int ret = pthread_create (&m_Thread[0], NULL, ComThreadR, this);    
	if (ret != 0)    
	{    
		perror ("com pthread_1_create");    
	}    
	ret = pthread_create (&m_Thread[1], NULL, ComThreadW, this);    
	if (ret != 0)    
	{    
		perror ("com pthread_2_create");    
	}  
	return;	
}
void  *ComThreadR(void *pPM)
{	
//读线程
	CSerial *p_Com = (CSerial*)pPM;
	p_Com->InitPort();
	p_Com->ReceiveChar();
	
	return (void *) 0;
}
void  *ComThreadW(void *pPM)
{	
	//写线程
	CSerial *p_Com = (CSerial*)pPM;
	p_Com->WriteChar();
	return (void *) 0;
}
void CSerial::WriteChar()
{
	int nRet = 0;
	char SendStr[] = {0x01,0x05,0x08,0x03,0xff,0x00,0x7e,0x5a};		
	while(1)
	{								
		if(OnLine == 0)
		{
			//the com off line
			usleep(10000);
			continue;
		}
		else
		{
			if(g_event[0] == 0)
			{
			//have nothing to send
				usleep(10000);
				continue;
			}
			else
			{
				nRet = write(m_fd, TcpRecv, TcpRecvNum);
				if(nRet == -1)
				{
					printf("com off line now:WriteChar()\n");
					continue;
				}
				else if(nRet != TcpRecvNum)
				{
					printf("com send less than nRet != TcpRecvNum\n");
					nRet = write(m_fd, TcpRecv, TcpRecvNum);
					if(nRet == TcpRecvNum)
					{
						printf("com send ok\n");
						TcpRecvNum = 0;
						g_event[0] = 0;
						memset(ComRecv,0,sizeof(ComRecv));
					}
					continue;
				}
				else if(nRet == TcpRecvNum)
				{
					printf("com send ok\n");
					TcpRecvNum = 0;
					g_event[0] = 0;
					
					#if 0
					ComRecvNum = nRet;
					for(int i = 0;i < nRet;i++)
						ComRecv[i] = TcpRecv[i];
					g_event[1] = 1;
					#endif
					memset(TcpRecv,0,sizeof(TcpRecv));
				}
				else if(nRet == 0)
				{
					printf("com 1 off line now:WriteChar()\n");
					continue;
				}
			}
		}
	
	}
}

void CSerial::ReceiveChar()
{
	printf("ReceiveChar,m_fd = %d\n",m_fd);
	int nRet = 0;
	fd_set set;
	FD_ZERO(&set);
    FD_SET(m_fd,&set);
    int flag = 0;
	while(1)
	{
		if(select(m_fd+1,&set,NULL,NULL,NULL)>0)
		{
			
			while(1)
			{
				memset(m_ReadBuffer,0,sizeof(m_ReadBuffer));
				nRet=read(m_fd, m_ReadBuffer, 499);
				if(nRet==-1)
				{
					//出错断开(例如客户端执行了超时操作导致自己断开)	
					printf("com nRet==-1\n");				
					OnLine = 0;
		            FD_CLR(m_fd,&set);  
					close(m_fd);				
					InitPort();
					FD_SET(m_fd,&set);
					break;
				}			
				if(nRet>0)
				{
					flag++;
					//收到新的数据
					printf("nRet = %d,m_fd = %d,com recv is ",nRet,m_fd);
					for(int i = 0;i<nRet;i++)
					{
					printf("%x ",m_ReadBuffer[i]&0xff);
					}
					printf("\n");
				//	ComRecvNum = nRet;
					//strcpy(ComRecv,m_ReadBuffer);
					for(int i = 0;i < nRet;i++)
							ComRecv[ComRecvNum++] = m_ReadBuffer[i];
					usleep(10000);
					continue;
					
				}
				if(nRet == 0 && flag != 0)
				{
					
					g_event[1] = 1;
					flag = 0;
					printf("com read nRet == 0 && flag != 0\n");
					break;
				}			
				if(nRet==0 && flag == 0)
				{
					//客户断开				
					printf("TCP nRet==0 && flag == 0\n");	
					OnLine = 0;
					FD_CLR(m_fd,&set);  
					close(m_fd);				
					InitPort();
					FD_SET(m_fd,&set);	
					break;
				}
			}
		}
	}
}

/**
 *@brief  设置串口通信速率
 *@param  fd     类型 int  打开串口的文件句柄
 *@param  speed  类型 int  串口速度
 *@return  void
 */
void CSerial::set_speed(int fd, int speed)
{
	unsigned int i;
	int status;
	struct termios Opt;
	tcgetattr(fd, &Opt);
	for (i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
	{
		if (speed == name_arr[i])
		{
			tcflush(fd, TCIOFLUSH);
			cfsetispeed(&Opt, speed_arr[i]);
			cfsetospeed(&Opt, speed_arr[i]);
			status = tcsetattr(fd, TCSANOW, &Opt);
			if (status != 0)
			{
				perror("tcsetattr fd1");
				return;
			}
			tcflush(fd, TCIOFLUSH);
		}
	}
}
/**
 *@brief   设置串口数据位,停止位和效验位
 *@param  fd     类型  int  打开的串口文件句柄
 *@param  databits 类型  int 数据位   取值 为 7 或者8
 *@param  stopbits 类型  int 停止位   取值为 1 或者2
 *@param  parity  类型  int  效验类型 取值为N,E,O,,S
 */
int CSerial::set_Parity(int fd, int databits, int stopbits, char parity) {
	struct termios options;
	if (tcgetattr(fd, &options) != 0) {
		perror("SetupSerial 1");
		return (false);
	}
	options.c_cflag &= ~CSIZE;
	switch (databits) /*设置数据位数*/
	{
	case 7:
		options.c_cflag |= CS7;
		break;
	case 8:
		options.c_cflag |= CS8;
		break;
	default:
		fprintf(stderr, "Unsupported data size\n");
		return (false);
	}
	switch (parity) {
	case 'n':
	case 'N':
		options.c_cflag &= ~PARENB; /* Clear parity enable */
		options.c_iflag &= ~INPCK; /* Enable parity checking */
		break;
	case 'o':
	case 'O':
		options.c_cflag |= (PARODD | PARENB); /* 设置为奇效验*/
		options.c_iflag |= INPCK; /* Disnable parity checking */
		break;
	case 'e':
	case 'E':
		options.c_cflag |= PARENB; /* Enable parity */
		options.c_cflag &= ~PARODD; /* 转换为偶效验*/
		options.c_iflag |= INPCK; /* Disnable parity checking */
		break;
	case 'S':
	case 's': /*as no parity*/
		options.c_cflag &= ~PARENB;
		options.c_cflag &= ~CSTOPB;
		break;
	default:
		fprintf(stderr, "Unsupported parity\n");
		return (false);
	}
	/* 设置停止位*/
	switch (stopbits) {
	case 1:
		options.c_cflag &= ~CSTOPB;
		break;
	case 2:
		options.c_cflag |= CSTOPB;
		break;
	default:
		fprintf(stderr, "Unsupported stop bits\n");
		return (false);
	}

	options.c_lflag  &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN);  /*Input*/

	options.c_iflag  &= ~(IXON | IXOFF | IXANY);//关流控
	options.c_iflag  &= ~(INLCR | IGNCR | ICRNL | IUCLC | IGNBRK|BRKINT|PARMRK|ISTRIP);

	options.c_oflag  &= ~(ONLCR | OCRNL | ONLRET | ONOCR | OLCUC | OFILL | CRTSCTS);
	options.c_oflag  &= ~OPOST;   /*Output*/

	/* Set input parity option */
	if (parity != 'n')
		options.c_iflag |= INPCK;
	tcflush(fd, TCIFLUSH);
	options.c_cc[VTIME] = 0; /* 设置超时15 seconds*/
	options.c_cc[VMIN] = 0; /* Update the options and do it NOW */
	if (tcsetattr(fd, TCSANOW, &options) != 0) {
		perror("SetupSerial 3");
		return (false);
	}
	return (true);
}

=================================================================================================================

程序猿和程序媛必备的咖啡-OneDay咖啡生活-https://shop110384469.taobao.com/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值