Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Компоненты Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.03.2014, 13:05   #1
GMX
 
Регистрация: 24.03.2014
Сообщений: 4
По умолчанию Дикий тупняк - чтение данных с com порта.

Господа, стыдно признаваться, но я туплю. Лет десять ничего не кодил, а тут пришлось. Сижу, туплю. Итак, ситуация: имеем ком порт, с которого с интервалом 30 мс приходит следующая инфа: два стартовых байта 'SS' следом 12 байт чисел (на самом деле шесть чисел типа int16_t) и заканчивается двумя байтами 'PP'.
В терминале это выгляди примерно так:
-------------------------
SS Иoэ2Шс8PPSSъю,ьс*8°PPSS wю» rрс@8јPPSSэE Њ {°сМ9TP
PSSэЎ Ј†Мрё7фPPSS† ¬ јрш8ђPPSSэШ $ Ќ°ра8hPPSSюц р =рИ8 PPSSюјюS н`сD8ЬPPSSю
EюKћарш7ьPPSSЪюm .р°8xPPSSюEэюи4р¬8ёPPSS эювЂсЂ84PPSSэ¤ыд C*с$9ШPPSSэ
ъґXр47PPSSь˜юАр*7АPPSSъщ Ѓ ќмпш7дPP
-------------------------

Мне необходимо считать эти 12 байт. Делфи совсем забыл, сижу туплю.
Стоит компонент ComPort Library.
Пытаюсь сделать что-то типа:

Код:
procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
  var
  LastString: String;
begin
  ComPort1.ReadStr(LastString, 16);
  if ((Pos('SS', LastString)=1) and (Pos('PP', LastString)=15)) then Memo1.Lines.Add(LastString);
  LastString:='';
end;
Получается какая-то фигня...
GMX вне форума Ответить с цитированием
Старый 24.03.2014, 13:40   #2
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,742
По умолчанию

Код:
uses bcports;

var com2: TBComPort;
...
 com2:= TBComPort.Create(nil);
 com2.OnRxChar:= rec2;
...



procedure Tform1.rec2(Sender: TObject; count: integer);
var buf: array[0..255] of byte;
     slovo1: word;
begin
 com2.Read(buf, count);
 //
 if (buf[0] = $53 {аски 'S'}) and
    (buf[1] = $53 {аски 'S'}) and
    (buf[14] = $50 {аски 'P'}) and
    (buf[15] = $50 {аски 'P'}) then begin
      slovo1:= (buf[3] shl 8)+ buf[2]; 
      // и т.д.
end;
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 24.03.2014, 16:19   #3
Slym
Участник клуба
 
Регистрация: 07.12.2011
Сообщений: 1,025
По умолчанию

а склеивать неполные пакеты?
восстанавливать стартовую позицию пакета в случае если программа запустилась на полпакете, или обрыв/восстановление ком шнурка?
псевдокод
Код:

uses bcports;

var com2: TBComPort;
var Data:string;
...
 com2:= TBComPort.Create(nil);
 com2.OnRxChar:= rec2;
...



procedure Tform1.rec2(Sender: TObject; count: integer);
var buf: array[0..255] of byte;
     slovo1: word;
begin
 com2.Read(buf, count);
data:=data+buf;

if length(data)>packetsize then
begin
  spos:=pos(data,'SS');
  if spos>1 then delete(data,spos-1);//обрезка полукадра
  ppos:=pos(data,'PP');
  if ppos>0 then
  begin
    packet:=copy(data,1,ppos);
    delete(data,ppos);
    processpacket(packet);
  end;
end

end;
Не стесняемся, плюсуем!

Последний раз редактировалось Slym; 24.03.2014 в 16:26.
Slym вне форума Ответить с цитированием
Старый 24.03.2014, 16:47   #4
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,742
По умолчанию

Для склейки у меня другой подход:
Код:
var tmp_val: string = '';

procedure Tform1.rec(Sender: TObject; count: integer);
var i, msgt, msgl, k, len: integer;
    str, msg, sss: string;
    slovo: word;
    CRC_MSG, CRC_SUM: int64;
    bigslovo: int64;
begin
 str:= '';
 com.ReadStr(str, count);

 // ищем склеенный пакет (55 AA 55 AA) плавающим окном
 str:= tmp_val + str;
 for i:= 1 to length(str) do begin

  // ищем начало кодограммы по FF
  if (Ord(str[i])  = $ff) and
     (Ord(str[i+1])= $ff) then begin

     slovo:= (Ord(str[i+3]) shl 8)+ Ord(str[i+2]);
     msgt:= get_data(0, 5, slovo);
     msgl:= get_data(6, 15, slovo);

     // если остаток меньше заданной длины msgl*4 байта ->
     // переносим на следующее считывание
     if i+(msgl*4)-1 > length(str) then begin
      tmp_val:= copy(str, i, length(str)-i+1);
      break;
     end else begin // иначе
      tmp_val:= '';
      msg:= copy(str, i, msgl*4);

      // -------------------------- ПРОВЕРКА CRC ------------------------------
...
...
...

        // -------------------------- ВИДЕО ------------------------------------
        // контроль по типу сообщения =2
        if (msgt = $2) then
         mvideo(msg);

        // -------------------------- ДИАГНОСТИКА ------------------------------
        // контроль по типу сообщения =4
        if (msgt = $4) then
         mdiagn(msg);

       end;
      end;
      
   end;
  end;
 end;
end;
Цитата:
или обрыв/восстановление ком шнурка?
вот прям все подавай на блюдечке Их есть у меня, через SetupAPI отслеживается наличие подключенного USB-шнурка. Наличие подключенного шнурка к физическому RS-232 можно отследить только по таймауту и отсутствию пакетов и никак иначе. Полный COM порт не есть обязательное использование в таких шнурках.
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 26.03.2014, 15:00   #5
GMX
 
Регистрация: 24.03.2014
Сообщений: 4
По умолчанию

Огромное спасибо отписавшимся! Из ваших постов собрал солянку, все ок.
Вопрос теперь следующий. Собираемые данные - со знаком, а при такой сборке типа
slovo1:= (buf[3] shl 8)+ buf[2];
Получаю беззнаковое значение. Еще раз прошу прощения за глупый вопрос, но как восстановить знак?
GMX вне форума Ответить с цитированием
Старый 26.03.2014, 15:10   #6
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,742
По умолчанию

Цитата:
Получаю беззнаковое значение. Еще раз прошу прощения за глупый вопрос, но как восстановить знак?
Цитата:
два стартовых байта 'SS' следом 12 байт чисел (на самом деле шесть чисел типа int16_t) и заканчивается двумя байтами 'PP'.
во-первых, начнем с того, что мой алгоритм предполагает передачу младшими байтами вперед в кодограмме, что у вас без понятия. Во-вторых, при сборке очевидно что 32 бита = 4 байтам (тип word) и указанные вами два символа юниксового типа тип int16_t из stdint.h размерностью 16 бит эквивалентны. Но вы не указали структуру внутри этих данных. Так о каком знаке мы тогда говорим?
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 26.03.2014, 15:13   #7
GMX
 
Регистрация: 24.03.2014
Сообщений: 4
По умолчанию

Все, разобрался. Объявил slovo как SmallInt. Всем огромное спасибо!
GMX вне форума Ответить с цитированием
Старый 26.03.2014, 15:15   #8
raxp
Старожил
 
Регистрация: 29.09.2009
Сообщений: 9,742
По умолчанию

Тип SmallInt - 16 битное целое число со знаком. Поступив таким образом, вы теряете данные из 32-битного набора. Integer надоть, имхо.

Так как распределены данные внутри? Партизанен швайне яйке подвешен?
Разработки и научно-технические публикации :: Видеоблог :: Твиттер
Radar systems engineer & Software developer of industrial automation
raxp вне форума Ответить с цитированием
Старый 26.03.2014, 15:39   #9
GMX
 
Регистрация: 24.03.2014
Сообщений: 4
По умолчанию

Мои int16_t - это 16-битное со знаком. Разбивка происходит в контроллере:
highByte=(char)(data>>8);
lowByte=(char)(data);
Передача в порядке: сначала старший байт, потом младший.
Собрал в обратном порядке:
slovo:=(highByte shl 8) + lowByte;
где slovo - SmallInt. Просто взял из справочника тип 16-бит со знаком.
GMX вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Чтение COM порта vovken1997 Общие вопросы Delphi 13 25.05.2020 16:44
Чтение com-порта на java danyamaster Фриланс 3 15.02.2013 14:09
Чтение с COM-порта через HyperTerminal rashid1988 Общие вопросы Delphi 9 20.04.2012 09:56
Чтение данных с COM порта 232 Dimitr_88 Общие вопросы C/C++ 10 03.09.2010 10:39
чтение с COM-порта в отдельном потоке не получается lexluter1988 Общие вопросы .NET 2 25.05.2010 20:40