Witajcie.
Proszę o drobną pomoc(podpowiedź), bo sam już sobie nie radzę.
Temat jest taki: Drukarka PosnetThermal i odczyt danych z Delphi przez rs232.
Z większością problemów sobie poradziłem, natomiast mam problem z odczytem danych.
Jednym buttonem naciskam "wyślij" - jest OK.
Drugim buttonem naciskam "odbierz" - też jest OK
ALE jeżeli w jednej procedurze dam wyślij i odbierz to bufor jest pusty i muszę dawać sleep(100) że by odczytać dane.
oto mój kod.
Tego chyba nie trzeba opisywać.
procedure TForm1.Button3Click(Sender: TObject);
var
S : string;
begin
SetLength(S,2048);
PosNet.Port_Open(PortNr,PortSpeed);
PosNet.SendSequence(Trim(Edit1.Text),False);
PosNet.ReadSequence(S,2048);
memo1.Lines.Add(S);
end;
Otwieranie portu.
function TComPortClass.Open(iPort:byte; aBaudRate: DWORD): Integer;
var
aPortName : PChar;
begin
if not (iPort in [1..99]) then begin
Result := SERROR;
exit;
end;
aPortName := pchar('COM'+IntToStr(iPort));
{
Transmisja synchroniczna (czyli z czekaniem na zakończenie operacji zapisu czy też odczytu)
}
hCom := CreateFile( aPortName, GENERIC_READ or GENERIC_WRITE, 0, Nil, OPEN_EXISTING, 0, 0);
if( hCom = INVALID_HANDLE_VALUE ) then begin
Result := ERR_CREATE_FILE_COM;
exit;
end;
GetCommState(hCom,aDCB);
aDcb.DCBlength := sizeof( aDCB );
aDcb.BaudRate := aBaudRate; //* Baud Rate */
// Dcb.fBinary := TRUE;
// Dcb.fParity := FALSE;
// Dcb.fOutxCtsFlow := FALSE;
// Dcb.fOutxDsrFlow := FALSE;
// Dcb.fDtrControl := DTR_CONTROL_DISABLE;
// Dcb.fDsrSensitivity := FALSE;
// Dcb.fTXContinueOnXoff := FALSE;
// Dcb.fOutX := TRUE; //* Xon/Xoff używane tylko podczas nadawania */
// Dcb.fInX := FALSE;
// Dcb.fErrorChar := FALSE;
// Dcb.fNull := FALSE;
// Dcb.fRtsControl := RTS_CONTROL_DISABLE;
// Dcb.fAbortOnError := FALSE; //* w przypadku wystąpienia błędu kolejne dostępy nie będą blokowane */
aDcb.XonLim := 1900;
aDcb.XoffLim := 1024;
aDcb.XonChar := chr(17);
aDcb.XoffChar := chr(19);
aDcb.ByteSize := 8; //* 8 bitów */
aDcb.Parity := NOPARITY; //* bez bitu kontroli parzystości */
aDcb.StopBits := ONESTOPBIT; //* jeden bit stopu */
aDcb.Flags := dcb_fBinary or dcb_fParity or dcb_fOutX; //* flagi */
if not ( SetCommState(hCom, aDcb) ) then begin
CleanUp;
Result := ERR_COMM_SETTINGS;
exit;
end;
{
Timeout na:
- całość ( RD_INTERV_TOUT * (1 + nr_of_bytes) )
- interwał międzybajtowy
}
GetCommTimeouts(hCom,aTimeouts);
aTimeouts.ReadIntervalTimeout := 1;
aTimeouts.ReadTotalTimeoutConstant := 300;
aTimeouts.ReadTotalTimeoutMultiplier := 0;
aTimeouts.WriteTotalTimeoutConstant := 300;
aTimeouts.WriteTotalTimeoutMultiplier := 0;
if not ( SetCommTimeouts( hCom, aTimeouts ) ) then begin
CleanUp;
Result := ERR_COMM_SETTINGS;
exit;
end;
// Żadne zdarzenia związane z portem nie będą generowane !!!
if not ( SetCommMask( hCom, EV_RXCHAR ) ) then begin
CleanUp;
Result := ERR_COMM_SETTINGS;
exit;
end;
//* Tak na dobry początek - czyścimy co się da (kolejki...) */
PurgeComm( hCom, PURGE_TXABORT OR PURGE_RXABORT OR PURGE_RXCLEAR OR PURGE_TXCLEAR );
//_ASSERTE( RetB ); // nie wiem po co to jest
{/*
Ustawiamy długości kolejek: wejściowej i wyjściowej.
Wejściowa - postaramy się ustawić jakąś sensowną wartość.
Wyjściowa - zero (brak kolejkowania danych wychodzących).
*/}
//aCommProp.dwProvSpec1:=COMMPROP_INITIALIZED;
if not GetCommProperties(hCom, aCommProp) then begin
CleanUp;
Result := ERR_COMM_SETTINGS;
exit;
end else begin
aCommProp.dwCurrentRxQueue := 2048;
aCommProp.dwCurrentTxQueue := 1024;
aCommProp.dwMaxRxQueue := min( PORT_RX_QUEUE_LEN, aCommProp.dwMaxRxQueue );
if not ( SetupComm(hCom, aCommProp.dwCurrentRxQueue, 0) ) then begin
CleanUp();
Result := ERR_COMM_SETTINGS;
exit;
end;
end;
Result := SOK;
end;
Zapis do portu - wysyłanie.
function TComPortClass.Write(Buffer:string;Len:DWORD): Integer;
var
RetB : Boolean;
BytesWritten : DWORD;
begin
if ( hCom = INVALID_HANDLE_VALUE ) then begin
Result := SERROR;
exit;
end;
RetB := WriteFile( hCom, pchar(Buffer)^, Len , BytesWritten, Nil ); //* wysyłamy */
if( (not RetB) or (BytesWritten <> Len) ) then begin
Result := ERR_WRITE_FILE_COM;
exit;
end;
Result := SOK;
end;
Odczyt z portu <= Tu mam problem
function TComPortClass.Read(var Buffer:string; var iReaded:DWORD; const Len:integer=PORT_OUTPUT_BUFFER_LEN):Integer;
var
Stat : TComStat;
Errors : DWORD;
toRead : DWORD;
B : byte;
S : string;
begin
if (hCom = INVALID_HANDLE_VALUE) then begin
Result := SERROR;
exit;
end;
ClearCommError(hCom, Errors, @Stat);
S := IntToStr(Stat.cbInQue)+'|'+IntToStr(Stat.cbOutQue); /// <= TUTAJ cbInQue ma wartość 0
if WaitForAnyByte(SHORT_RESPONSE_TIME,B)=SOK then begin
// sleep(SHORT_RESPONSE_TIME);
Sleep(10);
ClearCommError(hCom, Errors, @Stat); /// <= TUTAJ przy sleep(10) cbInQue ma wartość 15
/// <= przy sleep(100) odczytuje cały komunikat 35zanków
S := S+#13+IntToStr(Stat.cbInQue)+'|'+IntToStr(Stat.cbOutQue);
Application.MessageBox(pchar(s),'Test kolejki',0);
SetLength(Buffer, Stat.cbInQue);
toRead := min(Stat.cbInQue,Len);
if not( ReadFile(hCom, pchar(Buffer)^, Stat.cbInQue, iReaded, NiL) ) then begin //* odczytujemy */
Result := ERR_READ_FILE_COM;
exit;
end;
Buffer := chr(B)+Buffer;
Result := SOK;
end else
Result := ERR_RESPONSE_TOUT;
end;
Co robię źle ?
złe ustawienia timeoutów ? / flag ? czy może jest jakiś znacznik że dane w buforze są gotowe do odczytu ??