· Начало · Статистика · WASM.RU · Noir.Ru ·

 WASM Phorum (Оффлайн - 24.11.2003) —› WASM.ZEN —› глуб0кий offtop

Посл.отвђт Сообщенiе


Дата: Сен 5, 2003 18:40:12

Простите, что как всегда не в тему, но просто это, можно сказать, срочно надо ... Несколько дней уже парюсь, глаза на лоб лезут, а строку правильно принять не могу - то со смещением получается, то вообще какие-то иероглифы принимаю. заколебался ...
ковыряю тут сом-порт и в упор(!) не могу разобраться с тем, как синхронизировать прием данныx если передатчик работает в непрерывном режиме ??? А именно: имеется нуль-модемный кабель, по которому одна прога без перерыва передает данные (строку длиной 22 символа), а вторая прога, соответственно, принимает последнюю. Если сначала включить приемник, а потом передатчик, то синхронизация происходит сама собой и строка выводится на экран как полагается ... но если сначала включить передатчик, то строка принимается с каким-то непонятным смещением: т.е. так 'FFFFFFFF0KG'#10#13'AB,CD,EF,' или так 'FFFF0KG'#10#13'AB,CD,EF,FFFF' или глюканы какие-то, но не так как полагается -
'AB,CD,EF,FFFFFFFF0KG'#10#13' !!!
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

прога, которая передает данные (отдельный поток):

var 
  str: string[22];

 ..............

  str := 'AB,CD,EF,FFFFFFFF0KG'#10#13;

  Port := CreateFile(PChar('COM1'), GENERIC_WRITE, 0, nil,
    OPEN_EXISTING, 0, 0);

  GetCommState(Port, DCB);
    DCB.BaudRate := 9600;
    DCB.ByteSize := 8;
    DCB.Parity := NOPARITY;
    DCB.StopBits := ONESTOPBIT;
  SetCommState(Port, DCB);

  repeat
    WriteFile(Port, str[1], 22, count, nil);
  until Terminated;

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

прога, которая принимает данные (тоже отдельный поток)

var
  str: array[1..22] of byte;

 ................

  Port := CreateFile(PChar('COM2'), GENERIC_READ, 0, nil,
    OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

  GetCommState(Port, DCB);
    DCB.BaudRate := 9600;
    DCB.ByteSize := 8;
    DCB.Parity := NOPARITY;
    DCB.StopBits := ONESTOPBIT;
    DCB.EvtChar := #13; //<- последний символ-событие в посылке за который хочу зацепиться
  SetCommState(Port, DCB);


  GetCommTimeOuts(Port, TM);
    TM.ReadIntervalTimeout := 50;
    TM.ReadTotalTimeoutMultiplier := 2;
    TM.ReadTotalTimeoutConstant := 100;
  SetCommTimeOuts(Port, TM);

  FillChar(ov, sizeof(ov), 0);
  ov.hEvent := CreateEvent(nil, true, false, nil);

  mask := EV_RXFLAG; 
  SetCommMask(Port, mask); //<- ставлю соответствующую маску порта (по символу-событию)

  mask := 0;

  if not WaitCommEvent(Port, mask, @ov) then 

  // если надо ожидать события
    if GetLastError = ERROR_IO_PENDING then
      case WaitForSingleObject(ov.hEvent, 1000) of
        WAIT_OBJECT_0: begin
          GetOverlappedResult(Port, ov, count, false);
          if mask = EV_RXFLAG then begin
           ResetEvent(ov.hEvent); //<- если символ словили переопределяем событие
           PurgeComm(Port, PURGE_RXABORT + PURGE_RXCLEAR); //<- очищаем приемный буфер дабы читать след. строку
           ClearCommError(Port, mask, nil);
            repeat
              count := 0;
              ReadFile(Port, str[1], 22, count, @ov); //<- читаем как обычно
              if GetLastError = ERROR_IO_PENDING then
                WaitForSingleObject(ov.hEvent, INFINITE); //<- здесь мне кажется можно и так
              Synchronize(ShowBuffer);
            until Terminated;
          end;

        WAIT_TIMEOUT: begin
          mask := $FFFFFFFF;
          Synchronize(ShowBuffer);
        end;
      end
  else begin

 // если ожидать события не надо
    if mask = EV_RXFLAG then begin
    ResetEvent(ov.hEvent); //<- переопределяем события для чтения
    PurgeComm(Port, PURGE_RXABORT + PURGE_RXCLEAR);
    ClearCommError(Port, mask, nil);
    repeat
      count := 0;
         ReadFile(Port, str[1], 22, count, @ov);
         if GetLastError = ERROR_IO_PENDING then
           WaitForSingleObject(ov.hEvent, INFINITE);
         Synchronize(ShowBuffer);
    until Terminated;
    end;
  end;
  until Terminated;


  CloseHandle(ov.hEvent);
  CloseHandle(Port);
end;


по идее если произошло событие по порту, то значит в буфер записан последний символ посылки - #13, соответственно если я очищу буфер, то следующим чтением обзательно прочитаю нормальную строку, однако(!!!) происходит так как происходит - строка получается со смещением и все тут ... при чем события WAIT_OBJECT_0 никогда не происходит, срабатывает WAIT_TIMEOUT, как будто последнего символа нет !!! Кто-нить сталкивался с такой замарочкой ?


Дата: Сен 6, 2003 14:26:22

Тебе просто надо НЕ воспринимать входящие данные пока не придет 13,10 (или 10,13).
Короче, ты сначала должен отловить момент, когда передатчик закончил передачу строки, а только потом воспринимать данные от передатчика как последовательность строк и обрабатывать их.


Дата: Сен 6, 2003 22:02:55

Так в том-то и прикол, что это символ не отлавливается !!! Например:
repeat
  ReadFile(Port, One, 1, count, nil);
  if One = 13 then begin
//читаю желаемую последовательность символов 
  end;
until Terminated;

замарочка, символ отлавливается либо случайно(!), после нескольких минут ожидания, либо если сначала включить приемник, а потом передатчик !!! Причем аналогичная прога написанная под DOS работает 100-процентно правильно, проверял. Там аналогично, сначала ожидаю 13-й символ, а потом считываю всю строку:
repeat
  repeat 
   b := port[$2FD];
  until (b and 1) > 0 //<- проверяю состояние линии
   b := port[$2F8]; //<- читаю принятый символ
until b = 13
for i := 1 to 22 do begin
  repeat 
    b := port[$2FD];
  until (b and 1) > 0 
  byte(str[i]) := port[$2F8]; //<- считываю строку
end;


Дата: Сен 6, 2003 22:10:08

как я только не пытался отловить этот символ - и с ожиданиями и без них и х## знает как ! А даже если он и отлавливался, то прием все равно происходил со смещением, если сначала был включен передатчик...


я просто фигею !!! ;(((... держите меня а то шАс выматерюсь от души...


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.081