串口通信跨平台

来源:互联网 发布:如何在java中实现线程 编辑:程序博客网 时间:2024/05/16 11:23

mac 下用python模拟串口

#! /usr/bin/env python


#coding=utf-8


import pty
import os 
import select
import time


def mkpty():
    #
    master1, slave = pty.openpty()
    slaveName1 = os.ttyname(slave)
    master2, slave = pty.openpty()
    slaveName2 = os.ttyname(slave)
    print '\nslave device names: ', slaveName1, slaveName2
    return master1, master2




if __name__ == "__main__":
    datasend = "jack.hong" 
    global data
    master1, master2 = mkpty()
    bl = True
    while True: 
    
        rl, wl, el = select.select([master1, master2], [], [], 60)
        for master in rl:  
            data = ""                    
            if master==master1:
                data = os.read(master, 2048)                
                print "read from master1 %d len data." % len(data), data                                                            
                os.write(master2, datasend) 
            else:
                #if bl == True:
                data = os.read(master, 2048) 
                print "read from master2 %d len data." % len(data), data                                     
                os.write(master1, datasend)
                bl = False        
        #time.sleep(3)


串口通信代码头文件

#pragma once

#include <thread>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#else
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#endif




/* #include <winbase.h>
#define NOPARITY            0
#define ODDPARITY           1
#define EVENPARITY          2
#define MARKPARITY          3
#define SPACEPARITY         4


#define ONESTOPBIT          0
#define ONE5STOPBITS        1
#define TWOSTOPBITS         2
*/


struct SerialPortInfo{
    std::string name;
    unsigned int baudRate{9600};
    unsigned int parity{'e'};
    unsigned int dataBits{7};
    unsigned int stopBits{1};
};


class BaseCom 
{
public:
BaseCom();
virtual ~BaseCom();
public:
    bool Connect(const SerialPortInfo& portinfo);
    void Close();
    bool IsOpen();
#ifdef WIN32
public:
bool Connect(const std::string& portName, unsigned int baudRate = CBR_9600, unsigned int parity = NOPARITY,
unsigned int dataBits = 8, unsigned int stopBits = ONESTOPBIT);
bool Connect(int port, unsigned int baudRate = CBR_9600, unsigned int parity = NOPARITY, unsigned int dataBits = 8, unsigned int stopBits = ONESTOPBIT);
protected:
virtual bool OpenPort() = 0;


void Init();
bool SetupPort();
void SetComPort(int port);


bool SetState(int BaudRate, int ByteSize, int Parity, int StopBits);


protected:


volatile int _port;  
volatile HANDLE _com_handle;
char _com_str[20];
DCB _dcb;     
COMMTIMEOUTS _co; 
#else
public:
bool Connect(const std::string& portName, unsigned int baudRate = 9600, unsigned int parity = 'N',
unsigned int dataBits = 8, unsigned int stopBits = 1);
protected:
    bool openLinuxPort(const SerialPortInfo& portinfo);
    bool setLinuxPortOpt(const SerialPortInfo& portinfo);
protected:
    int _fdSerial{-1};
    bool _isOpen{false};
#endif
protected:
    SerialPortInfo _portinfo;
};


//ͬ������


#ifdef WIN32
class SyncCom : public BaseCom
{
public:
SyncCom();


int Read(char *buf, int buf_len);


int SendData(const char* buf, int buf_len);
int SendData(const char* buf);


protected:
virtual bool OpenPort();
};
#endif


//�첽����
typedef void(*RecvDataCallBack)(const std::string& data, void* context);
class ASynCom : public BaseCom
{
public:
ASynCom();


virtual ~ASynCom();


int Read(char* buf, int buf_len);


bool SendData(const char* buf, int buf_len);
bool SendData(const std::string& buf);


void Start();
void Stop();    
void SetRecvDataCallBack(RecvDataCallBack callback, void* context);


protected:
static void OnProcRecvData(void* context);
#ifdef WIN32
protected:
    virtual bool OpenPort();
protected:
OVERLAPPED _ro, _wo; // �ص�I/O
    OVERLAPPED _wait_o; //WaitCommEvent use
#else
    ssize_t readDataTty(int fd, char *rcv_buf, int TimeOut, int Len);
    ssize_t sendDataTty(int fd, const char *send_buf, int Len);
    void reInit();
#endif
    bool _isExit = false;
std::thread* _workThread = NULL;
RecvDataCallBack _recvDataCallback = NULL;
void* _recvDataContext = NULL;


};



串口通信代码CPP文件

#include "SerialPort.h"


#include <cassert>


BaseCom::BaseCom()
{
#ifdef WIN32
    Init();
#endif
}


BaseCom::~BaseCom()
{
Close();
}


bool BaseCom::Connect(const SerialPortInfo& portinfo)
{
_portinfo = portinfo;
#ifdef WIN32
return Connect(portinfo.name, portinfo.baudRate, portinfo.parity, portinfo.dataBits, portinfo.stopBits);
#else
   
   bool result{false};
   result = openLinuxPort(_portinfo);
   if(result)
       result = setLinuxPortOpt(_portinfo);
   return result;
#endif
}


bool BaseCom::Connect(const std::string& portName, unsigned int baudRate, unsigned int parity,
unsigned int dataBits, unsigned int stopBits)
{
#ifdef WIN32
int pos = portName.find("COM");
if (pos == std::string::npos){
printf("COM name is error. %s\n", portName.c_str());
return false;
}
std::string sport = portName.substr(pos + 3, portName.size());
int port = atoi(sport.c_str());
return Connect(port, baudRate, parity, dataBits, stopBits);
#else    
    _portinfo.name = portName;
    _portinfo.baudRate = baudRate;
    _portinfo.parity = parity;
    _portinfo.dataBits = dataBits;
    _portinfo.stopBits = stopBits;
    return Connect(_portinfo);
#endif
}


#ifdef WIN32
bool BaseCom::Connect(int port, unsigned int baudRate, unsigned int parity, unsigned int dataBits, unsigned int stopBits)
{
if (port < 1 || port > 1024)
return false;


SetComPort(port);


if (!OpenPort())
return false;


if (!SetupPort())
return false;


return SetState(baudRate, dataBits, parity, stopBits);
}


bool BaseCom::SetState(int BaudRate, int ByteSize, int Parity, int StopBits)
{
    if (IsOpen())
    {
        if (!GetCommState(_com_handle, &_dcb))
            return false;
        _dcb.BaudRate = BaudRate;
        _dcb.ByteSize = ByteSize;
        _dcb.Parity = Parity;
        _dcb.StopBits = StopBits;
        return SetCommState(_com_handle, &_dcb) == TRUE;
    }
    return false;
}


void BaseCom::Init()
{
    memset(_com_str, 0, 20);
    memset(&_co, 0, sizeof(_co));
    memset(&_dcb, 0, sizeof(_dcb));
    _dcb.DCBlength = sizeof(_dcb);
    _com_handle = INVALID_HANDLE_VALUE;
}


bool BaseCom::SetupPort()
{
    if (!IsOpen())
        return false;


    if (!SetupComm(_com_handle, 8192, 8192))
        return false;


    if (!GetCommTimeouts(_com_handle, &_co))
        return false;
    _co.ReadIntervalTimeout = 0xFFFFFFFF;
    _co.ReadTotalTimeoutMultiplier = 0;
    _co.ReadTotalTimeoutConstant = 0;
    _co.WriteTotalTimeoutMultiplier = 0;
    _co.WriteTotalTimeoutConstant = 2000;
    if (!SetCommTimeouts(_com_handle, &_co))
        return false;


    if (!PurgeComm(_com_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))
        return false;


    return true;
}


void BaseCom::SetComPort(int port)
{
    char p[12];
    _port = port;
    strcpy_s(_com_str, "\\\\.\\COM");
    _ltoa_s(_port, p, 10);
    strcat_s(_com_str, p);
}


#else
bool BaseCom::openLinuxPort(const SerialPortInfo& portinfo)
{
    _fdSerial = open(portinfo.name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
    if (-1 == _fdSerial)
    {
        printf("Can't Open %s Serial Port \n", portinfo.name.c_str());
        return(false);
    }
    else
    {
        printf("open %s .....\n", portinfo.name.c_str());
    }


    if(fcntl(_fdSerial, F_SETFL, FNDELAY) < 0)//非阻塞,覆盖前面open的属性
    {
        printf("set %s noblock failed\n", _portinfo.name.c_str());
    }
    else{
        printf("set %s noblock succ\n", _portinfo.name.c_str());
    }
    
/*
    int ifcntl = fcntl(_fdSerial, F_SETFL, 0); //阻塞
    if (ifcntl < 0)
    {
        printf("fcntl %s  failed, result is %d!\n", portinfo.name.c_str(), ifcntl);
    }
    else
    {
        printf("fcntl %s succ, result is %d!\n", portinfo.name.c_str(), ifcntl);
    }
 */


    if (isatty(STDIN_FILENO) == 0)
    {
        printf("%s is not a terminal device\n", portinfo.name.c_str());
    }
    else
    {
        printf("%s is a tty success!\n", portinfo.name.c_str());
    }
    printf("%s is open fdSerial = %d\n", portinfo.name.c_str(), _fdSerial);
    return true;
}


bool BaseCom::setLinuxPortOpt(const SerialPortInfo& portinfo)
{
    int speed_arr[] = { B38400, B19200, B9600, B4800, B2400, B1200, B300, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
    int name_arr[] = {38400, 19200, 9600, 4800, 2400, 1200, 300, 38400, 19200, 9600, 4800, 2400, 1200, 300, };
    struct termios newtio, oldtio;
    if (tcgetattr(_fdSerial, &oldtio) != 0)
    {
        printf("getSerial %s attr fail", portinfo.name.c_str());
        return false;
    }
    bzero(&newtio, sizeof(newtio));
    newtio.c_cflag |= CLOCAL | CREAD;
    newtio.c_cflag &= ~CSIZE;
        
    switch (portinfo.dataBits)
    {
        case 5:
            newtio.c_cflag |= CS5;
            break;
        case 6:
            newtio.c_cflag |= CS6;
            break;
        case 7:
            newtio.c_cflag |= CS7;
            break;
        case 8:
            newtio.c_cflag |= CS8;
            break;
        default:
            printf("%s bits is not 7 or 8, please check", portinfo.name.c_str());
            newtio.c_cflag |= CS8;
            break;  
    }
        
    switch (portinfo.parity)
    {
        case 'o':
        case 'O':                     //奇校验
            newtio.c_cflag |= PARENB;
            newtio.c_cflag |= PARODD;
            newtio.c_iflag |= (INPCK);
            break;
        case 'e':
        case 'E':                     //偶校验
            newtio.c_iflag |= (INPCK | ISTRIP);
            newtio.c_cflag |= PARENB;
            newtio.c_cflag &= ~PARODD;
            break;
        case 'n':
        case 'N':                    //无校验
            newtio.c_cflag &= ~PARENB;
            newtio.c_iflag &= ~INPCK;
            break;
        case 's':
        case 'S':
            newtio.c_cflag &= ~PARENB; //清除校验位
            newtio.c_cflag &= ~CSTOPB; //??????????????
            newtio.c_iflag |= INPCK; //disable pairty checking
            break;
        default:
            printf("%s Unsupported parity.\n", _portinfo.name.c_str());
            return false;
    }
    
    for(auto i = 0; i < sizeof(speed_arr) / sizeof(int); i++)
    {
        if(portinfo.baudRate == name_arr[i])
        {
            tcflush(_fdSerial, TCIOFLUSH);
            cfsetispeed(&newtio, speed_arr[i]);
            cfsetospeed(&newtio, speed_arr[i]);
            /*
             TCSANOW:立即执行而不等待数据发送或者接受完成。
             TCSADRAIN:等待所有数据传递完成后执行。
             TCSAFLUSH:Flush input and output buffers and make the change
             */
            if ((tcsetattr(_fdSerial, TCSANOW, &newtio)) != 0)
            {
                printf("%s set error", portinfo.name.c_str());
                return false;
            }
            tcflush(_fdSerial, TCIOFLUSH);
            break;
        }
    }
        
    if (portinfo.stopBits == 1)
    {
        newtio.c_cflag &= ~CSTOPB;
    }
    else if(portinfo.stopBits == 2)
    {
        newtio.c_cflag |= CSTOPB;
    }
    else
    {
        printf("%s Unsupported stopbits error", portinfo.name.c_str());
        return false;
    }
    
    newtio.c_cflag |= IXON | IXOFF | IXANY;
    
    newtio.c_cflag &= ~CSIZE;
    
    newtio.c_oflag &= ~OPOST;
    
    newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    
    newtio.c_cc[VTIME] = 0;
    newtio.c_cc[VMIN] = 0;
    if( tcflush(_fdSerial, TCIOFLUSH) == -1)
    {
        printf(" %s  tcflush failed\n", portinfo.name.c_str());
    }
    printf("%s set done!\n", portinfo.name.c_str());
    _isOpen = true;
    return true;


}


#endif


void BaseCom::Close()
{
#ifdef WIN32
if (IsOpen())
{
CloseHandle(_com_handle);
_com_handle = INVALID_HANDLE_VALUE;
}
#else
    if (_fdSerial > 0)
        close(_fdSerial);
#endif
}


bool BaseCom::IsOpen()
{
#ifdef WIN32
    return _com_handle != INVALID_HANDLE_VALUE;
#else
    return _isOpen;
#endif
}






#ifdef WIN32
SyncCom::SyncCom()
{
}


bool SyncCom::OpenPort()
{
if (IsOpen())
Close();


_com_handle = CreateFileA(
_com_str,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);


return IsOpen();
}


int SyncCom::Read(char* buf, int buf_len)
{
if (!IsOpen())
return 0;


buf[0] = '\0';


COMSTAT  stat;
DWORD error;


if (ClearCommError(_com_handle, &error, &stat) && error > 0) 
{
PurgeComm(_com_handle, PURGE_RXABORT | PURGE_RXCLEAR);
return 0;
}


unsigned long r_len = 0;


buf_len = min(buf_len - 1, (int)stat.cbInQue);
if (!ReadFile(_com_handle, buf, buf_len, &r_len, NULL))
r_len = 0;
buf[r_len] = '\0';


    return r_len;
}


int SyncCom::SendData(const char* buf, int buf_len)
{
if (!IsOpen() || !buf)
return 0;


DWORD    error;
if (ClearCommError(_com_handle, &error, NULL) && error > 0) 
PurgeComm(_com_handle, PURGE_TXABORT | PURGE_TXCLEAR);


unsigned long w_len = 0;
if (!WriteFile(_com_handle, buf, buf_len, &w_len, NULL))
w_len = 0;


return w_len;
}


int SyncCom::SendData(const char* buf)
{
return SendData(buf, strlen(buf));
}
 #endif


ASynCom::ASynCom()
{
#ifdef WIN32
memset(&_ro, 0, sizeof(_ro));
memset(&_wo, 0, sizeof(_wo));


_ro.hEvent = CreateEvent(NULL, true, false, NULL);
assert(_ro.hEvent != INVALID_HANDLE_VALUE);


_wo.hEvent = CreateEvent(NULL, true, false, NULL);
assert(_wo.hEvent != INVALID_HANDLE_VALUE);




memset(&_wait_o, 0, sizeof(_wait_o));
_wait_o.hEvent = CreateEvent(NULL, true, false, NULL);
assert(_wait_o.hEvent != INVALID_HANDLE_VALUE);
#endif
}




ASynCom::~ASynCom()
{
    Close();
#ifdef WIN32




if (_ro.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(_ro.hEvent);


if (_wo.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(_wo.hEvent);


if (_wait_o.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(_wait_o.hEvent);
#endif
}


#ifdef WIN32
bool ASynCom::OpenPort()
{
#ifdef WIN32
if (IsOpen())
Close();


_com_handle = CreateFileA(
_com_str,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 
NULL
);
return IsOpen();
 #endif
    return false;
}
#endif


int ASynCom::Read(char* buf, int buf_len)
{
#ifdef WIN32
if (!IsOpen())
return 0;


buf[0] = '\0';


COMSTAT  stat;
DWORD error;


if (ClearCommError(_com_handle, &error, &stat) && error > 0) 
{
PurgeComm(_com_handle, PURGE_RXABORT | PURGE_RXCLEAR); 
return 0;
}


if (!stat.cbInQue)
return 0;


unsigned long r_len = 0;


buf_len = min((int)(buf_len - 1), (int)stat.cbInQue);


if (!ReadFile(_com_handle, buf, buf_len, &r_len, &_ro)) 
{
if (GetLastError() == ERROR_IO_PENDING) 
{
if (!GetOverlappedResult(_com_handle, &_ro, &r_len, false))
{
if (GetLastError() != ERROR_IO_INCOMPLETE)
r_len = 0;
}
}
else
r_len = 0;
}


buf[r_len] = '\0';
return r_len;
 #else
    return (int)readDataTty(_fdSerial, buf, 20, buf_len); //100 没有数据就等待100毫秒
 #endif
  
}


bool ASynCom::SendData(const char* buf, int buf_len)
{
#ifdef WIN32
if (!IsOpen())
return false;


DWORD error;
if (ClearCommError(_com_handle, &error, NULL) && error > 0) 
PurgeComm(_com_handle, PURGE_TXABORT | PURGE_TXCLEAR);


unsigned long w_len = 0, o_len = 0;
if (!WriteFile(_com_handle, buf, buf_len, &w_len, &_wo)){
if (GetLastError() != ERROR_IO_PENDING)
return false;
}


return true;
#else
   ssize_t sendlen = sendDataTty(_fdSerial, buf, buf_len);
   return sendlen != -1;
#endif
}


bool ASynCom::SendData(const std::string& buf)
{
#ifdef WIN32
return SendData(buf.c_str(), buf.size());
#else
    ssize_t sendlen = sendDataTty(_fdSerial, buf.c_str(), (int)buf.size());
    return sendlen != -1;
#endif
}


void ASynCom::SetRecvDataCallBack(RecvDataCallBack callback, void* context)
{
_recvDataCallback = callback;
_recvDataContext = context;
}


void ASynCom::Start()
{
_isExit = false;
_workThread = new std::thread(ASynCom::OnProcRecvData, this);
}


void ASynCom::Stop()
{
if (!_isExit && _workThread != NULL && _workThread->joinable()){
_isExit = true;
#ifdef WIN32
TerminateThread(_workThread->native_handle(), 1);
#endif
if (_workThread->joinable()){
_workThread->join();
}
delete _workThread;
_workThread = NULL;
}
}


void ASynCom::OnProcRecvData(void* context)
{
ASynCom *pcom = (ASynCom *)context;
#ifdef WIN32
if (!SetCommMask(pcom->_com_handle, EV_RXCHAR | EV_ERR))
return;


COMSTAT  stat;
DWORD error;
DWORD mask;
DWORD length;
while (!pcom->_isExit){
if (!WaitCommEvent(pcom->_com_handle, &mask, &pcom->_wait_o))
{
if (GetLastError() == ERROR_IO_PENDING)
{
GetOverlappedResult(pcom->_com_handle, &pcom->_wait_o, &length, true);
}
}


if (mask & EV_ERR) 
ClearCommError(pcom->_com_handle, &error, &stat);


if (mask & EV_RXCHAR) 
{
ClearCommError(pcom->_com_handle, &error, &stat);
if (stat.cbInQue > 0){
char buf[1024] = { 0 };
int buflen = sizeof(buf);
int r = pcom->Read(buf, buflen);
if (r > 0){
std::string msg;
msg.assign(buf, r);
if (pcom->_recvDataCallback != NULL && !msg.empty()){
pcom->_recvDataCallback(msg, pcom->_recvDataContext);
}
else{
printf("SerialPort recv data:%s\n", msg.c_str());
}
}
}
}
}
#else
    char buf[1024] = { 0 };
    int ibuflen = sizeof(buf)/ sizeof(char);
    while (!pcom->_isExit)
    {
        memset(buf,0,ibuflen);        
        int r = pcom->Read(buf, ibuflen);
        if (r > 0)
        {
            std::string msg;
            msg.assign(buf, r);
            if (pcom->_recvDataCallback != NULL && !msg.empty())
            {
                pcom->_recvDataCallback(msg, pcom->_recvDataContext);
            }
            else{
                if(!msg.empty())
                    printf("%s recv data:%s\n", pcom->_portinfo.name.c_str(), msg.c_str());
            }
         }
        
    }
#endif
}


#ifndef WIN32
ssize_t ASynCom::readDataTty(int fd, char *rcv_buf, int TimeOut, int Len)
{
    if(!_isOpen)
    {
        if(Connect(_portinfo))
        {
            fd = _fdSerial;
        }
        else
        {
            return -1;
        }
    }
    int retval;
    fd_set rfds;
    struct timeval tv;
    ssize_t ret = 0, pos = 0;
    tv.tv_sec = TimeOut / 1000;  //set the rcv wait time
    tv.tv_usec = TimeOut % 1000 * 1000;  //100000us = 0.1s
    FD_ZERO(&rfds);
    FD_SET(fd, &rfds);
    while (FD_ISSET(fd, &rfds))
    {
        FD_ZERO(&rfds);
        FD_SET(fd, &rfds);     
        retval = select(fd + 1, &rfds, NULL, NULL, &tv);
        if (retval == -1)
        {
            break;
        }
        else if (retval)
        {
            ret = read(fd, rcv_buf + pos, Len-pos);
            if (-1 == ret)
            {
                close(_fdSerial);
                _isOpen = false;
                break;
            }


            if (ret == 0) {
                break;
            }
            pos += ret;
            if (Len <= pos)
            {
                break;
            }


            FD_ZERO(&rfds);
            FD_SET(fd,&rfds);
            retval = select(fd+1,&rfds,NULL,NULL,&tv);
            if(retval <= 0)
            {
                break;
            }
        }
        else
        {
            //printf("%s read data time out", _portinfo.name.c_str());
            break;
        }
    }
    return pos;
}


ssize_t ASynCom::sendDataTty(int fd, const char *send_buf, int Len)
{
    ssize_t ret;
    if(!_isOpen)
    {
        if(Connect(_portinfo))
            fd = _fdSerial;
        else
            return -1;
    }
    std::string sbuf;
    sbuf.assign(send_buf, Len);
    int pos = 0, ilen = (int)sbuf.size();
    while(pos != ilen)
    {
        ret = write(fd, sbuf.c_str()+ pos, ilen-pos);
        if (ret == -1)
        {
            //close(_fdSerial);
            //_isOpen = false;
            printf("%s write %s error \n", _portinfo.name.c_str(), sbuf.c_str());
            return -1;
        }
        pos += ret;
    }
    return pos;
}
#endif



测试程序代码

//

//  main.cpp

//  SerialPort

//

//  Created by soft on 6/3/2017.

//  Copyright © 2017 Reginald. All rights reserved.

//


#include <iostream>

#include "SerialPort.h"



static int com1count =0;

static int com2count =0;


static void senddata(ASynCom* com,conststd::string& msg,int* cont)

{

    std::string temp;

    while (true) {

        (*cont)++;

        temp = msg + " times is " +std::to_string(*cont);

        com->SendData(temp);

        temp = "";

        usleep(800);


    }

}


void dohandleReadData(conststd::string& data,void* context)

{

    SerialPortInfo* own =static_cast<SerialPortInfo*>(context);

    printf("[%s] %s", own->name.c_str(), data.c_str());

    

}


int main(int argc,constchar * argv[]) {

    SerialPortInfo Com1info;

    SerialPortInfo Com2info;

    Com1info.name ="/dev/ttys029";

    Com2info.name ="/dev/ttys030";

    ASynCom Com1;

    ASynCom Com2;

    Com1.SetRecvDataCallBack(dohandleReadData, &Com1info);

    Com2.SetRecvDataCallBack(dohandleReadData, &Com2info);

    if (Com1.Connect(Com1info) &&  Com2.Connect(Com2info))

    {

        Com1.Start();

        Com2.Start();

        std::thread tcom1(senddata, &Com1,"com1_AAAAA", &com1count);

        std::thread tcom2(senddata, &Com2,"com2_BBBBB", &com2count);

        if(tcom1.joinable())

            tcom1.join();

        if(tcom2.joinable())

            tcom2.join();

    }

    

    return0;

}








0 0