RS232 w DELPHI mi spowalnia 115200bit

0

Mam taki problem a mianowicie mam urządzenie działające, podłączone do kompa i chcę je programować po RS'ie przez Delphi.

pętla tego urządzenia jest następująca - ideowo

Petla do testow

var
  Dana : Byte;
repeat
  ReadByte (Dana);
  PrintByte (Dana); 
until NIESKONCZONA

Docelowa petla programu

var
  Dana : Byte;
repeat
  ReadByte (Dana);
  //funkcja jakaś tam.... która za każdym bajtem zajmuje inna wartość
  PrintByte (Dana); 
until NIESKONCZONA

Mój problem polega na tym że chcę wysłać jeden bajt i go zaraz odebrać jeśli odbiorę ten sam bajt to wysyłam kolejny.
Robiłem już wszystkie mi znane metody:
WriteFile
ReadFile
Każdą z tych metod robiłem w oddzielnym wątku i tak i tak występuje opóźnienie ok 100ms pomiędzy wysłaniem kolejnego bajtu a ściągnąłem sobie aplikacje która testuje port COM i śmiga jak przecinak wysyłając 1000bajtów przez ok. 67ms.

0

Pokaz funkcje ReadByte/PrintByte i jak ustawiasz parametry portu COM (parametr podawany do funkcji SetCommState).

0

ReadByte i WriteByte to teoria mikrokontrolera na żywca to jest tak:
Jest to Bascom i ATmega128

dim Znak as Byte
do
  if Ischarwaiting() = 1 then
    Znak = Inkey()
    Printbin Znak
  end if
loop
end
  lpFileName := 'COM1';

  hCommDev := CreateFile(lpFileName, GENERIC_READ or
                         GENERIC_WRITE,0, NIL,
                         OPEN_EXISTING, 0, 0);

  if (hCommDev <> INVALID_HANDLE_VALUE) then
    begin
      SetupComm(hCommDev, 1, 1);
      dcb.DCBlength := sizeof(dcb);
      GetCommState(hCommDev, dcb);
      dcb.BaudRate := CBR_115200;
      dcb.Parity := NOPARITY;
      dcb.StopBits := ONESTOPBIT;
      dcb.ByteSize := 8;
      SetCommState(hCommDev, dcb);
      GetCommMask(hCommDev, fdwEvtMask);
      SetCommMask(hCommDev, EV_TXEMPTY);

          end
      else
         case hCommDev of
           IE_BADID: MessageDlg(s1 + lpFileName,
                                mtError, [mbOk], 0);
         end;
0

Parametry portu masz ustawione w prawidlowy sposob, zatem wina jest gdzies zapisie/odczycie. Troche zle Cie zrozumialem, ze ReadByte/PrintByte sa w programie Delphi, a nie programie mikrokontrolera. Pokaz wykorzystnanie ReadFile/WriteFile a takze powiedz, jak ustawiony jest priorytet watku, ktory obsluguje komunikacje i przy jakim obciazeniu systemu badasz. Moze sie okazac, ze po prostu twoj program nie dostaje czasu CPU do wykonania operacji miedzy odczytem a zapisem.

Wyslanie wsadowe przez port COM jest o wiele szybsze niz wysylanie bajt po bajcie, dopiero, gdy odczytasz prawidlowo. W pierwszym przypadku sterownik urzadzenia lub kontroler na slepo wysylaja dane przez port, gdy tylko linia transmisyjna nie jest zajeta. W drugim (Twoim przypadku) wysylasz, czekasz (linia wysylajaca jest wolna), odbierasz i porownujesz (linia wysylajaca jest wolna), wysylasz kolejny bajt. Pamietaj, ze PC nie jest urzadzeniem czasu rzeczywistego i im wiecej operacji mozesz zrobic poza procesem twojej aplikacji (a na poziomie sterownika/kontrolera czy po drugiej stronie linii transmisyjnej), tym lepiej.

0

Podaje kod:

0
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    RichEdit1: TRichEdit;
    RichEdit2: TRichEdit;
    Button2: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
const
// -- wartości flag sterujących portu szeregowego --
  dcb_fBinary = $0001;
  dcb_fParity = $0002;
  dcb_fOutxCtsFlow = $0004;
  dcb_fOutxDsrFlow = $0008;

  // -- fDtrControl --
  DTR_CONTROL_ENABLE = $0010;
  DTR_CONTROL_HANDSHAKE = $0020;

  dcb_fDsrSensitivity = $0040;
  dcb_fTXContinueOnXoff = $0080;
  dcb_fOutX = $0100;
  dcb_fInX  = $0200;
  dcb_fErrorChar = $0400;
  dcb_fNull = $0800;

  // -- fRtsControl --
  RTS_CONTROL_ENABLE = $1000;
  RTS_CONTROL_HANDSHAKE = $2000;
  RTS_CONTROL_TOGGLE = $3000;

  dcb_fAbortOnError = $4000;

var
  Buffer_O : Char; // bufor wyjściowy
  Buffer_I : Char;  // bufor wejściowy
  Number_Bytes_Read : DWORD;
  hCommDev : THANDLE;
  lpFileName : PChar;
  fdwEvtMask : DWORD;
  Stat : TCOMSTAT;
  Errors : DWORD;
  dcb    : TDCB;

  KoniecRS : Boolean;
  Odebrano : Boolean;
  hThread_RF   : THANDLE;  // pseudoidentyfikator wątku
  ThreadID_RF  : Cardinal; // zmienna identyfikująca wątek
  hThread_SF   : THANDLE;  // pseudoidentyfikator wątku
  ThreadID_SF  : Cardinal; // zmienna identyfikująca wątek
  F : File of Byte;
  Dana : Byte;
  TypDana : Byte;          //0-naglowek, 1-dane mmc, 2-koniec
  FilePos : Longint;
  DoWyslania : LongInt;
  WielkoscPliku : LongInt;
  BytesRead, BytesWritten: Integer;
  NumberOfBytesWritten : DWORD;
  Buf: array[1..32] of Char;
  DoZapisu : Integer = 0;
  LiczZapis: Integer = 0;
  BufforPusty : Boolean = TRUE;

  Wys : Integer;
  Ode : Integer;

resourcestring
   s1 = 'Niewłaściwa nazwa lub jest aktywny port ';

implementation

{$R *.dfm}

function RS_SendFile(P: Pointer): Integer;
begin
  while KoniecRS do
    begin
      if Odebrano then
        begin
         Odebrano:=FALSE;

         Buffer_O:=#10;
         WriteFile(hCommDev, Buffer_O, SizeOf(Buffer_O),
             NumberOfBytesWritten, NIL);
         WaitCommEvent(hCommDev, fdwEvtMask, NIL);
         //TransmitCommChar (hCommDev, Char(10)); //to też testowałem

        end;
    end;
end;

function RS_ReciveFile(P: Pointer): Integer;
begin
  while KoniecRS do
    begin
      ClearCommError(hCommDev, Errors, @Stat);
      if (Stat.cbInQue > 0) then
        begin
          ReadFile(hCommDev, Buffer_I, 1,
                   Number_Bytes_Read, NIL);
          if Number_Bytes_Read > 0 then
            begin

              Form1.RichEdit2.Text:=Form1.RichEdit2.Text+' '+IntToStr(Byte(Buffer_I));
              Inc (Ode);
              Form1.Label4.Caption:=IntToStr(Ode);

              Odebrano:=TRUE;
            end;
        end;
    end;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  KoniecRS:=TRUE;
  Odebrano:=TRUE;
  Wys:=0;
  Ode:=0;
  FilePos:=0;
  AssignFile (F, 'C:\TEMP.TXT');
  Reset (F);
  WielkoscPliku:=FileSize(F)-1;
  DoWyslania:=8+WielkoscPliku+1;
  lpFileName := 'COM1';

  hCommDev := CreateFile(lpFileName, GENERIC_READ or
                         GENERIC_WRITE,0, NIL,
                         OPEN_EXISTING, 0, 0);

  if (hCommDev <> INVALID_HANDLE_VALUE) then
    begin
      SetupComm(hCommDev, 1, 1);
      dcb.DCBlength := sizeof(dcb);
      GetCommState(hCommDev, dcb);
      dcb.BaudRate := CBR_115200;
      dcb.Parity := NOPARITY;
      dcb.StopBits := ONESTOPBIT;
      dcb.ByteSize := 8;
      SetCommState(hCommDev, dcb);
      GetCommMask(hCommDev, fdwEvtMask);
      SetCommMask(hCommDev, EV_TXEMPTY);

      hThread_RF := BeginThread (NIL, 0, @RS_ReciveFile,
                                 NIL, 0, ThreadID_RF);
      hThread_SF := BeginThread (NIL, 0, @RS_SendFile,
                                 NIL, 0, ThreadID_SF)
      



          end
      else
         case hCommDev of
           IE_BADID: MessageDlg(s1 + lpFileName,
                                mtError, [mbOk], 0);
         end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  KoniecRS:=FALSE;
  SuspendThread(ThreadID_SF);
  SuspendThread(ThreadID_RF);
  CloseHandle(hCommDev);
  CloseFile (F);
end;

end.
0

próbowałeś TComPort??

0

,...

0

Dzięki za podpowiedz c TComPort jest SUPER!

Mam takie pytanie widze że Write działa szybciej niż WriteStr dlatego chcę załadować do Write zmienne typy bajt np.:

for i :=1 to 125 do
  begin
    ComPort1.Write (i, 1);
  end;
jak zamienić tan kod na poprawny?
0

Po co dublujesz pytania - Ord(I) - napisałem już.

1 użytkowników online, w tym zalogowanych: 0, gości: 1