Logo Hardware.com.br
Raul_Kl
Raul_Kl Veterano Registrado
1.2K Mensagens 65 Curtidas

[Resolvido] Loop em segundo plano no Lazarus. TThread?

#1 Por Raul_Kl 28/07/2010 - 20:37
Estou criando um programa bem simples para controlar dispositivos pela porta paralela no linux. Existem alguns programas escritos em C/C++ que fazem isso, mas pelo terminal. Quero um programa com interface gráfica, e como não consegui encontrar nenhum que fizesse o que quero(no linux), resolvi colocar as mãos na massa, digo, no teclado...

Estou construindo o programa com o Lazarus, que é o único em que consigo "me virar". Já tenho pronta e funcionando a parte de acionamento das saídas, mas para monitorar as entradas da porta paralela preciso criar um processo que seja executado em loop infinito, durante todo o tempo de execução do programa.

A questão é: Como criar esse loop sem travar meu programa? E como iniciar e parar o loop no momento que eu quiser? Pesquisando na internet, encontrei algumas coisas sobre TThread, mas não entendi direito como usar. Ou existe método melhor e mais simples para fazer?
PHIRON
PHIRON Zumbi Registrado
6K Mensagens 418 Curtidas
#2 Por PHIRON
28/07/2010 - 21:00
Você não tem acesso ao código fonte desses programas em C/C++ ? você pode usar os mesmos e adicionar apenas uma interface gráfica não? eu conheço pouco o lazarus e pascal, mas pelo visto você vai ter que criar um daemon que monitore a sua entrada, um serviço tipo o hal/dbus etc.
Verifique se em pascal é possível criar algo desse tipo. Looping infinito é complicado, todas as linguagens possuem um limite para isso, com certeza quando um dispositivo emite/envia algum dado/sinal o sistema operacional responde de alguma forma a isso, nesse caso no linux a porta paralela cria um dispositivo virtual em /dev/ então você cria um programa que receba a entrada desse dispositivo e entenda o que ele envia, você não precisaria necessariamente de um looping infinito para isso, bastava descobrir uma entrada válida na linguagem que reconheça esse tipo de dispositivo (por exemplo, o scanf em C reconhece entrada de teclado, teria que descobrir qual , no seu caso em pascal, método/objeto receberia a entrada do dispositivo virtual em /dev) eu sugeriria dar uma olhada em C pois deve ter bibliotecas prontas para isso e criava uma interface em Qt ou GTK, eu sugeriria o Qt por ter melhores ferramentas e uma ótima documentação.

Thread é computação paralela, um conceito muito mais complexo e difícil de implementar do que a minha sugestão big_green.png
Raul_Kl
Raul_Kl Veterano Registrado
1.2K Mensagens 65 Curtidas
#3 Por Raul_Kl
28/07/2010 - 21:38
Bem, vou postar o código que já tenho. Acessar a porta não é problema, o que não estou conseguindo é encontrar uma maneira de ficar monitorando continuadamente a entrada. As soluções prontas que encontrei(ioport, portcontrol...) também não fazem muita coisa. São ferramentas para serem usadas por linha de comando, e que apenas retornam uma informação quando acionadas. Mas essa é a parte fácil.

Nesse caso, o daemon em loop ficaria continuadamente comparando o estado atual da porta com o estado anterior, e em caso de alteração, tomaria a decisão programada. O meu problema é exatamente o monitoramento contínuo.


unit Unit1;

{$mode objfpc}{$H+}

interface

uses
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
StdCtrls, Ports, Crt;

type

{ TForm1 }

TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
CheckBox1: TCheckBox;
CheckBox2: TCheckBox;
CheckBox3: TCheckBox;
CheckBox4: TCheckBox;
CheckBox5: TCheckBox;
CheckBox6: TCheckBox;
CheckBox7: TCheckBox;
CheckBox8: TCheckBox;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure CheckBox1Change(Sender: TObject);
procedure CheckBox2Change(Sender: TObject);
procedure CheckBox3Change(Sender: TObject);
procedure CheckBox4Change(Sender: TObject);
procedure CheckBox5Change(Sender: TObject);
procedure CheckBox6Change(Sender: TObject);
procedure CheckBox7Change(Sender: TObject);
procedure CheckBox8Change(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
end;

var
Form1: TForm1;
Led1, Led2, Led3, Led4, Led5, Led6, Led7, Led8: boolean;
PortStatus: Integer;

function ioperm(from: Cardinal; num: Cardinal; turn_on: Integer): Integer; cdecl; external 'libc';

implementation

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin
ioperm($378,8,1);
port[$378]:=0;
Led1:=false;
Led2:=false;
Led3:=false;
Led4:=false;
Led5:=false;
Led6:=false;
Led7:=false;
Led8:=false;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Form1.CheckBox1.Checked:=true;
Form1.CheckBox2.Checked:=true;
Form1.CheckBox3.Checked:=true;
Form1.CheckBox4.Checked:=true;
Form1.CheckBox5.Checked:=true;
Form1.CheckBox6.Checked:=true;
Form1.CheckBox7.Checked:=true;
Form1.CheckBox8.Checked:=true;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Form1.CheckBox1.Checked:=false;
Form1.CheckBox2.Checked:=false;
Form1.CheckBox3.Checked:=false;
Form1.CheckBox4.Checked:=false;
Form1.CheckBox5.Checked:=false;
Form1.CheckBox6.Checked:=false;
Form1.CheckBox7.Checked:=false;
Form1.CheckBox8.Checked:=false;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Form1.CheckBox1.Checked:=true;
Delay(300);
Form1.CheckBox1.Checked:=false;
end;

procedure TForm1.CheckBox1Change(Sender: TObject);
begin
if (Led1=false) then
begin
PortStatus:=(Integer(port[$378]))+1;
port[$378]:=PortStatus;
Led1:=true;
end
else if (Led1=true) then
begin
PortStatus:=(Integer(port[$378]))-1;
port[$378]:=PortStatus;
Led1:=false;
end;
end;

procedure TForm1.CheckBox2Change(Sender: TObject);
begin
if (Led2=false) then
begin
PortStatus:=(Integer(port[$378]))+2;
port[$378]:=PortStatus;
Led2:=true;
end
else if (Led2=true) then
begin
PortStatus:=(Integer(port[$378]))-2;
port[$378]:=PortStatus;
Led2:=false;
end;

end;

procedure TForm1.CheckBox3Change(Sender: TObject);
begin
if (Led3=false) then
begin
PortStatus:=(Integer(port[$378]))+4;
port[$378]:=PortStatus;
Led3:=true;
end
else if (Led3=true) then
begin
PortStatus:=(Integer(port[$378]))-4;
port[$378]:=PortStatus;
Led3:=false;
end;
end;

procedure TForm1.CheckBox4Change(Sender: TObject);
begin
if (Led4=false) then
begin
PortStatus:=(Integer(port[$378]))+8;
port[$378]:=PortStatus;
Led4:=true;
end
else if (Led4=true) then
begin
PortStatus:=(Integer(port[$378]))-8;
port[$378]:=PortStatus;
Led4:=false;
end;
end;

procedure TForm1.CheckBox5Change(Sender: TObject);
begin
if (Led5=false) then
begin
PortStatus:=(Integer(port[$378]))+16;
port[$378]:=PortStatus;
Led5:=true;
end
else if (Led5=true) then
begin
PortStatus:=(Integer(port[$378]))-16;
port[$378]:=PortStatus;
Led5:=false;
end;
end;

procedure TForm1.CheckBox6Change(Sender: TObject);
begin
if (Led6=false) then
begin
PortStatus:=(Integer(port[$378]))+32;
port[$378]:=PortStatus;
Led6:=true;
end
else if (Led6=true) then
begin
PortStatus:=(Integer(port[$378]))-32;
port[$378]:=PortStatus;
Led6:=false;
end;
end;

procedure TForm1.CheckBox7Change(Sender: TObject);
begin
if (Led7=false) then
begin
PortStatus:=(Integer(port[$378]))+64;
port[$378]:=PortStatus;
Led7:=true;
end
else if (Led7=true) then
begin
PortStatus:=(Integer(port[$378]))-64;
port[$378]:=PortStatus;
Led7:=false;
end;
end;

procedure TForm1.CheckBox8Change(Sender: TObject);
begin
if (Led8=false) then
begin
PortStatus:=(Integer(port[$378]))+128;
port[$378]:=PortStatus;
Led8:=true;
end
else if (Led8=true) then
begin
PortStatus:=(Integer(port[$378]))-128;
port[$378]:=PortStatus;
Led8:=false;
end;
end;

initialization
{$I unit1.lrs}

end.
Obs.: Este código ainda está em fase experimental, e funciona para acionar as 8 saídas da porta paralela, mas ainda não tem nada para controlar as entradas.

EDIT: Bem, desculpem pelo tópico besta, mas pesquisei um pouco e encontrei uma solução extremamente simples: TTimer!
Foi só adicionar o comando para verificar o status da porta ao evento OnTimer e setar um valor baixo ao timer. Só isso.
© 1999-2024 Hardware.com.br. Todos os direitos reservados.
Imagem do Modal