Юрий Ревич - Занимательная микроэлектроника
- Название:Занимательная микроэлектроника
- Автор:
- Жанр:
- Издательство:БХВ-Петербург
- Год:2007
- Город:Санкт-Петербург
- ISBN:978-5-9775-0080-7
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Юрий Ревич - Занимательная микроэлектроника краткое содержание
Для широкого круга радиолюбителей
Занимательная микроэлектроника - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
Принцип работы компонента заключается как раз в создании параллельного потока, в котором байты принимаются по мере их поступления и накапливаются в буфере независимо от деятельности основной программы. Специально следить за приходом данных не требуется, поскольку все делается автоматически, нам остается только отловить принятые данные. Недостаток этого способа в том, что данные принимаются кучей в одной процедуре, и приходится отдельно разбираться, что же мы приняли в данный момент, и где заканчиваются одни данные и начинаются другие. Но при использовании параллельного потока это пришлось бы делать в любом случае, а тут все организовано за вас, «ручками» ничего делать не приходится.
После установки компонент будет находиться в палитре компонентов на вкладке AsyncFree. На самом деле там образуется много компонентов, но нам требуется только самый первый из них под названием AfComPort. Установим его на форму. В перечень переменных добавим:
…
FlagCOM:boolean=False;
FlagSend:integer=0;
tall:integer;
…
Переменные toldи ttimeнам здесь не понадобятся. На форму добавим Label7, в который будем выводить установленный порт и скорость передачи, и Timer. Проверьте, чтобы у таймера интервал составлял 1000 мс (так по умолчанию). Кроме этого, установим компонент comboBox(выпадающий список), у которого в свойстве Itemsсразу запишем строки для выбора СОМ-порта («СОМ1», «COM2» и т. п.). Аналогичный список можно создать для выбора скорости передачи, но если речь идет о конкретном приборе, то это необязательно (а вот СОМ выбирать, скорее всего, придется).
Начнем с того, что перепишем процедуру IniCoM, что иллюстрирует листинг 18.4 (как и в предыдущем случае, к моменту ее вызова в stcomдолжна находиться строка с номером порта, например, «СОМ1»).
Листинг 18.4
procedure IniCOM;
var i, err: integer;
begin
FlagCOM:=False;
Form1.Label7.Caption:='COM?';
{инициализация COM — номер в строке stcom}
Form1.AfComPort1.Close; {закрываем старый COM, если был}
val(stcom[length(stcom)],i,err); {извлекаем номер порта}
if err=0 then Form1.AfComPort1.ComNumber:=i else exit;
{здесь требуется число, а не строка}
Form1.AfComPortl.BaudRate:=br9600; {скорость 9600}
try
Form1.AfComPortl.Open ;{пробуем открыть}
except
if not Form1.AfComPort1.Active then{если не открылся}
begin
st:=stcom+' does not be present or occupied.';
Application.MessageBox(Pchar(st),'Error',MB_OK);
exit{выход из процедуры — неудача}
end;
end;
ab[1]:=ord('A'); {будем посылать инициализацию модема}
ab[2]:=ord('Т');
ab[3]:=13; {CR}
ab[4]:=10; {LF}
for i:=1 to 4 do Form1.AfComPort1.WriteData(ab[i],1);
{ответ не сразу:}
Form1.Timer1.Enabled:=True;
tall:=0;
while tall<1 do application.ProcessMessages; {пауза в 1 с}
Form1.Timer1.Enabled:=False;
st:=Form1.AfComPort1.ReadString; {ответ модема 10 знаков}
if pos(1 OK',st)<>0 then {модем}
begin
st:=stcom+' занят модемом';
Application.MessageBox(Pchar(st),'Error',MB_OK);
exit;
end else{все нормально, COM открыт}
begin
Form1.Label7.Caption:=stcom+' 96001;
FlagCOM:=True;
end;
end;
Как видим, процедура создания порта много понятнее, чем в случае прямого обращения к API — все через привычную установку свойств компонента. FlagCOMиграет у нас роль индикатора, доступен порт или нет. Если он остался при значении False, то процедуру следует повторить с другим значением в строке stcom(каковую мы задаем с помощью ComboBox, см. далее). При определении модема применен хитрый способ задания паузы — вместо обычного оператора Sleep, который тормозит программу, мы использовали таймер. Чтобы это сработало, надо в обработчике события OnTimer: все время увеличивать переменную tall. Полностью процедура по таймеру приводится далее, т. к. tall нам понадобится не только для этого.
Как только мы обратились к процедуре AfComPort1.open, у нас немедленно будет создан параллельный поток и весь прием пойдет через него. Поэтому, чтобы при определении модема принятые байты не обрабатывались, нужно не забыть добавить в процедуру приема выход по условию FiagCOM=Faise.
Для создания этой процедуры обычным способом — через инспектор объектов — создадим обработчик события AfComPort1DataRecived [17] Написание слова «receive» — настоящая проблема для любого, кто не является носителем английского языка. Каких только вариантов не встретишь на просторах Сети! Как видим, наш чех Петя Вонис также не избежал общей участи.
(листинг 18.5).
Листинг 18.5
procedure TForm1.AfComPort1DataRecived(Sender:TObject; Count:Integer);
{чтение очередного байта по сообщению wmCOMPORT}
var i: integer;
begin
if FlagCOM=False then exit; {если модем еще не опрошен}
if count<>0 then{если что-то принято}
begin
AfComPort1.ReadData(ab,count);{читаем буфер в массив}
хn:=xn+count;{число принятых байт}
tall:=0;{обнуляем время}
end;
end;
На самом деле условие count<>0не требуется, оно введено просто ради порядка (иначе бы процедура просто не была бы вызвана). По выходу из процедуры в переменной хnбудет накапливаться количество принятых байтов. Осталось только дописать остальные процедуры (листинг 18.6).
Листинг 18.6
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установлен (T rue), иначе это вообще был не прием, а опрос модема. Сказанное иллюстрирует листинг 18.7.
Читать дальшеИнтервал:
Закладка: