В данном разделе представлены фрагменты текстов программ, которые открывают, настраивают, работают и закрывают файл устройства, ассоциированный с RS-232 портом, в разных операционных системах, а именно:
Процедура инициализации порта RS-232 в Linux/GCC:
// Description: Program for PowerAnt speed test #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <termios.h> #include <unistd.h> #include <time.h> void init_raw_tty( int fd ){ struct termios newtio; bzero(&newtio, sizeof(newtio)); newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD /*| CSTOPB */; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; /* set input mode (non-canonical, no echo,...) */ newtio.c_lflag = 0; newtio.c_cc[VTIME] = 1; newtio.c_cc[VMIN] = 1; /* blocking read until 5 chars received */ tcflush(fd, TCIFLUSH); tcsetattr(fd,TCSANOW,&newtio); } FILE * powerants; int powerants_int; void printAnswer( void ){ int inCh; do { inCh = fgetc(powerants); if( inCh > 0 ){ printf("%c",inCh); if( inCh == 0x0D ){ printf("\n"); }; } else { printf("Non blocking output!\n"); // Ввод блокирующий, то есть этого сообщения мы никогда не увидим, если все будет нормально exit( 0 ); }; } while( inCh != 0x0D ); } int main( int ArgC, char * ArgV[] ){ if( ArgC < 2 ){ fprintf( stderr, "ERROR: some parameters are missing (f.e. /dev/ttyS1)\n"); return 0; }; powerants_int = open(ArgV[1],O_RDWR | O_NOCTTY ); if(! powerants_int ){ fprintf( stderr, "ERROR: (open) %s\n", strerror( errno ) ); return -1; }; printf("Working with %s, 9600 8N1\n",ArgV[1]); init_raw_tty( powerants_int ); powerants = fdopen( powerants_int, "w+b" ); fputc( 0x1B, powerants ); // Прочистка буфера приема PowerAnt fprintf(powerants,"??\r"); // Команда ?? printAnswer(); fclose(powerants); return 0; };
Borland C++, в справочной системе, предоставляет стандартный пример работы с COM портом. Приведенная тут программа это несколько измененный стандартный пример, который превращен в универсальную программу для работы с устройствами PowerAnt, подключенными к любому COM порту (COM1, COM2,...).
#include <bios.h> // Консольный ввод-вывод #include <conio.h> // Для функции atoi #include <stdlib.h> #define COM1 0 #define DATA_READY 0x100 #define TRUE 1 #define FALSE 0 #define SETTINGS (_COM_9600 | _COM_CHR8 | _COM_STOP1 | _COM_NOPARITY) int main(int ArgC, char * ArgV[]) { unsigned in, out, status, commnum; if( ArgC == 1 ){ cprintf("Pass COM port number as first argument (COM1=0, COM2=1...)\r\n"); return 0; }; commnum = atoi(ArgV[1]); cprintf("Working with COM%i\r\n",(commnum+COM1+1)); _bios_serialcom(_COM_INIT, COM1 + commnum, SETTINGS); cprintf("... _BIOS_SERIALCOM for PowerAnts, press [ESC] to exit ...\r\n"); for (;;) { status = _bios_serialcom(_COM_STATUS, COM1 + commnum, 0); if (status & DATA_READY) if ((out = _bios_serialcom(_COM_RECEIVE, COM1 + commnum, 0) & 0x7F) != 0) putch(out); if (kbhit()) { if ((in = getch()) == '\x1B') break; _bios_serialcom(_COM_SEND, COM1 + commnum, in); } } return 0; }
В данном фрагменте представлен только код, который отвечает за работу с COM портом, а именно: открытие и инициализация файла устройства, закрытие файла устройства, процедура отправки команды в PowerAnt и получения отчета о её выполнении. Также приведена процедура вывода сообщения об системной ошибке.
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Begin.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- #include <winbase.h> #include <stdio.h> DCB pwrAntDCB; HANDLE pwrAntHANDLE; COMMTIMEOUTS pwrAntCommTimeouts; void ShowError( const char * whereError ){ LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); // Display the string. MessageBox( NULL, (const char *)lpMsgBuf, "GetLastError", MB_OK|MB_ICONINFORMATION ); // Free the buffer. LocalFree( lpMsgBuf ); } BOOL openPwrAntPort( const char * comName ){ pwrAntHANDLE = CreateFile( comName ,GENERIC_READ | GENERIC_WRITE // Read-Write access ,0 // Cannot be shared ,NULL // Security Attributes ,OPEN_EXISTING // Open existing file ,FILE_ATTRIBUTE_NORMAL || FILE_FLAG_WRITE_THROUGH // | FILE_FLAG_NO_BUFFERING // Auto flush ,NULL // Template File ); if( ! pwrAntHANDLE ){ ShowError("CreateFile"); return FALSE; }; if( ! GetCommState( pwrAntHANDLE, &pwrAntDCB )){ ShowError("GetCommState"); return FALSE; }; if( ! BuildCommDCB( "baud=9600 parity=N data=8 stop=1", &pwrAntDCB ) ){ ShowError("BuildCommDCB"); return FALSE; }; if( ! SetCommState( pwrAntHANDLE, &pwrAntDCB )){ ShowError("SetCommState"); return FALSE; }; if( ! GetCommTimeouts( pwrAntHANDLE, &pwrAntCommTimeouts ) ){ ShowError("GetCommTimeouts"); return FALSE; }; pwrAntCommTimeouts.ReadIntervalTimeout = 10; // milliseconds pwrAntCommTimeouts.ReadTotalTimeoutMultiplier = 0; // pwrAntCommTimeouts.ReadTotalTimeoutConstant = 0; // pwrAntCommTimeouts.WriteTotalTimeoutMultiplier = 0; // pwrAntCommTimeouts.WriteTotalTimeoutConstant = 0; // if( ! SetCommTimeouts( pwrAntHANDLE, &pwrAntCommTimeouts ) ){ ShowError("SetCommTimeouts"); return FALSE; }; return TRUE; } BOOL pwrAntCMD( const char * cmd ){ unsigned char buff[70]; unsigned long i; unsigned long io_i; for( i = 0 ; cmd[i] ; i++ ){ buff[i] = cmd[i]; }; buff[i++] = 0x0D; buff[i++] = 0x00; // /* { unsigned char buff2[100]; unsigned char * buffptr = buff2; MessageBox( NULL, buff , "Send Command", MB_OK|MB_ICONINFORMATION ); for( unsigned int x = 0 ; x < i ; x++ ){ buffptr += sprintf( buffptr, "%02x ", buff[x] ); }; MessageBox( NULL, buff2 , "Command by Bytes", MB_OK|MB_ICONINFORMATION ); } */ if( ! WriteFile( pwrAntHANDLE ,buff , i-1 // Do not send Zero at end of command , &io_i , NULL )){ ShowError("WriteFile"); return FALSE; }; if( ! FlushFileBuffers( pwrAntHANDLE )){ ShowError("FlushFileBuffers"); return FALSE; }; // Read the answer from PowerAnt if( ! ReadFile( pwrAntHANDLE ,buff , 50 // Full PowerAnt Buffer Length , &io_i , NULL )){ ShowError("ReadFile"); return FALSE; }; buff[io_i] = 0; // Null Termination if( io_i > 3 || (buff[0] != '+') ){ MessageBox( NULL, buff , "Command execution result", MB_OK|MB_ICONINFORMATION ); /* unsigned char buff2[100]; unsigned char * buffptr = buff2; for( unsigned int x = 0 ; x < io_i ; x++ ){ buffptr += sprintf( buffptr, "%02x ", buff[x] ); }; MessageBox( NULL, buff2 , "Answer by Bytes", MB_OK|MB_ICONINFORMATION ); */ }; return TRUE; } void closePwrAntPort( void ){ if( ! CloseHandle( pwrAntHANDLE )){ ShowError("CloseFile"); return; }; } void __fastcall TForm1::FormCreate(TObject *Sender) { openPwrAntPort( "COM2" ); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormDestroy(TObject *Sender) { closePwrAntPort(); } void __fastcall TForm1::Button1Click(TObject *Sender){ // In Edit1 properties field OEMConvert MUST BE TRUE! pwrAntCMD( Edit1->Text.c_str() ); }