📄 pmdser.c
字号:
/** PMDSer.c -- parallel interface command/data transfer functions for the MC2xxx Performance Motion Devices, Inc.*/#include <stdio.h>#include <stdlib.h>#include "PMDtypes.h"#include "PMDecode.h"#include "PMDtrans.h"#include "PMDconio.h"#include "PMDser.h"#include "string.h"// only include this if we are running in diagnostics mode#include "PMDdiag.h"#ifdef _LINUX#include <fcntl.h>#include <linux/termios.h>#include <linux/serial.h>#include <time.h>#include <unistd.h>#include <errno.h>// Even parity.#define EVENPARITY 2// Mark parity.#define MARKPARITY 3// No parity.#define NOPARITY 0// Odd parity.#define ODDPARITY 1// Space parity#define SPACEPARITY 4static struct termios oldtio;#endifstatic int g_deviceBaudRate;// ------------------------------------------------------------------------static HANDLE OpenPort( int portnum ){ HANDLE hPort; char szPort[ 32 ];#ifdef WIN32 sprintf( szPort, "COM%d", portnum ); hPort = CreateFile( szPort, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );#endif#ifdef _LINUX // Open read/write, not a controlling terminal, // don't block if DCD ser line is not active // int flags = O_RDWR | O_NOCTTY | O_NDELAY; int flags = O_RDWR | O_NOCTTY; sprintf( szPort, "/dev/ttyUSB%d", portnum ); hPort = open( szPort, flags ); if ( hPort == INVALID_HANDLE_VALUE ) { sprintf( szPort, "/dev/ttyS%d", portnum ); hPort = open( szPort, flags ); if ( hPort == INVALID_HANDLE_VALUE ) { sprintf( szPort, "/dev/usb/tty/%d", portnum ); hPort = open( szPort, flags ); } }#endif return hPort;}// ------------------------------------------------------------------------static void ClosePort( HANDLE hPort ){ if ( hPort != INVALID_HANDLE_VALUE ) {#ifdef WIN32 CloseHandle( hPort );#endif#ifdef _LINUX tcsetattr( hPort, TCSANOW, &oldtio); close( hPort );#endif }}// ------------------------------------------------------------------------static BOOL ConfigPortTimeouts( HANDLE hPort, long rttm, long rttc ){#ifdef WIN32 COMMTIMEOUTS timeouts; timeouts.ReadIntervalTimeout = 0; timeouts.ReadTotalTimeoutMultiplier = rttm; timeouts.ReadTotalTimeoutConstant = rttc; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 0; return SetCommTimeouts( hPort, &timeouts );#endif#ifdef _LINUX struct termios tio; tcgetattr( hPort, &tio ); tio.c_cc[VTIME] = rttc/100; tcflush( hPort, TCIFLUSH); tcsetattr( hPort, TCSANOW, &tio); return TRUE;#endif}// ------------------------------------------------------------------------static BOOL FlushPort( HANDLE hPort ){#ifdef WIN32 return FlushFileBuffers( hPort );#endif#ifdef _LINUX // Block til all data has been sent tcdrain( hPort ); return TRUE;#endif}// ------------------------------------------------------------------------// Blocking write to the serial portstatic BOOL WritePort( HANDLE hPort, char* buf, unsigned long toWrite, unsigned long* written ){#ifdef WIN32 return WriteFile( hPort, buf, toWrite, written, NULL );#endif#ifdef _LINUX ssize_t writ; writ = write( hPort, buf, toWrite ); if ( writ < 0 ) { *written = 0; return FALSE; } *written = writ; return TRUE;#endif}// ------------------------------------------------------------------------// Blocking read from the serial portstatic BOOL ReadPort( HANDLE hPort, char* buf, unsigned long toRead, unsigned long* numread ){#ifdef WIN32 return ReadFile( hPort, buf, toRead, numread, NULL );#endif#ifdef _LINUX ssize_t r; int nread = 0; // printf( "Reading %d bytes\n", toRead ); // while ( toRead != 0 ) { r = read( hPort, buf, toRead ); if ( r < 1 ) { *numread = r; return FALSE; } nread += r; toRead -= r; buf += r; } *numread = nread; return TRUE;#endif}// ------------------------------------------------------------------------// Discards all buffered but unread data on the portstatic void FlushRxPort( HANDLE hPort ){#ifdef WIN32 PurgeComm( hPort, PURGE_RXCLEAR );#endif#ifdef _LINUX tcflush( hPort, TCIFLUSH );#endif}// ------------------------------------------------------------------------static void SLEEP( unsigned long ms ){#ifdef WIN32 Sleep( ms );#endif#ifdef _LINUX struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = ms*1000; nanosleep( &ts, NULL );#endif}// ------------------------------------------------------------------------PMDuint16 PMDSerial_GetStatus(void* transport_data){ return 0;}// ------------------------------------------------------------------------PMDuint16 PMDSerial_IsReady(void* transport_data){ return 1;}// ------------------------------------------------------------------------PMDuint16 PMDSerial_HasInterrupt(void* transport_data){ return 0;}// ------------------------------------------------------------------------PMDuint16 PMDSerial_HasError(void* transport_data){ return 0;}// ------------------------------------------------------------------------PMDuint16 PMDSerial_HardReset(void* transport_data){ return 0; // unsupported}// ------------------------------------------------------------------------PMDuint16 PMDSerial_InitPort(void* transport_data){ PMDSerialIOData* SIOtransport_data = (PMDSerialIOData*)transport_data; SIOtransport_data->hPort = INVALID_HANDLE_VALUE; SIOtransport_data->hPort = OpenPort( SIOtransport_data->port ); if( SIOtransport_data->hPort == INVALID_HANDLE_VALUE ) { return PMD_ERR_InvalidSerialPort; } if( !PMDSerial_SetConfig( transport_data, SIOtransport_data->baud, NOPARITY) ) { ClosePort( SIOtransport_data->hPort ); return PMD_ERR_InvalidSerialPort; } if ( !ConfigPortTimeouts( SIOtransport_data->hPort, 10, 100 ) ) { ClosePort( SIOtransport_data->hPort ); return PMD_ERR_InvalidSerialPort; } // make sure the serial port is synched to receive a command byte first// PMDSerial_Sync(transport_data); return PMD_ERR_OK;}// ------------------------------------------------------------------------void PMDSerial_Close(void* transport_data){ PMDSerialIOData* SIOtransport_data = (PMDSerialIOData*)transport_data; if (transport_data != NULL) { if ( SIOtransport_data->hPort!=INVALID_HANDLE_VALUE ) { ClosePort( SIOtransport_data->hPort ); SIOtransport_data->hPort = INVALID_HANDLE_VALUE; } free(transport_data); } transport_data = NULL;}// ------------------------------------------------------------------------BOOL PMDSerial_SetConfig(void* transport_data,PMDuint32 b,PMDuint8 p){ PMDSerialIOData* SIOtransport_data = (PMDSerialIOData*)transport_data;#ifdef WIN32 DCB dcb;#endif#ifdef _LINUX struct termios newtio; long BAUD; long PARITY; long PARITYON; long STOPBITS; int customBaud = 0;#endif if( !SIOtransport_data || (SIOtransport_data->hPort == INVALID_HANDLE_VALUE) ) return FALSE; SIOtransport_data->baud = b; SIOtransport_data->parity = p;#ifdef WIN32 // if the baud is > 57600 set the stop bits to 2 SIOtransport_data->stop = b<57600?ONESTOPBIT:TWOSTOPBITS; dcb.DCBlength = sizeof(DCB); dcb.BaudRate = b; dcb.fBinary = 1; dcb.fParity = TRUE; dcb.fOutxCtsFlow = 0; dcb.fOutxDsrFlow = 0; dcb.fDtrControl = DTR_CONTROL_DISABLE; dcb.fDsrSensitivity = 0; dcb.fTXContinueOnXoff = 0; dcb.fOutX = 0; dcb.fInX = 0; dcb.fErrorChar = 0; dcb.fNull = 0; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fAbortOnError = 0; dcb.XonLim = 0; dcb.XoffLim = 0; dcb.ByteSize = 8; dcb.Parity = p; dcb.StopBits = SIOtransport_data->stop; dcb.XonChar = 0; dcb.XoffChar = 0; dcb.ErrorChar = 0; dcb.EofChar = 0; dcb.EvtChar = 0; if( !SetCommState( SIOtransport_data->hPort, &dcb ) ) return FALSE;#endif#ifdef _LINUX // if the baud is > 57600 set the stop bits to 2 SIOtransport_data->stop = b<57600?1:2; // save current port settings tcgetattr( SIOtransport_data->hPort, &oldtio ); tcgetattr( SIOtransport_data->hPort, &newtio ); switch ( b ) { case 230400: BAUD = B230400; break; case 115200: BAUD = B115200; break; case 57600: BAUD = B57600; break; case 38400: BAUD = B38400; break; case 19200: BAUD = B19200; break; case 9600: BAUD = B9600; break; case 4800: BAUD = B4800; break; case 2400: BAUD = B2400; break; case 1800: BAUD = B1800; break; case 1200: BAUD = B1200; break; case 600: BAUD = B600; break; case 300: BAUD = B300; break; case 200: BAUD = B200; break; case 150: BAUD = B150; break; case 134: BAUD = B134; break; case 110: BAUD = B110; break; case 75: BAUD = B75; break; case 50: BAUD = B50; break; default: // custom baudrate customBaud = 1; BAUD = B38400; break; } //end of switch baud_rate switch ( SIOtransport_data->stop ) { case 1: default: STOPBITS = 0; break; case 2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -