procedure TForm2.Button2Click(Sender:TObject);
begin {запрос}
if FlagCOM=False then exit;
{если порт еще не инициализирован — выход}
AfComPortl.PurgeRX; {очищаем буфер порта на всякий случай}
xb:=$А2;
AfComPort1.WriteData(xb,1); {посылаем команду}
FlagSend:=$А2; {обозначаем посылку запроса времени}
tall:=0; {обнуляем время}
хn:=0; {счетчик принятых байтов}
Timer1.Enabled:=True; {запускаем таймер}
end;
procedure TForm1.FormCreate(Sender:TObject);
begin
{инициализация COM1 при запуске}
stcom:='COM1';
IniCOM;
end;
procedure TForm1.ComboBox1Select(Sender: TObject);
begin
stcom:=ComboBox1.Text; {устанавливаем порт COM1,2,3,4}
IniCOM;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
AfComPort1.Close; {закрытие порта}
end;
Теперь нам осталось разобраться с тем, что мы там напринимали. Это позволит сделать установленное нами значение FiagSend и таймер. В таймере переменную tall мы будем увеличивать на единицу, а в процедуре приема мы все время ее обнуляем, так что пока она равна нулю, можно полагать, что прием еще не закончился. Как только она станет больше единицы (прошло более секунды с момента последнего принятого байта или прием вообще не происходил), мы начинаем что-то делать, но только в том случае, если флаг FlagCOM установлен (True), иначе это вообще был не прием, а опрос модема. Сказанное иллюстрирует листинг 18.7.
procedure TForm1.Timer1Timer(Sender:TObject);
var i: integer;
begin {таймер}
inc tall
if FlagCOM=False then exit;
if tall>1 then
begin
Timer1.Enabled:=False; {выключаем таймер}
if xn=0 then {если счетчик = 0, то ничего не принято}
begin
Application.MessageBox('Устройство не обнаружено 1,'Error',МВ_ОК);
exit {выход из процедуры — неудача}
end else
begin {иначе обрабатываем данные}
if FlagSend=$A2 then {если был запрос времени}
begin
if xn<>6 then
begin
Application.MessageBox('Неправильный формат данных','Error',MB_OK);
exit;
end;
StaticText1.Caption:=IntToHex(ab[1],2); // часы
StaticText2.Caption:=IntToHex(ab[2],2); // минуты
StaticText3.Caption:=IntToHex(ab[3],2); // секунды
StaticText4.Caption:=IntToHex(ab[4],2); // дата
StaticText5.Caption:=IntToHex(ab[5],2); //месяц
StaticText6.Caption:=IntToHex(ab[6],2); // год
end;
end;
end;
end; {конец таймера)
По аналогии вы легко добавите процедуры, соответствующие всем остальным командам, предусмотренным в программе нашего измерителя. Пользуясь функцией DateTime, легко создать процедуру, которая будет загружать из компьютера точное время (только С форматом TDateTime придется немного попотеть, см. по этому поводу [15] и [16]). Не забывайте принимать и анализировать возвращаемые байты для процедур записи. При длинной процедуре приема данных из flash, когда число байтов заранее неизвестно, суммарное значение счетчика хn покажет, сколько именно байтов принято. Причем если это число не кратно четырем, то можно смело утверждать, что целостность данных была нарушена. И не забудьте увеличить размер массива ab, если у вас энергонезависимая память большей емкости!
Наряду с такой программой для обслуживания прибора имеет смысл также написать отдельное приложение, которое обрабатывает скачанные данные по температуре и давлению, переводит их в физические величины и представляет их в вид масштабируемого графика, отфильтровывая и записывая отдельно для просмотра байты сбоев с соответствующими датами.
Глава 19
Практические схемы на AVR