Page 1 of 1

Serial Communication

Posted: Mon Oct 01, 2007 9:31 am
by joop hermsen
To All

Our company have just decided using FWPPC instead of our Clipper application at this moment where are just practicing with some basic things, like fonts, buttons, pull-down menus etc.
We also would like to practice with a serial external device.

Can someone give me a sample to start practicing with serial communication?

Here a small part of our clipper application, to wake up our serial device.

Fuction WakeUp_VendingMachine(portnumber)
Local nCharacter := 0
Local Pos1 := 0
Local helpstr := ""
Local retwaarde := .F.

IF portnumber = NILL
portnumber = 1
ENDIF

IF COM_INIT(portnumber,9600,"E",8,1)
IF COM_OPEN(portnumber, 1000, 1000) //.T. when successful
COM_FLUSH(portnumber)
COM_SEND(portnumber,REPLICATE("*",30))//Wake_Up VendingMach
delay(100) //wait for 1 second
nCharacter := COM_COUNT(portnumber) //Number of characters
IF nCharacter > 0
HelpSTR=COM_READ(portnumber,nCharacter) //Read n characters
Pos1 = AT("##",HelpSTR)
IF Pos1 > 0 //Vending <Machine is Up
ret_waarde=.T.
ENDIF
ENDIF
ENDIF
ENDIF
RETURN ret_waarde

I hope somebody can help me to start this issue in a good direction.

Best regards,
Joop

Posted: Mon Oct 01, 2007 11:45 am
by Antonio Linares
Hello Joop,

Nice to meet you here :-)

Please make a search for *comm on this same FWPPC forum and you will get lots of samples :-)

Posted: Tue Oct 02, 2007 2:53 pm
by joop hermsen
Antonio Linares wrote:Hello Joop,

Nice to meet you here :-)

Please make a search for *comm on this same FWPPC forum and you will get lots of samples :-)
Hello Antonio,

I can't find a sample with a simple Initcomm, writecomm or readcomm.
In fact, I don't understand the most samples concerning serial communication!

Even in the help functions I can't find for example to set an EVEN parity?

I hoped to get some input to take the first step to improve that FWPPC can communicate with our vending machine….

DEFINE COMM <oComm>
[ STOP <nStop> ];
[ BAUD <nBaud> ];
[ PARITY <cParity> ];
[ INSIZE <nInQueue> ];
[ OUTSIZE <nOutQueue> ];
[ DEVICE <nDevice> ];
[ DATA <nData> ];

<oComm> The variable to hold this object.
<nNumber> Number of queue to flush.
<nData> Number of bits.
<nCode> Escape code to send.
<cString> A text to send.
<nDevice> Device number.
<nBaud> Bauds speed.
<nOutQueue> Size of the out queue in bytes.
<cParity> Parity "y" yes or "n" no.
<nStop> Number of stop bytes.

Posted: Tue Oct 02, 2007 8:34 pm
by Salvador
joop.

Este fuente puede servirte de ayuda.

Saludos.

Salvador Gallardo

Code: Select all

/////////////////////////////////////////////
//
// Funciones de comunicacion por Rs232
//
////////////////////////////////////////////
#include "Fwce.ch"

#define BUFF_IN               1024
#define BUFF_OUT              1024
#define GENERIC_READ          0x80000000
#define GENERIC_WRITE         0x40000000
#define OPEN_EXISTING         3
#define FILE_ATTRIBUTE_NORMAL 0x00000080

#define NOPARITY            0
#define ODDPARITY           1
#define EVENPARITY          2
#define MARKPARITY          3
#define SPACEPARITY         4

#define ONESTOPBIT          0
#define ONE5STOPBITS        1
#define TWOSTOPBITS         2

///////////////////////////////////////////////
//
// OpenCom
// Abre el puerto especificado y lo configura
//////////////////////////////////////////////
Function OpenCom( nCom, nBauds, nParity, nDataByt, nStopBits, lIRmode )
LOCAL hComm, cComm

DEFAULT nCom := 1, nBauds := 2400, nParity := NOPARITY, nDataByt := 8, lIRmode := .f.
DEFAULT nStopBits := ONESTOPBIT
cComm := "Com"+ AllTrim( Str( nCom, 2 ) )+ ":"

hComm := CreateFile( cComm, nOr(GENERIC_WRITE, GENERIC_READ) , 0, 0, OPEN_EXISTING, 0,0 )

IF hComm ==-1
  Msginfo("Fallo al abrir "+ cComm)
  Return -1
ENDIF

IF lIRMode
  IF !RAWIRON( hComm )
    Msginfo( "Fallo al iniciar RAWIR")
    ComClose( hComm )
    RETURN -1
  ENDIF
ENDIF


IF !SetComm( hComm, nBauds, nParity, nDataByt, nStopBits )
  MsgInfo("Fallo al configurar "+ cComm)
  ComClose( hComm )
  RETURN -1
ENDIF

RETURN hComm


///////////////////////////////////
//
// ComSend( nHdlCom, cString )
//
////////////////////////////////////////////

Function  ComSend( hComm, cString )

LOCAL nBytesend, nBytes:= Len( cString )

nByteSend := WriteComm( hComm, @cString, nBytes )

Return  ( nByteSend == nBytes )


////////////////////////////////////
//
// ComRead( nHdlCom, nChars )
//
////////////////////////////////////////////
Function ComRead( nHdlCom, nChars )
LOCAL nBytes, cBuffIn := Space(BUFF_IN)

nBytes := ReadComm( nHdlCom, @cBuffIn, nChars )

RETURN if( nBytes >0, Left( cBuffIn, nBytes ),"" )


////////////////////////////////////
//
// ComClose( nHdlCom)
//
////////////////////////////////////////////
FUNCTION ComClose( hComm )

RAWIROFF( hComm )
CloseHandle( hComm )

RETURN .t.


#pragma BEGINDUMP

#include <windows.h>
#include <winbase.h>
#include <hbapi.h>
#include <aygshell.h>

HB_FUNC( SETCOMM )
{
   DCB dcb;
   COMMTIMEOUTS timeouts;

   SetupComm(( HANDLE) hb_parnl( 1 ), BUFF_IN, BUFF_OUT ) ;

   GetCommState( ( HANDLE ) hb_parnl( 1 ), &dcb );

   dcb.BaudRate             = hb_parnl( 2 );
   dcb.Parity               = hb_parni( 3 );
   dcb.ByteSize             = hb_parni( 4 );
   dcb.StopBits             = hb_parni( 5 );

   dcb.fBinary              = TRUE;
   dcb.fParity              = TRUE;
   dcb.fOutxCtsFlow         = FALSE;
   dcb.fOutxDsrFlow         = FALSE;
   dcb.fDtrControl          = DTR_CONTROL_DISABLE;
   dcb.fDsrSensitivity      = FALSE;
   dcb.fTXContinueOnXoff    = FALSE;
   dcb.fOutX                = FALSE;
   dcb.fInX                 = FALSE;
   dcb.fErrorChar           = FALSE;
   dcb.fNull                = FALSE;
   dcb.fRtsControl          = RTS_CONTROL_DISABLE;
   dcb.fAbortOnError        = FALSE;

   GetCommTimeouts(( HANDLE) hb_parnl, &timeouts);

   timeouts.ReadIntervalTimeout         = 0;
   timeouts.ReadTotalTimeoutMultiplier  = 0;
   timeouts.ReadTotalTimeoutConstant    = 1000;
   timeouts.WriteTotalTimeoutMultiplier = 0;
   timeouts.WriteTotalTimeoutConstant   = 0;


   SetCommTimeouts(( HANDLE) hb_parnl( 1 ), &timeouts );

   hb_retl(SetCommState( ( HANDLE ) hb_parnl( 1 ), &dcb ));
}

HB_FUNC( READCOMM )
{
  DWORD dw = 0;
  ReadFile( ( HANDLE ) hb_parnl( 1 ), ( LPVOID ) hb_parc( 2 ), ( DWORD ) hb_parni( 3 ), &dw, NULL );

  hb_retni( ( int ) dw ? dw : -1 );
}

HB_FUNC( WRITECOMM )
{
  DWORD dw = 0;
  WriteFile( (HANDLE ) hb_parnl( 1 ), ( LPVOID ) hb_parc( 2 ), ( DWORD ) hb_parni( 3 ), &dw, NULL );
  hb_retni( ( int ) dw ? dw : -1);
}


HB_FUNC( RAWIRON )
{

   hb_retl( EscapeCommFunction( ( HANDLE ) hb_parnl( 1 ), SETIR ) );
}

HB_FUNC( RAWIROFF )
{

   hb_retl( EscapeCommFunction( ( HANDLE ) hb_parnl( 1 ), CLRIR ) );
}

#pragma ENDDUMP


Posted: Wed Oct 03, 2007 3:54 am
by Antonio Linares
Salvador,

Thanks! :-)

Serial Communication

Posted: Wed Oct 03, 2007 10:50 am
by joop hermsen
Salvador,

Muchas gracias!!!
I will do some testing today.


Regards,
Joop

Posted: Tue Oct 23, 2007 7:26 pm
by Arturo Lopesoria
Salvador. Gracias por el fuente. Lo probe con el codigo que pongo abajo.

NOTAS DE LAS PRUEBAS CON TUS FUENTES:
1.- Al compilar no reconocio las constantes, por lo que tuve que cambiar estas lineas:
// SetupComm(( HANDLE) hb_parnl( 1 ), BUFF_IN, BUFF_OUT ) ;
SetupComm(( HANDLE) hb_parnl( 1 ), 1024, 1024 ) ;

2.-En el dispositivo solo corre con lIRmode:=.F.. Por favor, podrias explicarnos que cambios en el control de flujo conlleva habilitar este parametro?

3.-Deshabilitando lIRMode pude Abrir el puerto COM3:, pero no puede enviar ni recibir datos. Tal vez hagan falta funciones del tipo Comm_DTR/DTS, o XON/XOFF ?? En tal caso, alguien podria explicarme los valores y como establecer el control de flujo?

4.-Aun cerrando el puerto debo reiniciar el programa para poder volver a abrir el puerto.

SALUDOS. LO PROBE CON ESTE CODIGO:

#include "FWCE.ch"

#define BUFF_IN 1024
#define BUFF_OUT 1024
#define GENERIC_READ 0x80000000
#define GENERIC_WRITE 0x40000000
#define OPEN_EXISTING 3
#define FILE_ATTRIBUTE_NORMAL 0x00000080
#define NOPARITY 0
#define ODDPARITY 1
#define EVENPARITY 2
#define MARKPARITY 3
#define SPACEPARITY 4
#define ONESTOPBIT 0
#define ONE5STOPBITS 1
#define TWOSTOPBITS 2

*--------------
FUNCTION Main()
*--------------
LOCAL ochk1l, lchk1:=.f., oWnd

DEFINE WINDOW oWnd TITLE "TestComm3"

@ 2, 1 CHECKBOX oChk1 VAR lChk1 PROMPT "lIRmode" OF oWnd COLOR "N/N*" SIZE 80, 20

@ 6, 1 BUTTON oBtn PROMPT "TstCom3" SIZE 80, 25 ;
ACTION SerialTrials(lchk1)

ACTIVATE WINDOW oWnd

RETU NIL


****************************************************************************

Function SerialTrials(lIRmode)
local hComm
IF (hComm:=OpenCom(3, 9600,,,, lIRmode )) > 0
msginfo("Ok Com3: "+str(hComm) + ", lIRmode:"+if(lIRmode,".t.",".f."))
IF ComSend( hComm, "hi there" )
msginfo("ComSend(hithere) regreso .T.")
cRead:=ComRead( nHdlCom, nChars )
msginfo("ComRead() regreso: "+cRead+ ",("+alltrim(str(len(cRead)))+" chs)")
else
msginfo("ComSend(hithere) regreso .FALSO.")
ENDIF
ComClose( hComm )
msginfo("puerto cerrado")
ENDIF
****************************************************************************



Salvador wrote:joop.

Este fuente puede servirte de ayuda.

Saludos.

Salvador Gallardo

Code: Select all

/////////////////////////////////////////////
//
// Funciones de comunicacion por Rs232
//
////////////////////////////////////////////
#include "Fwce.ch"

#define BUFF_IN               1024
#define BUFF_OUT              1024
#define GENERIC_READ          0x80000000
#define GENERIC_WRITE         0x40000000
#define OPEN_EXISTING         3
#define FILE_ATTRIBUTE_NORMAL 0x00000080

#define NOPARITY            0
#define ODDPARITY           1
#define EVENPARITY          2
#define MARKPARITY          3
#define SPACEPARITY         4

#define ONESTOPBIT          0
#define ONE5STOPBITS        1
#define TWOSTOPBITS         2

///////////////////////////////////////////////
//
// OpenCom
// Abre el puerto especificado y lo configura
//////////////////////////////////////////////
Function OpenCom( nCom, nBauds, nParity, nDataByt, nStopBits, lIRmode )
LOCAL hComm, cComm

DEFAULT nCom := 1, nBauds := 2400, nParity := NOPARITY, nDataByt := 8, lIRmode := .f.
DEFAULT nStopBits := ONESTOPBIT
cComm := "Com"+ AllTrim( Str( nCom, 2 ) )+ ":"

hComm := CreateFile( cComm, nOr(GENERIC_WRITE, GENERIC_READ) , 0, 0, OPEN_EXISTING, 0,0 )

IF hComm ==-1
  Msginfo("Fallo al abrir "+ cComm)
  Return -1
ENDIF

IF lIRMode
  IF !RAWIRON( hComm )
    Msginfo( "Fallo al iniciar RAWIR")
    ComClose( hComm )
    RETURN -1
  ENDIF
ENDIF


IF !SetComm( hComm, nBauds, nParity, nDataByt, nStopBits )
  MsgInfo("Fallo al configurar "+ cComm)
  ComClose( hComm )
  RETURN -1
ENDIF

RETURN hComm


///////////////////////////////////
//
// ComSend( nHdlCom, cString )
//
////////////////////////////////////////////

Function  ComSend( hComm, cString )

LOCAL nBytesend, nBytes:= Len( cString )

nByteSend := WriteComm( hComm, @cString, nBytes )

Return  ( nByteSend == nBytes )


////////////////////////////////////
//
// ComRead( nHdlCom, nChars )
//
////////////////////////////////////////////
Function ComRead( nHdlCom, nChars )
LOCAL nBytes, cBuffIn := Space(BUFF_IN)

nBytes := ReadComm( nHdlCom, @cBuffIn, nChars )

RETURN if( nBytes >0, Left( cBuffIn, nBytes ),"" )


////////////////////////////////////
//
// ComClose( nHdlCom)
//
////////////////////////////////////////////
FUNCTION ComClose( hComm )

RAWIROFF( hComm )
CloseHandle( hComm )

RETURN .t.


#pragma BEGINDUMP

#include <windows.h>
#include <winbase.h>
#include <hbapi.h>
#include <aygshell.h>

HB_FUNC( SETCOMM )
{
   DCB dcb;
   COMMTIMEOUTS timeouts;

   SetupComm(( HANDLE) hb_parnl( 1 ), BUFF_IN, BUFF_OUT ) ;

   GetCommState( ( HANDLE ) hb_parnl( 1 ), &dcb );

   dcb.BaudRate             = hb_parnl( 2 );
   dcb.Parity               = hb_parni( 3 );
   dcb.ByteSize             = hb_parni( 4 );
   dcb.StopBits             = hb_parni( 5 );

   dcb.fBinary              = TRUE;
   dcb.fParity              = TRUE;
   dcb.fOutxCtsFlow         = FALSE;
   dcb.fOutxDsrFlow         = FALSE;
   dcb.fDtrControl          = DTR_CONTROL_DISABLE;
   dcb.fDsrSensitivity      = FALSE;
   dcb.fTXContinueOnXoff    = FALSE;
   dcb.fOutX                = FALSE;
   dcb.fInX                 = FALSE;
   dcb.fErrorChar           = FALSE;
   dcb.fNull                = FALSE;
   dcb.fRtsControl          = RTS_CONTROL_DISABLE;
   dcb.fAbortOnError        = FALSE;

   GetCommTimeouts(( HANDLE) hb_parnl, &timeouts);

   timeouts.ReadIntervalTimeout         = 0;
   timeouts.ReadTotalTimeoutMultiplier  = 0;
   timeouts.ReadTotalTimeoutConstant    = 1000;
   timeouts.WriteTotalTimeoutMultiplier = 0;
   timeouts.WriteTotalTimeoutConstant   = 0;


   SetCommTimeouts(( HANDLE) hb_parnl( 1 ), &timeouts );

   hb_retl(SetCommState( ( HANDLE ) hb_parnl( 1 ), &dcb ));
}

HB_FUNC( READCOMM )
{
  DWORD dw = 0;
  ReadFile( ( HANDLE ) hb_parnl( 1 ), ( LPVOID ) hb_parc( 2 ), ( DWORD ) hb_parni( 3 ), &dw, NULL );

  hb_retni( ( int ) dw ? dw : -1 );
}

HB_FUNC( WRITECOMM )
{
  DWORD dw = 0;
  WriteFile( (HANDLE ) hb_parnl( 1 ), ( LPVOID ) hb_parc( 2 ), ( DWORD ) hb_parni( 3 ), &dw, NULL );
  hb_retni( ( int ) dw ? dw : -1);
}


HB_FUNC( RAWIRON )
{

   hb_retl( EscapeCommFunction( ( HANDLE ) hb_parnl( 1 ), SETIR ) );
}

HB_FUNC( RAWIROFF )
{

   hb_retl( EscapeCommFunction( ( HANDLE ) hb_parnl( 1 ), CLRIR ) );
}

#pragma ENDDUMP


Posted: Tue Oct 23, 2007 9:01 pm
by Salvador
Arturo,
La función EscapeCommFunction( ( HANDLE ) , SETIR ), lo que hace es habilitar el modo RAWIR en un puerto IR previamente abierto, en este modo no hay control de flujo de ningún tipo es decir en todo momento debemos saber cuando escribir o leer en el para que no se produzcan colisiones en la comunicación. Solo funcionan las señales RX y TX .
Para que el IR funcione en modo RAW en la configuración de la PPC en conexiones->infrarrojos, hay que desactivar "aceptar conexiones."
Lo utilizo en una aplicación que hace la lectura de unos dispositivos electrónicos controlados por PIC, que contabilizan las jugadas y los premios realizados en máquinas recreativas (tragaperras), funciona sin problemas.

Saludos.
Salvador

Posted: Tue Oct 23, 2007 10:00 pm
by Arturo Lopesoria
Gracias Salvador. Ahora voy a probar porqué no me aparece la configuración del puerto infrarojo en la PPC con WMobile 5.0
Salvador wrote:Arturo,
La función EscapeCommFunction( ( HANDLE ) , SETIR ), lo que hace es habilitar el modo RAWIR en un puerto IR previamente abierto, en este modo no hay control de flujo de ningún tipo es decir en todo momento debemos saber cuando escribir o leer en el para que no se produzcan colisiones en la comunicación. Solo funcionan las señales RX y TX .
Para que el IR funcione en modo RAW en la configuración de la PPC en conexiones->infrarrojos, hay que desactivar "aceptar conexiones."
Lo utilizo en una aplicación que hace la lectura de unos dispositivos electrónicos controlados por PIC, que contabilizan las jugadas y los premios realizados en máquinas recreativas (tragaperras), funciona sin problemas.

Saludos.
Salvador

Posted: Tue Oct 23, 2007 10:02 pm
by Salvador
Arturo me olvidaba !!

No todas las PDA son compatibles con el modo RAWIR. He utilizado HP2210 y HP HX2490 y no dan problemas.

Saludos.
Salvador

Posted: Tue Oct 23, 2007 10:06 pm
by Arturo Lopesoria
Entiendo. Yo estoy probando con la Symbol MC35. Aun asi creo que deberia haber algun parametro de configuracion relativo al IRDA en mi PPC y por algun arazon no lo encuentro.
Gracias.
Salvador wrote:Arturo me olvidaba !!

No todas las PDA son compatibles con el modo RAWIR. He utilizado HP2210 y HP HX2490 y no dan problemas.

Saludos.
Salvador