int zozSerialOpen(unsigned int port, unsigned int baud) /* opens the serial port, tests for the presence of the stepper and then * * returns a handle to the port */ { HANDLE hCommDev; DCB dcb; // device control block COMMTIMEOUTS commTimeOuts; char szPort[8]; char readbuf[16]; if ((port < 0) || (port > 9)) { printf("Error opening port: port number %d out of range 0..9\n", port); return(-1); } strcpy (szPort, "COM"); szPort[3] = port+'0'; // to char... works for 0 - 9 szPort[4] = '\0'; // open the serial port... hCommDev = CreateFile(szPort, GENERIC_READ | GENERIC_WRITE, 0, // exclusive access NULL, // no security attrs OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hCommDev == (HANDLE)-1) { printf("Error opening port: couldn't open port %s\n", szPort); hCommDev = 0; return(-1); } // get any early notifications SetCommMask(hCommDev, EV_RXCHAR); // set buffer sizes SetupComm(hCommDev, 256, 256); // Set the parameters on the comms if (!GetCommState(hCommDev, &dcb)) { printf("Error opening port: couldn't get current DCB settings\n"); return(-1); } // set baud rate... switch (baud) { case 1200: dcb.BaudRate = CBR_1200; break; case 2400: dcb.BaudRate = CBR_2400; break; case 4800: dcb.BaudRate = CBR_4800; break; case 9600: default: dcb.BaudRate = CBR_9600; break; case 19200: dcb.BaudRate = CBR_19200; break; case 38400: dcb.BaudRate = CBR_38400; break; case 57600: dcb.BaudRate = CBR_57600; break; case 115200: dcb.BaudRate = CBR_115200; break; } dcb.fBinary = TRUE; dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fDsrSensitivity = FALSE; dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.fNull = FALSE; dcb.fAbortOnError = FALSE; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fAbortOnError = 0; // don't abort on error dcb.ByteSize = 8; // 5, 6, 7, or 8 dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; // setting size recommended by Microsoft's serial I/O web page dcb.DCBlength = sizeof(dcb); if (!SetCommState(hCommDev, &dcb)) { printf("Error opening port: couldn't set comm state - possible invalid DCB structure\n"); } commTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF; // timeout = bytesToBeWritten * multiplier + Constant(milliseconds) commTimeOuts.ReadTotalTimeoutMultiplier = 0; commTimeOuts.ReadTotalTimeoutConstant = 1000; // milliseconds commTimeOuts.WriteTotalTimeoutMultiplier = 0; commTimeOuts.WriteTotalTimeoutConstant = 1000; SetCommTimeouts(hCommDev, &commTimeOuts); // setup overlapped PurgeComm(hCommDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); zozWriteChar(hCommDev, '?'); // check for stepper activity Sleep(50); // pause for reset if (!zozCanRead(hCommDev)) { printf("Error opening port: no response from reset command\n"); return(-1); } zozRead(hCommDev, readbuf, sizeof(readbuf)); printf("Port status: %s\n", readbuf); return((int)hCommDev); } void zozSerialClose(HANDLE hSerialDev) /* closes serial port - not really necessary but friendly */ { CloseHandle(hSerialDev); return; } int zozCanRead(HANDLE hSerialDev) /* checks for non-empty receive buffer */ { COMSTAT cs; DWORD dwErrors; // seems to be the only way to get COMSTAT if (!ClearCommError (hSerialDev, &dwErrors, &cs)) { printf("Error: ClearCommError failed in zozCanRead()\n"); return FALSE; } return cs.cbInQue != 0; } int zozRead(HANDLE hSerialDev, char *psz, int maxlen) /* reads data from receive buffer, up to maxlen chars */ { DWORD readLen; ReadFile(hSerialDev, psz, maxlen, &readLen, 0); // need to null-terminate it for ascii psz[readLen] = '\0'; return(readLen); } void zozWrite(HANDLE hSerialDev, char *psz, int len) /* writes a string to a serial device */ { DWORD writtenLen; if (len == 0) { len = strlen(psz); } if (!WriteFile(hSerialDev, psz, len, &writtenLen, 0)) { if (GetLastError() != ERROR_IO_PENDING) // WriteFile failed, but isn't delayed. Report error. { printf("Error: write failed\n"); } } } void zozWriteChar(HANDLE hSerialDev, char c) /* writes a single character to a serial device */ { char cmd[2]; cmd[0] = c; cmd[1] = '\0'; zozWrite(hSerialDev, cmd, 1); }