/*
plcSeria.cpp
Последовательный канал PC
Project: Programming Logic Controller
Copyright (c) 1996 xxxxx ltd.
*/
#if !defined( __DOS_H )
#include <dos.h>
#endif
#if !defined( __PLCSERIA_H )
#include "plcSeria.h"
#endif
#if !defined( __PLCBNET_H )
#include "plcBnet.h"
#endif
IORegisterBlock::IORegisterBlock( bool listAdrPresent )
{
transport = new BitNetTransport( this );
if( listAdrPresent == true )
listAdr = new ListNetworkAdres( iDefaultConnections );
else
listAdr = 0;
}
IORegisterBlock::~IORegisterBlock()
{
if( transport )
{
delete transport;
transport = 0;
}
if( listAdr )
{
delete listAdr;
listAdr = 0;
}
}
bool IORegisterBlock::addConnect( unsigned char newConnect )
{
if( listAdr && (transport->getNetAdres() != newConnect) )
return listAdr->Add( newConnect ) ? true : false;
else
return false;
}
IORegisterBlock& ComBase::operator<<( BitNetProtokol& protokol )
{
for( unsigned short i=0, l= usSizeBitNetProtokol; i < l; i++ )
if( sendByte( protokol[i]) == false )
{
setError( srHardwareError, true );
return *this;
}
return *this;
}
ByteQueue lib;
ComPort::ComPort( char* portName )
{
numByteRead =
numByteWrite =
sizeWrite =
errorCodes =
dwWriteThreadID=
dwReadThreadID = 0L;
namePort = portName;
hComm = CreateFile( portName,
GENERIC_READ | GENERIC_WRITE,
0L,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL );
if( hComm == INVALID_HANDLE_VALUE )
MessageBox(NULL, "Неверное имя порта или он занят другой программой!",
"", MB_ICONSTOP | MB_OK );
bqRead = new ByteQueue(iReadDefaultSerialBufferSizeOnPC);
bqWrite = new ByteQueue(iWriteDefaultSerialBufferSizeOnPC);
bufRead = new char[iReadDefaultSerialBufferSizeOnPC];
bufWrite= new char[iWriteDefaultSerialBufferSizeOnPC];
// Установка буфферов
SetupComm( hComm, usSizeBitNetProtokol*64, usSizeBitNetProtokol*64 ) ;
// очистить информацию о буфферах
PurgeComm( hComm, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
// установки для паралельного в/в
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF ;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0 ;
CommTimeOuts.ReadTotalTimeoutConstant = 4000 ;
CommTimeOuts.WriteTotalTimeoutMultiplier= 0 ;
CommTimeOuts.WriteTotalTimeoutConstant = 4000 ;
SetCommTimeouts( hComm, &CommTimeOuts ) ;
overlapped.Internal =
overlapped.InternalHigh= 0;
overlapped.Offset =
overlapped.OffsetHigh = 0;
overlapped.hEvent = NULL;
hEventWrite = CreateEvent( NULL, TRUE, FALSE, NULL );
hEventRead = CreateEvent( NULL, TRUE, FALSE, NULL );
DCB dcb ;
GetCommState( hComm, &dcb );
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.fBinary = TRUE;
dcb.fParity = NOPARITY;
dcb.fOutxCtsFlow = TRUE;
dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fDsrSensitivity = FALSE;
dcb.fNull = FALSE;
SetCommState( hComm, &dcb ) ;
// ::EscapeCommFunction( hComm, SETRTS );
// Нам интересно когда запускать команду чтения
::SetCommMask( hComm, EV_RXCHAR | EV_TXEMPTY | EV_CTS ) ;
// Создаем паралелльный процесс для чтения
hReadThread =
::CreateThread( LPSECURITY_ATTRIBUTES( NULL ),
0,
LPTHREAD_START_ROUTINE( &ComPort::getData ),
LPDWORD(this),
0,
&dwReadThreadID
);
// Создаем паралелльный процесс для записи
hWriteThread =
::CreateThread( LPSECURITY_ATTRIBUTES( NULL ),
0,
LPTHREAD_START_ROUTINE( &ComPort::putData ),
LPDWORD(this),
0,
&dwWriteThreadID
);
::SetThreadPriority( hReadThread, THREAD_PRIORITY_ABOVE_NORMAL );
::SetThreadPriority( hWriteThread,THREAD_PRIORITY_ABOVE_NORMAL );
}
ComPort::~ComPort()
{
CloseHandle( hComm );
CloseHandle( hEventWrite);
CloseHandle( hEventRead );
delete bqRead;
delete bqWrite;
delete bufRead;
delete bufWrite;
}
bool ComPort::sendByte( char byte )
{
if( isTransmitBufferNotFull() )
{
bqWrite->Put( byte );
return true;
}
return false;
}
DWORD __stdcall ComPort::putData( LPDWORD lpdwParam )
{
ComPort& port = (ComPort&)(*lpdwParam);
COMSTAT ComStat ;
while(1)
{
if( (port.sizeWrite = port.bqWrite->GetItemsInContainer()) >= usSizeBitNetProtokol )
{
for( register i = 0; i < port.sizeWrite ; i++ )
port.bufWrite[i] = port.bqWrite->Get();
port.overlapped.hEvent = port.hEventWrite;
port.numByteWrite = 0;
if((::WriteFile(
port.hComm,
port.bufWrite,
port.sizeWrite,
&port.numByteWrite,
&port.overlapped )
) == FALSE )
{
if(::GetLastError() == ERROR_IO_PENDING)
;
else
{
::ClearCommError( port.hComm, &port.errorCodes, &ComStat );
port.displayErrorCodes( port.errorCodes );
port.errorCodes = 0L;
continue;
}
}
while(!::GetOverlappedResult( port.hComm, &port.overlapped, &port.numByteWrite, TRUE ))
{
if(GetLastError() == ERROR_IO_INCOMPLETE)
continue;
else
break;
}
::ResetEvent( port.hEventWrite );
port.numByteWrite = port.sizeWrite = 0L;
}
}
}
DWORD __stdcall ComPort::getData( LPDWORD lpdwParam )
{
ComPort& port = (ComPort&)(*lpdwParam);
COMSTAT comStat ;
while(1)
{
DWORD dwComEvent = 0; // Ожидаем приема от порта
::WaitCommEvent( port.hComm, &dwComEvent, NULL );
if ((dwComEvent & EV_RXCHAR) == EV_RXCHAR) // Дождались чтения
{
port.errorCodes = 0L; // Сколько байт в буффере
::ClearCommError ( port.hComm, &port.errorCodes, &comStat );
port.numByteRead = 0 ;
port.errorCodes = 0L;
port.overlapped.hEvent = port.hEventRead; // Чтение
if(::ReadFile( port.hComm,
port.bufRead,
comStat.cbInQue,
&port.numByteRead,
&port.overlapped
)== FALSE )
{
if(::GetLastError() == ERROR_IO_PENDING)
;
else
{
::ClearCommError( port.hComm, &port.errorCodes, &comStat ) ;
port.displayErrorCodes( port.errorCodes );
port.errorCodes = 0L;
continue;
}
}
while(!::GetOverlappedResult( port.hComm, &port.overlapped, &port.numByteRead, TRUE ))
{
if(GetLastError() == ERROR_IO_INCOMPLETE)
continue;
else
break;
}
::ResetEvent( port.hEventRead );
for( register i = 0; i < port.numByteRead; i++ )
port.bqRead->Put( port.bufRead[i] );
port.numByteRead = 0;
}
}
}
void ComPort::receiveData()
{
if( bqRead->GetItemsInContainer() >= usSizeBitNetProtokol )
{
::SuspendThread( hReadThread);
transport->moveDataFrom( *bqRead );
::ResumeThread( hReadThread);
}
}
void ComPort::displayErrorCodes( DWORD erc )
{
char * errorString=0;
if( erc & CE_BREAK )
errorString = "Аппаратура порта обнаружила сигнал Break.\n";
if( erc & CE_FRAME )
errorString = "Аппаратура порта обнаружила ошибку передачи.\n";
if( erc & CE_IOE )
errorString = "Ошибка ввода-вывода.\n";
if( erc & CE_MODE )
errorString = "Запрошенный режим не поддерживается, или неверен hCommDev параметр.\n";
if( erc & CE_OVERRUN )
errorString = "Буффер переполнен. Следующий байт потерян.\n";
if( erc & CE_RXOVER )
errorString = "Входной буффер переполне. Недостаточен размер буффера или символ принят конца файла (EOF).\n";
if( erc & CE_RXPARITY )
errorString = "Аппаратура обнаружила ошибку четности.\n";
if( erc & CE_TXFULL )
errorString = "Выходной буффер переполнен.\n";
if( erc & CE_DNS )
errorString = "Параллельное устройство не выбрано.\n";
if( erc & CE_PTO )
errorString = "Тime-out параллельного устройства.\n";
if( erc & CE_OOP )
errorString = "Параллельное усртройство сигнализирует о конце бумаги.\n";
::MessageBox(NULL, errorString, namePort, MB_ICONSTOP | MB_OK );
}
[свернуть]
Социальные закладки