Problemas com comunicação de porta serial

Delphi

18/08/2008

Olá a todos, estou com problemas com um programinha que lê os dados enviados para a porta serial do micro! Estou usando uma API do windows pra isso e o problema é um tanto estranho! Qdo ligo o micro e coloco o programa para rodar ele ñ funciona, recebe apenas um ou dois caracteres de controle! Se eu abrir o Hiper Terminal do Windows e colocar as mesmas configurações q estão dentro do programa, os dados são recebidos corretamente no Hyper Terminal! O grande problema é q depois q uso o Hiper Termial e o fecho, o programa passa a receber os dados corretamente! Estou colocando a parte do cógiso em q acho q pode estar o problema!
Desde já Obrigado


Function OpenComm(NomePorta, ConfigPorta: String):Boolean;
var BarDCB: DCB;
    LastError: Cardinal;
    CTimeOut: COMMTIMEOUTS;
begin
   hComm:=CreateFile(PChar(NomePorta),GENERIC_READ+GENERIC_WRITE,
                                0, //not shared
                                nil, //no security
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL, //+FILE_FLAG_OVERLAPPED
                                0 );
    If hComm = INVALID_HANDLE_VALUE Then begin
        ShowMessage(´Porta Serial ´ + NomePorta + ´ não disponível. configure os paramentros da porta serial´);
        Result:=False;
        Exit;
    End;
//  Configurar os Time Outs para a Porta
    CtimeOut.ReadIntervalTimeout:=20;
    CtimeOut.ReadTotalTimeoutConstant:=1;
    CtimeOut.ReadTotalTimeoutMultiplier:=1;
    CtimeOut.WriteTotalTimeoutConstant:=20;
    CtimeOut.WriteTotalTimeoutMultiplier:=1;
    iRet:=SetCommTimeouts(hComm, CTimeOut);
    If Ord(iRet)= -1 Then begin
        LastError:=GetLastError();
        ShowMessage(´Não é permitido configurar os Timeouts para esta porta ´ + NomePorta + ´ Erro: ´ + Inttostr(LastError));
        CloseHandle(hComm);
        Result:=False;
        Exit;
    End;
    BarDCB.BaudRate := CBR_115200;
    BarDCB.ByteSize := 8;
    BarDCB.Parity   := NOPARITY;
    BarDCB.StopBits := ONESTOPBIT;

    iRet:=BuildCommDCB(PChar(´COM1:115200,N,8,1´), BarDCB);
    If Ord(iRet)=-1 Then begin
        LastError:= GetLastError();
        ShowMessage(´Não é permitido montar os parametros da Porta´ + ConfigPorta + ´ Erro: ´ + Inttostr(LastError));
        CloseHandle(hComm);
        Result:=False;
        Exit;
    End;}
    iRet := SetCommState(hComm, BarDCB);
    If Ord(iRet)= -1 Then begin
        LastError:= GetLastError();
        ShowMessage(´Não é permitido configurar os parametros da Porta´ + ConfigPorta + ´ Erro: ´ + Inttostr(LastError));
        CloseHandle(hComm);
        Result:=False;
        Exit;
    End;
    Result:=True;
End;



Ccbrambilla

Ccbrambilla

Curtidas 0

Respostas

Obrunno

Obrunno

18/08/2008

O problema é que o windows XP não permite controlar dispositivos de hardware diretamente sem driver iniciado.

Em outras palavras, vc terá de simular o uso de um driver. Tenho um sistema desse funcionando perfeitamente via porta paralela.

Sugiro a vc usar a inpout32.dll. Pesquise na internet a fonte de download e os parametros de uso.


GOSTEI 0
Ccbrambilla

Ccbrambilla

18/08/2008

Olá obruno, obrigado pela dica!
Consegui resolver o problema usando a API do windows (com apenas 1 linha) e agora está ótimo, só preciso testar com o Vista ou ainda o 98!

Valeu

CEzar


GOSTEI 0
Carlosib

Carlosib

18/08/2008

Coloca ae a solução encontrada :)


GOSTEI 0
Ccbrambilla

Ccbrambilla

18/08/2008

Segue o código completo e mais tratado do q o anterior e o problemas estava no fato de não usar o comando ´GetCommState´ antes de setar os parâmetros de configuração da porta.

Abraços a todos!

Function OpenComm(NomePorta, ConfigPorta: String):Boolean;
var BarDCB: DCB;
    LastError: Cardinal;
    CTimeOut: COMMTIMEOUTS;
begin
   hComm:=CreateFile(PChar(NomePorta),GENERIC_READ+GENERIC_WRITE,
                                0, //not shared
                                nil, //no security
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL, //+FILE_FLAG_OVERLAPPED
                                0 );
    If hComm = INVALID_HANDLE_VALUE Then
    begin
        ShowMessage(´Porta Serial ´ + NomePorta + ´ não disponível. configure os paramentros da porta serial´);
        Result:=False;
        Exit;
    End;
//  Configurar os Time Outs para a Porta
    CtimeOut.ReadIntervalTimeout         :=20;
    CtimeOut.ReadTotalTimeoutConstant    :=1;
    CtimeOut.ReadTotalTimeoutMultiplier  :=1;
    CtimeOut.WriteTotalTimeoutConstant   :=20;
    CtimeOut.WriteTotalTimeoutMultiplier :=1;

    iRet:=SetCommTimeouts(hComm, CTimeOut);
    If Ord(iRet)= -1 Then
    begin
        LastError:=GetLastError();
        ShowMessage(´Não é permitido configurar os Timeouts para esta porta ´ + NomePorta + ´ Erro: ´ + Inttostr(LastError));
        CloseHandle(hComm);
        Result:=False;
        Exit;
    End;

    iRet := GetCommState(hComm, BarDCB);
    If Ord(iRet)=-1 Then
    begin
        LastError:= GetLastError();
        ShowMessage(´Não é permitido montar os parametros da Porta ´ + ConfigPorta + ´ Erro: ´ + Inttostr(LastError));
        CloseHandle(hComm);
        Result:=False;
        Exit;
    End;

    BarDCB.BaudRate := CBR_115200;
    BarDCB.ByteSize := 8;
    BarDCB.Parity   := NOPARITY;
    BarDCB.StopBits := ONESTOPBIT;

    iRet:=BuildCommDCB(PChar(NomePorta + ´:´ + ConfigPorta), BarDCB);
    If Ord(iRet)=-1 Then
    begin
        LastError:= GetLastError();
        ShowMessage(´Não é permitido montar os parametros da Porta ´ + ConfigPorta + ´ Erro: ´ + Inttostr(LastError));
        CloseHandle(hComm);
        Result:=False;
        Exit;
    End;

    iRet := SetCommState(hComm, BarDCB);
    If Ord(iRet)= -1 Then
    begin
        LastError:= GetLastError();
        ShowMessage(´Não é permitido configurar os parametros da Porta´ + ConfigPorta + ´ Erro: ´ + Inttostr(LastError));
        CloseHandle(hComm);
        Result:=False;
        Exit;
    End;
    Result:=True;
End;



GOSTEI 0
Carlosib

Carlosib

18/08/2008

Não querendo ser chato... mas já o sendo... dá um exemplo de quais parâmetros vc passaria para chamar a função.

Function OpenComm(NomePorta, ConfigPorta: String):Boolean


Nome da porta seria COM1, COM2, etc?

ConfigPorta seria o que?


GOSTEI 0
Ccbrambilla

Ccbrambilla

18/08/2008

Sem problema nenhum, é o seguinte, o NomePorta é isso COM1, COM2...

o ConfigPorta seria ´115200,N,8,1´ onde esses parâmetros seriam:

´BaudeRate, Parity, ByteSize, StopBits´, e passando esses parâmetros eu acho q nem precisaria passar as linas de código :

    BarDCB.BaudRate := CBR_115200; 
    BarDCB.ByteSize := 8; 
    BarDCB.Parity   := NOPARITY; 
    BarDCB.StopBits := ONESTOPBIT; 


mas ainda não deu tempo de fazer os testes!

Abraços


GOSTEI 0
Wilson Azevedo

Wilson Azevedo

18/08/2008

Estou utilizando a mesma API e o mesmo código para comunicação com um transceptor de radioamador que utiliza caracteres em Hexadecimal em sua conexão com a serial. A recepção dos caracteres está ok, más não tô conseguindo transmitir nenhum caracter, através da função "function TPorta_Serial.SendComm(sComando: String): Integer;". Já alterei a forma de abertura da COM em "function TPorta_Serial.F_CharToHex(MyChar: Char): String;" e nada. Outra questão, é que quando abrimos a COM, a linhas DTR e RTS vem habilitadas, precisando chamar a funções correspondentes (final do código) para desativá-las, ocasionando um pico momentâneo de ativação das mesmas. Teria como abrir a serial ser ter essas linhas ativadas? Estou usando o Delphi X7 e Windows 8.1. Se alguém puder me ajudar serei grato. Veja o código abaixo.

[code][/unit Porta_Serial_Codigo;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
TPorta_Serial = class(TForm)
function F_CharToHex(MyChar: Char): String;
function OpenComm(NomePorta, ConfigPorta: String): Boolean;
function CloseComm(): Boolean;
procedure FlushComm();
procedure ClearReadComm();
procedure ClearSendComm();
function ReadComm(): String;
function SendComm(sComando: String): Integer;
function GetSensors(): String;
procedure DTR_On_Off(ATIVADO: Boolean);
procedure RTS_On_Off(ATIVADO: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Porta_Serial: TPorta_Serial;
hComm: THandle;
bRead: array[0..255] of byte;
iRet: LongBool;
bAberta: Boolean;

implementation

{$R *.dfm}

uses Captura_Dados_Serial;

function TPorta_Serial.F_CharToHex(MyChar: Char): String;
var escala: string;
res, num: integer;
begin
num:=Ord(Mychar);
escala := '0123456789ABCDEF';
res := (num div 16);
result := escala[res+1];
res := (num-(res*16));
result := result+escala[res+1];
end;

function TPorta_Serial.OpenComm(NomePorta, ConfigPorta: String): Boolean;
var
BarDCB: DCB;
LastError: Cardinal;
CTimeOut: COMMTIMEOUTS;
begin
//==============================================================================
// Abrir porta.
hComm := CreateFile(PChar(NomePorta),GENERIC_READ + GENERIC_WRITE,
0, //not shared
nil, //no security
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, //+ FILE_FLAG_OVERLAPPED
0 );

if hComm = INVALID_HANDLE_VALUE then
begin
ShowMessage('Porta Serial ' + NomePorta + ' não disponível. Configure os parâmentros da porta serial');
Result := False;
Exit;
end;
//==============================================================================
// Configurar os Time Outs para a Porta
CtimeOut.ReadIntervalTimeout:=20;
CtimeOut.ReadTotalTimeoutConstant:=1;
CtimeOut.ReadTotalTimeoutMultiplier:=1;
CtimeOut.WriteTotalTimeoutConstant:=20;
CtimeOut.WriteTotalTimeoutMultiplier:=1;

iRet := SetCommTimeouts(hComm, CTimeOut);

if Ord(iRet) = -1 then
begin
LastError := GetLastError();
ShowMessage('Não é permitido configurar os timeouts para esta porta ' + NomePorta + ' Erro: ' + Inttostr(LastError));
CloseHandle(hComm);
Result := False;
Exit;
end;
//==============================================================================
iRet := GetCommState(hComm, BarDCB);

if Ord(iRet) = -1 then
begin
LastError := GetLastError();
ShowMessage('Não é permitido montar os parâmetros da porta ' + ConfigPorta + ' Erro: ' + Inttostr(LastError));
CloseHandle(hComm);
Result := False;
Exit;
end;
//==============================================================================
iRet := BuildCommDCB(PChar(NomePorta + ':' + ConfigPorta), BarDCB);

if Ord(iRet) = -1 then
begin
LastError := GetLastError();
ShowMessage('Não é permitido montar os parâmetros da porta ' + ConfigPorta + ' Erro: ' + Inttostr(LastError));
CloseHandle(hComm);
Result := False;
Exit;
end;
//==============================================================================
iRet := SetCommState(hComm, BarDCB);

if Ord(iRet)= -1 then
begin
LastError := GetLastError();
ShowMessage('Não é permitido configurar os parâmetros da porta ' + ConfigPorta + ' Erro: ' + Inttostr(LastError));
CloseHandle(hComm);
Result := False;
Exit;
end;
//==============================================================================

//Desligando os comandos.
DTR_On_Off(False);
RTS_On_Off(False);

Result := True;
end;
//==============================================================================
{
Objetivo: Fechar comunicação com a porta serial
Retorno: True ou false
}
function TPorta_Serial.CloseComm(): Boolean;
begin
Result := CloseHandle(hComm);
end;
//==============================================================================
{
Objetivo: Limpar Buffer de Leitura e Escrita
}
procedure TPorta_Serial.FlushComm();
begin
FlushFileBuffers(hComm);
end;
//==============================================================================
{
Objetivo: Limpar dados recebidos na porta serial
}
procedure TPorta_Serial.ClearReadComm();
begin
PurgeComm(hComm,PURGE_RXCLEAR);
end;
//==============================================================================
{
Objetivo: Limpar dados enviados para porta serial
}
procedure TPorta_Serial.ClearSendComm();
begin
PurgeComm(hComm,PURGE_TXCLEAR);
end;
//==============================================================================
{
Objetivo: Ler dados na Porta serial
Retorno: String
}
function TPorta_Serial.ReadComm(): String;
var
BytesLidos: DWord;
I: Integer;
ReadStr: String;
begin
iRet := ReadFile(hComm, bRead[0], 255, BytesLidos, nil);
if ord(iRet) = -1 then exit;
ReadStr := '';

//if BytesLidos > 0 then ShowMessage(IntToStr(BytesLidos));

if BytesLidos > 0 then
begin
for I := 0 to BytesLidos - 1 do ReadStr := ReadStr + chr(bRead[I]);
end
else
begin
FlushComm;
end;

Result := ReadStr;
end;
//==============================================================================
{
Objetivo: Enviar dados para a porta serial
Paramentros:
sComando = ’54FEC400'
comando para configurar o leitor em 9600,o,8,1
Modelo TL800 da empresa Tecsimi
Retorno: Integer
}
function TPorta_Serial.SendComm(sComando: String): Integer;
var
BytesEnviados: DWORD;
begin
iRet := WriteFile(hComm,PCHAR(sComando)[0],Length(sComando), BytesEnviados, nil);
FlushComm;

if iRet then Result := BytesEnviados else Result := -1;
end;
//==============================================================================
//Saber estado de sensores.
function TPorta_Serial.GetSensors(): String;
var
COMStatus: DWORD; //Status do Modem (API).
RETORNO: String[4];
begin
//Obtém estado da COM.
GetCommModemStatus(hComm, COMStatus);

if(COMStatus and MS_RLSD_ON) = MS_RLSD_ON then //Se DCD está ligado.
RETORNO := '1' //DCD Ligado.
else
RETORNO := '0'; //DCD desligado.

if(COMStatus and MS_DSR_ON) = MS_DSR_ON then //Se DSR está ligado.
RETORNO := RETORNO + '1' //DSR ligado.
else
RETORNO := RETORNO + '0'; //DSR desligado.

if(COMStatus and MS_CTS_ON) = MS_CTS_ON then //Se CTS está ligado.
RETORNO := RETORNO + '1' //CTS ligado.
else
RETORNO := RETORNO + '0'; //CTS desligado.

if(COMStatus and MS_RING_ON) = MS_RING_ON then //Se RI está ligado.
RETORNO := RETORNO + '1' //RI ligado.
else
RETORNO := RETORNO + '0'; //RI desligado.

Result := RETORNO;
end;
//==============================================================================
//Ativar/Deativar comando DTR.
procedure TPorta_Serial.DTR_On_Off(ATIVADO: Boolean);
begin
if ATIVADO = True then
EscapeCommFunction(hComm, SETDTR) //Liga a linha DTR.
else
EscapeCommFunction(hComm, CLRDTR); //Desliga a linha DTR.
end;
//==============================================================================
//Ativar/Deativar comando RTS.
procedure TPorta_Serial.RTS_On_Off(ATIVADO: Boolean);
begin
if ATIVADO = True then
EscapeCommFunction(hComm, SETRTS) //Liga a linha RTS.
else
EscapeCommFunction(hComm, CLRRTS); //Desliga a linha RTS.
end;
//==============================================================================

end.code]


Abraço a todos.
GOSTEI 0
Mauricio Gabriel

Mauricio Gabriel

18/08/2008

Function OpenComm(NomePorta, ConfigPorta: String):Boolean

Poderia por favor ajudar-me neste sentido , pois estou com dificuldades em passar os parametros acima citados , devido ser iniciantes , fiz varias tentativas e sem sucesso de como chamar essa function .... poderia por favor ajudar-me neste sentido , ou posta o arquivo .pas para estudo a aprendizado. Desde já antecipo cordial agradecimentos.

Abaços.
GOSTEI 0
POSTAR