В данном разделе представлены фрагменты текстов программ, которые открывают, настраивают, работают и закрывают файл устройства, ассоциированный с 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() );
}