Пример #1
0
void CSerialPort::SetDefaultConfig(int nPort, COMMCONFIG& config)
{
  //Validate our parameters
  ASSERT(nPort>0 && nPort<=255);

  //Create the device name as a string
  CString sPort;
  sPort.Format(_T("COM%d"), nPort);

  DWORD dwSize = sizeof(COMMCONFIG);
  if (!SetDefaultCommConfig(sPort, &config, dwSize))
  {
    TRACE(_T("Failed in call to GetDefaultCommConfig\n"));
    AfxThrowSerialException();
  }
}
Пример #2
0
// Open a port, by name.  Return 0 on success, non-zero for error
int Serial::Open(const wxString& name)
{
	Close();
#if defined(LINUX)
	struct serial_struct kernel_serial_settings;
	int bits;
	port_fd = open(name.mb_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
	if (port_fd < 0) {
		if (errno == EACCES) {
		  error_msg = _("Unable to access ") + wxString(name,wxConvUTF8) + _(", insufficient permission");
			// TODO: we could look at the permission bits and owner
			// to make a better message here
		} else if (errno == EISDIR) {
		  error_msg = _("Unable to open ") + wxString(name,wxConvUTF8) +
		    _(", Object is a directory, not a serial port");
		} else if (errno == ENODEV || errno == ENXIO) {
		  error_msg = _("Unable to open ") + wxString(name,wxConvUTF8) +
		    _(", Serial port hardware not installed");
		} else if (errno == ENOENT) {
		  error_msg = _("Unable to open ") + wxString(name,wxConvUTF8) +
		    _(", Device name does not exist");
		} else {
		  error_msg = _("Unable to open ") + wxString(name,wxConvUTF8) +
		    _(", ") + wxString(strerror(errno),wxConvUTF8);
		}
		return -1;
	}
	if (ioctl(port_fd, TIOCMGET, &bits) < 0) {
		close(port_fd);
		error_msg = _("Unable to query serial port signals");
		return -1;
	}
	bits &= ~(TIOCM_DTR | TIOCM_RTS);
	if (ioctl(port_fd, TIOCMSET, &bits) < 0) {
		close(port_fd);
		error_msg = _("Unable to control serial port signals");
		return -1;
	}
	if (tcgetattr(port_fd, &settings_orig) != 0) {
		close(port_fd);
		error_msg = _("Unable to query serial port settings (perhaps not a serial port)");
		return -1;
	}
	memset(&settings, 0, sizeof(settings));
	settings.c_iflag = IGNBRK | IGNPAR;
	settings.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
	Set_baud(baud_rate);
	if (ioctl(port_fd, TIOCGSERIAL, &kernel_serial_settings) == 0) {
		kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
		ioctl(port_fd, TIOCSSERIAL, &kernel_serial_settings);
	}
	tcflush(port_fd, TCIFLUSH);
#elif defined(MACOSX)
	int bits;
	port_fd = open(name.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
	if (port_fd < 0) {
	  error_msg = _("Unable to open ") + name + _(", ") + strerror(errno);
		return -1;
	}
	if (ioctl(port_fd, TIOCEXCL) == -1) {
		close(port_fd);
		error_msg = _("Unable to get exclussive access to port ") + name;
		return -1;
	}
	if (ioctl(port_fd, TIOCMGET, &bits) < 0) {
		close(port_fd);
		error_msg = _("Unable to query serial port signals on ") + name;
		return -1;
	}
	bits &= ~(TIOCM_DTR | TIOCM_RTS);
	if (ioctl(port_fd, TIOCMSET, &bits) < 0) {
		close(port_fd);
		error_msg = _("Unable to control serial port signals on ") + name;
		return -1;
	}
	if (tcgetattr(port_fd, &settings_orig) < 0) {
		close(port_fd);
		error_msg = _("Unable to access baud rate on port ") + name;
		return -1;
	}
	memset(&settings, 0, sizeof(settings));
	settings.c_cflag = CS8 | CLOCAL | CREAD | HUPCL;
	settings.c_iflag = IGNBRK | IGNPAR;
	Set_baud(baud_rate);
	tcflush(port_fd, TCIFLUSH);
#elif defined(WINDOWS)
	COMMCONFIG cfg;
	COMMTIMEOUTS timeouts;
	int got_default_cfg=0, port_num;
	char buf[1024], name_createfile[64], name_commconfig[64], *p;
	DWORD len;

	snprintf(buf, sizeof(buf), _("%s"), name.c_str());
	p = strstr(buf, _("COM"));
	if (p && sscanf(p + 3, _("%d"), &port_num) == 1) {
	  printf(_("port_num = %d\n"), port_num);
	  snprintf(name_createfile, sizeof(name_createfile), _("\\\\.\\COM%d"), port_num);
	  snprintf(name_commconfig, sizeof(name_commconfig), _("COM%d"), port_num);
	} else {
	  snprintf(name_createfile, sizeof(name_createfile), _("%s"), name.c_str());
	  snprintf(name_commconfig, sizeof(name_commconfig), _("%s"), name.c_str());
	}
	len = sizeof(COMMCONFIG);
	if (GetDefaultCommConfig(name_commconfig, &cfg, &len)) {
		// this prevents unintentionally raising DTR when opening
		// might only work on COM1 to COM9
		got_default_cfg = 1;
		memcpy(&port_cfg_orig, &cfg, sizeof(COMMCONFIG));
		cfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
		cfg.dcb.fRtsControl = RTS_CONTROL_DISABLE;
		SetDefaultCommConfig(name_commconfig, &cfg, sizeof(COMMCONFIG));
	} else {
	  printf(_("error with GetDefaultCommConfig\n"));
	}
	port_handle = CreateFile(name_createfile, GENERIC_READ | GENERIC_WRITE,
	   0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if (port_handle == INVALID_HANDLE_VALUE) {
		win32_err(buf);
		error_msg =  _("Unable to open ") + name + _(", ") + buf;
		return -1;
	}
	len = sizeof(COMMCONFIG);
	if (!GetCommConfig(port_handle, &port_cfg, &len)) {
		CloseHandle(port_handle);
		win32_err(buf);
		error_msg = _("Unable to read communication config on ") + name + _(", ") + buf;
		return -1;
	}
	if (!got_default_cfg) {
		memcpy(&port_cfg_orig, &port_cfg, sizeof(COMMCONFIG));
	}
	// http://msdn2.microsoft.com/en-us/library/aa363188(VS.85).aspx
	port_cfg.dcb.BaudRate = baud_rate;
	port_cfg.dcb.fBinary = TRUE;
	port_cfg.dcb.fParity = FALSE;
	port_cfg.dcb.fOutxCtsFlow = FALSE;
	port_cfg.dcb.fOutxDsrFlow = FALSE;
	port_cfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
	port_cfg.dcb.fDsrSensitivity = FALSE;
	port_cfg.dcb.fTXContinueOnXoff = TRUE;	// ???
	port_cfg.dcb.fOutX = FALSE;
	port_cfg.dcb.fInX = FALSE;
	port_cfg.dcb.fErrorChar = FALSE;
	port_cfg.dcb.fNull = FALSE;
	port_cfg.dcb.fRtsControl = RTS_CONTROL_DISABLE;
	port_cfg.dcb.fAbortOnError = FALSE;
	port_cfg.dcb.ByteSize = 8;
	port_cfg.dcb.Parity = NOPARITY;
	port_cfg.dcb.StopBits = ONESTOPBIT;
	if (!SetCommConfig(port_handle, &port_cfg, sizeof(COMMCONFIG))) {
		CloseHandle(port_handle);
		win32_err(buf);
		error_msg = _("Unable to write communication config to ") + name + _(", ") + buf;
		return -1;
	}
	if (!EscapeCommFunction(port_handle, CLRDTR | CLRRTS)) {
		CloseHandle(port_handle);
		win32_err(buf);
		error_msg = _("Unable to control serial port signals on ") + name + _(", ") + buf;
		return -1;
	}
	// http://msdn2.microsoft.com/en-us/library/aa363190(VS.85).aspx
	// setting to all zeros means timeouts are not used
	//timeouts.ReadIntervalTimeout		= 0;
	timeouts.ReadIntervalTimeout		= MAXDWORD;
	timeouts.ReadTotalTimeoutMultiplier	= 0;
	timeouts.ReadTotalTimeoutConstant	= 0;
	timeouts.WriteTotalTimeoutMultiplier	= 0;
	timeouts.WriteTotalTimeoutConstant	= 0;
	if (!SetCommTimeouts(port_handle, &timeouts)) {
		CloseHandle(port_handle);
		win32_err(buf);
		error_msg = _("Unable to write timeout settings to ") + name + _(", ") + buf;
		return -1;
	}
#endif
	port_name = name;
	port_is_open = 1;
	return 0;
}
Пример #3
0
int _init_uart(char* nm, char* speed)
{
	char fullNm[20];
	DCB dcb;
	DWORD dwErr;
	COMMTIMEOUTS tmo;
	COMSTAT comStat;
	COMMCONFIG ccfg;
	DWORD ccfgLen;
	int portNum = 0;
	char* scannm;
	char* shownm;
	char modemode;

	// skip COM if specified and scan number and mode (optional)
	scannm = strnicmp(nm, "COM", 3) ? nm : nm+3;
	sscanf(scannm, "%i%c%c", &portNum, &modemode, &serial_mode);

	if (modemode == '!')
		defaultyes = 1;	// omit Yes/No before programming
	
	// port number specified ?
	if(portNum)
	{
		sprintf(fullNm, "\\\\.\\COM%d", portNum);
		nm = fullNm;
	}

	// name to show in error messages
	shownm = nm;
	// do not show backslashes in error message
	if(!strncmp(shownm, "\\\\.\\", 4))
		shownm += 4;

	// try not to make pulse on DTR line during open
	ccfgLen = sizeof(ccfg);
	if(GetDefaultCommConfig(shownm, &ccfg, &ccfgLen))
	{
		ccfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
		if(!SetDefaultCommConfig(shownm, &ccfg, ccfgLen))
			fprintf(logfile,  "Warning: can not preset default comm config (%s)\n", shownm);
	}
	//else
		//fprintf(logfile,  "Warning: can not get default comm config (%s)\n", shownm);

	// open port
	port = CreateFile(nm, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
						 	    FILE_ATTRIBUTE_NORMAL, NULL);

	if(port == INVALID_HANDLE_VALUE) 
	{
		//fprintf(logfile,  "Can't open serial port %s\n", shownm);
		return -1;
	}

	// init queues
	PurgeComm(port, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

	// prepare DCB
	dcb.DCBlength = sizeof(dcb);		// sizeof(DCB) 
	dcb.BaudRate = CBR_9600;			// current baud rate 
	dcb.fBinary = TRUE;					// binary mode, no EOF check 
	dcb.fParity = FALSE;				// disable parity checking 
	dcb.fOutxCtsFlow = FALSE;			// CTS output flow control 
	dcb.fOutxDsrFlow = FALSE;			// DSR output flow control 
	dcb.fDtrControl = DTR_CONTROL_DISABLE; // DTR flow control type 
	dcb.fDsrSensitivity = FALSE;		// DSR sensitivity 
	dcb.fTXContinueOnXoff = FALSE;		// XOFF continues Tx 
	dcb.fOutX = FALSE;					// XON/XOFF out flow control 
	dcb.fInX = FALSE;					// XON/XOFF in flow control 
	dcb.fErrorChar = FALSE;				// enable error replacement 
	dcb.fNull = FALSE;					// enable null stripping 
	dcb.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control 
	dcb.fAbortOnError = FALSE;			// abort reads/writes on error 
	dcb.XonLim = 100;					// transmit XON threshold 
	dcb.XoffLim = 100;					// transmit XOFF threshold 
	dcb.ByteSize = 8;					// number of bits/, 4-8 
	dcb.Parity = NOPARITY;				// 0-4=no,odd,even,mark,space 
	dcb.StopBits = ONESTOPBIT;			// 0,1,2 = 1, 1.5, 2 
	dcb.XonChar = 17;					// Tx and Rx XON acter 
	dcb.XoffChar = 19;					// Tx and Rx XOFF acter 
	dcb.ErrorChar = 0;					// error replacement acter 
	dcb.EofChar = 0;					// end of input acter 
	dcb.EvtChar = 0;					// received event acter 

	// speed string specified ?
	if(speed)
	{
		if(sscanf(speed, "%lu", &dcb.BaudRate) != 1)
		{
			fprintf(logfile,  "Invalid speed specified (%s)\n", speed);
			return -1;
		}
	}

	if(!SetCommState(port, &dcb))
	{
		fprintf(logfile,  "Can't setup serial port (%s @ %s)\n", shownm, speed);
		return -1;
	}

	if(!SetupComm(port, 512, 512))
	{
		fprintf(logfile,  "Can't setup serial port queues.\n");
		return -1;
	}

	tmo.ReadIntervalTimeout = 100;		// between two characters
	tmo.ReadTotalTimeoutMultiplier = 1;
	tmo.ReadTotalTimeoutConstant = 500;
	tmo.WriteTotalTimeoutMultiplier = 1;
	tmo.WriteTotalTimeoutConstant = 1000;

	if(!SetCommTimeouts(port, &tmo))
	{
		fprintf(logfile,  "Can't set serial port timeouts (%s)\n", shownm);
		return -1;
	}
	if(!SetCommMask(port, EV_TXEMPTY))
	{
		fprintf(logfile,  "Can't set serial port waitmask (%s)\n", shownm);
		return -1;
	}

	// we are ready !
	EscapeCommFunction(port, CLRDTR);
	ClearCommError(port, &dwErr, &comStat);
	return 1;
}
    int ArduinoSerial::openPort(const char *portName)
    {


        _portName = std::string(portName);
        _portOpened = false;
        triedToConfigureAgain = false;
        closeSerial();
        fd = 0;
        _numberOfChannels = 1;
#if defined(__APPLE__) || defined(__linux__)
        struct termios options;

        fd = open(portName, O_RDWR | O_NOCTTY | O_NDELAY);//O_SHLOCK
        sleep(2);
        int bits;
#endif
#ifdef __APPLE__
        std::stringstream sstm;

        if (fd < 0) {
            sstm << "Unable to open " << portName << ", " << strerror(errno);
            errorString = sstm.str();
            std::cout<<"Unable to open "<<portName<<", "<<strerror(errno)<<"\n";
            return -1;
        }
        if (ioctl(fd, TIOCEXCL) == -1) {
            close(fd);
            sstm << "Unable to get exclussive access to port " << portName;;
            errorString = sstm.str();
            std::cout<<"Unable to get exclussive access to port "<<portName<<"\n";
            return -1;
        }
        if (ioctl(fd, TIOCMGET, &bits) < 0) {
            close(fd);
            sstm <<"Unable to query serial port signals on " << portName;
            errorString = sstm.str();
            std::cout<<"Unable to query serial port signals on "<<portName<<"\n";
            return -1;
        }
        bits &= ~(TIOCM_DTR | TIOCM_RTS);
        if (ioctl(fd, TIOCMSET, &bits) < 0) {
            close(fd);
            sstm <<"Unable to control serial port signals on " << portName;
            errorString = sstm.str();
            std::cout<<"Unable to control serial port signals on "<<portName<<"\n";
            return -1;
        }
        struct termios settings_orig;
        if (tcgetattr(fd, &settings_orig) < 0) {
            close(fd);
            sstm <<"Unable to access baud rate on port " << portName;
            errorString = sstm.str();
            std::cout<<"Unable to access baud rate on port "<<portName<<"\n";
            return -1;
        }
#endif
#ifdef __linux__
 // struct serial_struct kernel_serial_settings;
    struct termios settings_orig;
    //struct termios settings;
    if (fd < 0)
    {
        if (errno == EACCES)
        {
            std::cout<<"Unable to access "<< portName<< ", insufficient permission";
            // TODO: we could look at the permission bits and owner
            // to make a better message here
        }
        else if (errno == EISDIR)
        {
            std::cout<< "Unable to open " << portName <<
                     ", Object is a directory, not a serial port";
        }
        else if (errno == ENODEV || errno == ENXIO)
        {
            std::cout<< "Unable to open " << portName <<
                     ", Serial port hardware not installed";
        }
        else if (errno == ENOENT)
        {
            std::cout<< "Unable to open " << portName <<
                     ", Device name does not exist";
        }
        else
        {
            std::cout<< "Unable to open " << portName; //<<

        }
        return -1;
    }
    if (ioctl(fd, TIOCMGET, &bits) < 0)
    {
        close(fd);
        std::cout<< "Unable to query serial port signals";
        return -1;
    }
    bits &= ~(TIOCM_DTR | TIOCM_RTS);
    if (ioctl(fd, TIOCMSET, &bits) < 0)
    {
        close(fd);
        std::cout<< "Unable to control serial port signals";
        return -1;
    }
    if (tcgetattr(fd, &settings_orig) != 0)
    {
        close(fd);
        std::cout<< "Unable to query serial port settings (perhaps not a serial port)";
        return -1;
    }
    /*memset(&settings, 0, sizeof(settings));
    settings.c_iflag = IGNBRK | IGNPAR;
    settings.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
    Set_baud(baud_rate);
    if (ioctl(port_fd, TIOCGSERIAL, &kernel_serial_settings) == 0) {
    	kernel_serial_settings.flags |= ASYNC_LOW_LATENCY;
    	ioctl(port_fd, TIOCSSERIAL, &kernel_serial_settings);
    }
    tcflush(port_fd, TCIFLUSH);*/
#endif
#if defined(__APPLE__) || defined(__linux__)
        if (fd == -1)
        {
            std::cout<<"Can't open serial port\n";
            return -1;
        }
        fcntl(fd, F_SETFL, 0);    // clear all flags on descriptor, enable direct I/O
        tcgetattr(fd, &options);   // read serial port options
        // enable receiver, set 8 bit data, ignore control lines
        options.c_cflag |= (CLOCAL | CREAD | CS8);
        // disable parity generation and 2 stop bits
        options.c_cflag &= ~(PARENB | CSTOPB);

        //cfsetispeed(&options, B9600);
        //cfsetospeed(&options, B9600);

        cfsetispeed(&options, B230400);
        cfsetospeed(&options, B230400);

        // set the new port options
        tcsetattr(fd, TCSANOW, &options);
#endif

#ifdef _WIN32

	COMMCONFIG cfg;
	COMMTIMEOUTS timeouts;
	int got_default_cfg=0, port_num;
	char buf[1024], name_createfile[64], name_commconfig[64], *p;
	DWORD len;

	snprintf(buf, sizeof(buf), "%s", _portName.c_str());
	p = strstr(buf, "COM");
	if (p && sscanf(p + 3, "%d", &port_num) == 1) {
		printf("port_num = %d\n", port_num);
		snprintf(name_createfile, sizeof(name_createfile), "\\\\.\\COM%d", port_num);
		snprintf(name_commconfig, sizeof(name_commconfig), "COM%d", port_num);
	} else {
		snprintf(name_createfile, sizeof(name_createfile), "%s", _portName.c_str());
		snprintf(name_commconfig, sizeof(name_commconfig), "%s", _portName.c_str());
	}
	len = sizeof(COMMCONFIG);
	if (GetDefaultCommConfig(name_commconfig, &cfg, &len)) {
		// this prevents unintentionally raising DTR when opening
		// might only work on COM1 to COM9
		got_default_cfg = 1;
		memcpy(&port_cfg_orig, &cfg, sizeof(COMMCONFIG));
		cfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
		cfg.dcb.fRtsControl = RTS_CONTROL_DISABLE;
		SetDefaultCommConfig(name_commconfig, &cfg, sizeof(COMMCONFIG));
	} else {
		printf("error with GetDefaultCommConfig\n");
	}
	port_handle = CreateFile(name_createfile, GENERIC_READ | GENERIC_WRITE,
	   0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if (port_handle == INVALID_HANDLE_VALUE) {
		win32_err(buf);
		//error_msg =  "Unable to open " + _portName + ", " + buf;
		return -1;
	}
	len = sizeof(COMMCONFIG);
	if (!GetCommConfig(port_handle, &port_cfg, &len)) {
		CloseHandle(port_handle);
		win32_err(buf);
		//error_msg = "Unable to read communication config on " + _portName + ", " + buf;
		return -1;
	}
	if (!got_default_cfg) {
		memcpy(&port_cfg_orig, &port_cfg, sizeof(COMMCONFIG));
	}
	// http://msdn2.microsoft.com/en-us/library/aa363188(VS.85).aspx
	port_cfg.dcb.BaudRate = 230400;
	port_cfg.dcb.fBinary = TRUE;
	port_cfg.dcb.fParity = FALSE;
	port_cfg.dcb.fOutxCtsFlow = FALSE;
	port_cfg.dcb.fOutxDsrFlow = FALSE;
	port_cfg.dcb.fDtrControl = DTR_CONTROL_DISABLE;
	port_cfg.dcb.fDsrSensitivity = FALSE;
	port_cfg.dcb.fTXContinueOnXoff = TRUE;	// ???
	port_cfg.dcb.fOutX = FALSE;
	port_cfg.dcb.fInX = FALSE;
	port_cfg.dcb.fErrorChar = FALSE;
	port_cfg.dcb.fNull = FALSE;
	port_cfg.dcb.fRtsControl = RTS_CONTROL_DISABLE;
	port_cfg.dcb.fAbortOnError = FALSE;
	port_cfg.dcb.ByteSize = 8;
	port_cfg.dcb.Parity = NOPARITY;
	port_cfg.dcb.StopBits = ONESTOPBIT;
	if (!SetCommConfig(port_handle, &port_cfg, sizeof(COMMCONFIG))) {
		CloseHandle(port_handle);
		win32_err(buf);
		//error_msg = "Unable to write communication config to " + name + ", " + buf;
		return -1;
	}
	if (!EscapeCommFunction(port_handle, CLRDTR | CLRRTS)) {
		CloseHandle(port_handle);
		win32_err(buf);
		//error_msg = "Unable to control serial port signals on " + name + ", " + buf;
		return -1;
	}
	// http://msdn2.microsoft.com/en-us/library/aa363190(VS.85).aspx
	// setting to all zeros means timeouts are not used
	//timeouts.ReadIntervalTimeout		= 0;
	timeouts.ReadIntervalTimeout		= MAXDWORD;
	timeouts.ReadTotalTimeoutMultiplier	= 0;
	timeouts.ReadTotalTimeoutConstant	= 0;
	timeouts.WriteTotalTimeoutMultiplier	= 0;
	timeouts.WriteTotalTimeoutConstant	= 0;
	if (!SetCommTimeouts(port_handle, &timeouts)) {
		CloseHandle(port_handle);
		win32_err(buf);
		//error_msg = "Unable to write timeout settings to " + name + ", " + buf;
		return -1;
	}

#endif // _WIN32

        circularBuffer[0] = '\n';

        cBufHead = 0;
        cBufTail = 0;

        serialCounter = 0;

        _portOpened = true;


        setNumberOfChannelsAndSamplingRate(1, maxSamplingRate());


        return fd;
    }