Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Для новичков > AsyncFree104 отлов байта


Автор: Darkblue 22.1.2012, 16:38
Пишу на делфи 7, использую драйвер AsyncFree104, дк вот мне нужно передавать на контроллер информацию побайтно ну и соответственно он мне должен отвечать (в данный момент просто отправить полученные байты обратно),  как реализовать вылавливание байтов (результат нужен в HEX), посылку делаю следующим образом: задаю в глобальных переменных Buff: byte = ($12);z:integer;  и соответственно на контроллер приходит число  12 hex, параллельно в поле StaticText2.Caption высвечивается число 18 dec, подключал осцил, на нём видно что число приходит с выхода TX
Код

procedure TForm1.BitBtn6Click(Sender: TObject);
begin
AfComPort1.PurgeTX; // очистили выходной буффер
AfComPort1.PurgeRX;
AfComPort1.WriteData(Buff, sizeof(Buff));
z:=Buff;
StaticText2.Caption:=IntToStr(z);
end;


Приём насколько я понял (в интернете вообще почемуто мало инфы о этом драйвере)  можно реализовать так: 
 d1:=AfComPort1.ReadString - не подходит  потому что он переводит данные в  кодировку ASCII а мне нужен HEX а не строка
либо через 
AfComPort1.ReadData
которая должна вызываться  процедурой 
procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
дк вот вопрос:как мне с помощью команды AfComPort1.ReadData отлавливать свои байты? сложность заключается в том, что нет такого компонента AfComPort1DataRecived для помещения его на рабочее поле, а если делать как в коде ниже (причём Buff: byte = ($12); ReadBuffer: array of byte; z,count:integer; задано в глобальных переменных)
Код

procedure TForm1.BitBtn6Click(Sender: TObject);
begin
Poz:=0;
AfComPort1.PurgeTX; // очистили выходной буффер
AfComPort1.PurgeRX;
AfComPort1.WriteData(Buff, sizeof(Buff));
z:=Buff;
StaticText2.Caption:=IntToStr(z);
AfComPort1.ReadData(ReadBuffer[Poz], count);
z:=ReadBuffer[count];
StaticText7.Caption:=IntToStr(z);
end;

то вылазит ошибка Acess violation at address 0049EAA3 in module Project1.exe. Read of address 00000000.

Уважаемые помогите пожалуйста

Автор: northener 22.1.2012, 18:22
Цитата(Darkblue @  22.1.2012,  16:38 Найти цитируемый пост)
procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);

Это не просто процедура. Это обработчик события OnDataRecieve данного компонента, которое сообщает что принято Count байт. В этом обработчике и нужно вызывать процедуру ReadData.

Автор: Darkblue 22.1.2012, 18:56
Извините первый раз юзаю обработчики, тоесть как я понял в ObjectInspector->AFComPort1->Events-> OnDataRecived прописываем ReadData, жмякаем Enter появляется процедура procedure TForm1.ReadData(Sender: TObject; Count: Integer); в которой мы и начинаем считывать наш байт AfComPort1.ReadData(ReadBuffer[Poz], count); ?

Автор: northener 22.1.2012, 19:05
в ObjectInspector->AFComPort1->Events-> OnDataRecived нажимаем Enter или двойной щелчок мышки. Появляется в коде шаблон обработчика TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer); В нем пишем AfComPort1.ReadData(ReadBuffer[Poz], count); и все прочее что нужно сделать с полученными данными.

Автор: Darkblue 22.1.2012, 19:26
Сделал как вы сказали реакций 00,теперь он даже ошибку не выдаёт что мол буфер пуст читать из него нельзя (Acess violation at address 0049EAA3 in module Project1.exe. Read of address 00000000.)
Код

procedure TForm1.ReadData(Sender: TObject; Count: Integer);
begin
AfComPort1.ReadData(ReadBuffer[Poz], count);
Inc(Poz, count);
z:=ReadBuffer[Poz];
StaticText7.Caption:=IntToStr(z);
end;



Автор: northener 22.1.2012, 19:34
Цитата(Darkblue @  22.1.2012,  19:26 Найти цитируемый пост)
Read of address 00000000

Что есть ReadBuffer?
Цитата(Darkblue @  22.1.2012,  19:26 Найти цитируемый пост)
Inc(Poz, count);
z:=ReadBuffer[Poz];

Эти две строки нужно поменять местами.

Автор: Darkblue 22.1.2012, 19:37
ReadBuffer: array of byte; занесён в глобальные переменные

Автор: northener 22.1.2012, 19:42
Цитата(Darkblue @  22.1.2012,  19:37 Найти цитируемый пост)
ReadBuffer: array of byte; занесён в глобальные переменные 

А SetLength(ReadBuffer,...) в коде есть?

Автор: Darkblue 22.1.2012, 20:31
Эм нет,в этом ошибка получается,тоесть нужно размер буфера задать ,так? а куда его засунуть до передачи непосредственно? 
Код

procedure TForm1.BitBtn6Click(Sender: TObject);
begin
AfComPort1.PurgeTX; // очистили выходной буффер
AfComPort1.PurgeRX;
AfComPort1.WriteData(Buff, sizeof(Buff));
SetLength(ReadBuffer, Length(ReadBuffer));
z:=Buff;
end;

Автор: northener 22.1.2012, 20:49
Цитата(Darkblue @  22.1.2012,  20:31 Найти цитируемый пост)
 а куда его засунуть до передачи непосредственно?

Ну например в FormCreate. Но только не так 
Цитата(Darkblue @  22.1.2012,  20:31 Найти цитируемый пост)
SetLength(ReadBuffer, Length(ReadBuffer));

Пока размер не задан Length(ReadBuffer) вернет 0. 

Автор: Darkblue 22.1.2012, 22:57
Всё разобрался,заработало,огромное вам northene спасибо

Автор: northener 23.1.2012, 00:13
Цитата(Darkblue @  22.1.2012,  22:57 Найти цитируемый пост)
огромное вам northener спасибо 

Не за что. Работа с внешним устройством через СОМ-порт - моя родная тематика. А все компоненты для такой работы сделаны практически по одной "кальке" smile

Автор: Darkblue 24.1.2012, 20:51
Подскажите пожалуйста ещё. Я отлавливаю байт с порта затем я должен построить 6 графиков в TChart один сдвинут относительно другого, байт=8бит но старшие биты я не использую,код такой
Код

procedure TForm1.Timer2Timer(Sender: TObject);
begin
E := z and 1;                          //Линия1
Series1.AddXY(i2,E+1,'',clRed);   //выделил только первый бит из кадра
E := z and 2;                         //Линия2
E:= E shr 1;                         //выделил только второй бит из кадра
Series2.AddXY(i2,E+3,'',clGreen);
E := z and 4;                         //Линия3
E:= E shr 2;                         //выделил только 3 бит из кадра
Series3.AddXY(i2,E+5,'',clBlue);
E := z and 8;                         //Линия4
E:= E shr 3;                         //выделил только 4 бит из кадра
Series4.AddXY(i2,E+7,'',clYellow);
E := z and 16;                         //Линия5
E:= E shr 4;                         //выделил только 5 бит из кадра
Series5.AddXY(i2,E+9,'',clPurple);
E := z and 32;                         //Линия6
E:= E shr 5;                         //выделил только 6 бит из кадра
Series6.AddXY(i2,E+11,'',clWhite);
inc(i2);
end;

 тоесть построение графика вертится в таймере,минимальное значение срабатывания таймера 1 милисекунда как я понял,как мне сделать правильно ось времени,ведь данные могут приходить намного чаще (56000б/с скорость работы порта выставлена) а минимальное деление оси времени 1 милисекунда?Данные беру с порта
Код

procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
begin
AfComPort1.ReadData(ReadBuffer[Poz], count);       // забрали с порта данные
z:=ReadBuffer[Poz];
AfComPort1.PurgeTX; // очистили выходной буффер
AfComPort1.PurgeRX; // очистили входной буффер!
Poz:=0;               //начальные позиции буфера приёма
count:=0;
end;


Автор: northener 24.1.2012, 21:01
Цитата(Darkblue @  24.1.2012,  20:51 Найти цитируемый пост)
минимальное значение срабатывания таймера 1 милисекунда

Увы больше. Как минимумум 10мс с хвостиком.

Автор: Darkblue 24.1.2012, 21:06
печально это,но как тогда встроить ось времении правильно в соответствии с временем прихода сигнала? (делаю логический анализатор)

Автор: northener 24.1.2012, 21:23
Почитай про 
QueryPerformanceCounter, QueryPerformanceFrequency
Это поможет максимально точно измерить время получения очередного сигнала.

Автор: Darkblue 24.1.2012, 22:31
Спасибо 

Автор: northener 25.1.2012, 01:14
Цитата(Darkblue @  24.1.2012,  22:31 Найти цитируемый пост)
Спасибо

Вот тут уж вообще почти не за что.
Вчера смог только указать более точные способы измерения интервалов времени, чем стандартный таймер.
Но.
Цитата(Darkblue @  24.1.2012,  21:06 Найти цитируемый пост)
делаю логический анализатор

Логический анализатор чего? И для чего?
Поскольку Windows не является ОС реального времени "время получения ответа по СОМ-порту от внешнего устройства вашей программой от времени ответа на ваш запрос к устройству" может различаться от раза к разу далеко не на миллисекуды. (Скорость передачи по СОМ-порту тут почти не при чём). И даже не на десятки/сотни миллисекунд. А на секунды!
Вы бы свою задачу представили бы полностью. Можно мне в личку или на почту, если что-то смущает.

Автор: Strannix 6.2.2012, 13:24
Может мой вопрос немного не по теме, использую тот же пакет компанентов для работы с портом, на пк реализована раздача GPS данных через виртуальные порты GPSGate, порт открывается данные в терминале идут, но когда пытаешься считать данные именно с порта в строку например так s:=AfComPort1.ReadString; ничего не происходит тоесть данных в переменной нет.Из потрта необходимо считать определенные строки с данными а дальше дело техники, прошу помощи. Вот какие данные отображаются в окне терминала 

$GPRMC,094812,A,5027.09199,N,04433.97236,E,9.91,328.3,060212,0.0,E*4D
$GPGLL,5027.09199,N,04433.97236,E,094812,A*2D
$GPGGA,094812,5027.09199,N,04433.97236,E,1,5,0.0,0.0,M,0.0,M,,*40
$GPVTG,328.3,T,328.3,M,9.91,N,18.35,K*70
$GPRMC,094813,A,5027.09434,N,04433.97009,E,9.91,328.3,060212,0.0,E*40


Автор: northener 6.2.2012, 13:31
Цитата(Strannix @  6.2.2012,  13:24 Найти цитируемый пост)
когда пытаешься считать данные именно с порта в строку например так s:=AfComPort1.ReadString

Процедура ReadString ожидает получения признака "конец строки". Как правило это LFCR или что-то одно из них. Если этих символов в принимаемой информации нет, данная процедура ничего не вернет.

Автор: Strannix 6.2.2012, 13:35
каким же образом тогда образом можно считать данные?получиться ли считать буфер как в предыдущем примере программы?я пробовал с буфером эксперементировать точно так как в примере результа также нет натолкните пожалуста на примлемое решение данного вопроса

Добавлено через 1 минуту и 20 секунд
есть ще вариант считывания необходимой информации непосредсвенно из лог файла но это не рационально и сопряжено с дополнительными проблемами

Автор: northener 6.2.2012, 13:39
Цитата(Strannix @  6.2.2012,  13:35 Найти цитируемый пост)
я пробовал с буфером эксперементировать точно так как в примере

Покажи свой код.

Автор: Strannix 6.2.2012, 13:41
var
  Form1: TForm1;
  Buff: byte = ($12);
  ReadBuffer: array of byte;
  z,count,poz,i:integer;
  s:string;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
i:= AfComPort1.InBufSize;
SetLength(ReadBuffer,i);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
AfComPort1.ComNumber :=strtoint(LabeledEdit1.Text);
AfComPort1.Open;
end;

procedure TForm1.AfComPort1DataRecived(Sender: TObject; Count: Integer);
begin
AfComPort1.ReadData(ReadBuffer[Poz], count);
z:=ReadBuffer[Poz];
Inc(Poz,count);
memo1.Lines.Add(inttostr(z));
poz:=0;
count:=0
end;

Автор: northener 6.2.2012, 13:53
Цитата(Strannix @  6.2.2012,  13:41 Найти цитируемый пост)
z:=ReadBuffer[Poz];
Inc(Poz,count);
memo1.Lines.Add(inttostr(z));
poz:=0;
count:=0

Зачем же так бездумно копировать чужой пример? Автор топика принимал от внешнего устройства только один байт в ответ на свою команду.
Попробуй переписать сей кусок кода так:
Код

  for i:=Poz to Poz+Count do
    Memo1.Text:=Memo1.Text+IntToStr(ReadBuffer[i])+',';
  Poz:=0;

Автор: Strannix 6.2.2012, 14:11
попробовал в мемо одни 0, и я до этого пробовал в цикле считать данные из буфера только концом цикла указывал InBufSize,

Автор: northener 6.2.2012, 14:28
Параметры СОМ-порта установлены правильно? Скорость, количество бит, четность, количество стоп-бит.
Кроме того обычно у подобных компонент СОМ-порта есть событие типа OnError. Попробуй его задействовать.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)