Comunicación por puerto serie

Anuncio
Club Builder
Documento: Comunicación por puerto serie
Autor: David Poinsett - dpoinsett@traverse.com
http://www.arrakis.es/~rporcar
e-mail: rporcar@retemail.es
Se puede distribuir este archivo siempre que no se efectúe ninguna modificación en el mismo. Se puede usar este documento con
fines educacionales, sin cargo alguno. Sin embargo, si desea utilizar este texto con fines comerciales (enseñanza o publicación),
debe contactar con el autor. No puede recibir ningún dinero por este documento sin consentimiento del autor.
Los comentarios dados en este color son importantes para entender el funcionamiento del ejemplo.
El texto escrito en este color, es el que el compilador ya ha generado y no debemos volver a copiar.
El código de color rojo, es el que debemos introducir para seguir el ejemplo.
El ejemplo consiste en un Form con un objeto Memo (para la entrada/salida de texto) y en un objeto
Thread. Empieza con un nuevo proyecto, donde situaremos un Memo en el Form1.
1.
Pon las propiedades del Memo de la siguiente forma:
Alignment = alClient
MaxLength = 0
ScrollBars = ssVertical
WantReturns = true
WantTabs = false
WordWrap = true
2.
File -> New... y añade un objeto Thread. Cuando pregunte el nombre para la clase, llámalo TRead.
Ahora deberías tener 2 units, una Unit1.cpp para el Form1, y una Unit2.cpp para el thread.
3.
Aquí hay una lista de los eventos a implementar:
Form1 OnCreate
Form1 OnClose
Memo1 OnKeyPress
4.
El código de la Unit1.cpp ...
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "Unit2.h" // CABECERA DE LA UNIT2 (THREAD)
// VARIABLES GLOBALES
HANDLE hComm = NULL;
TRead *ReadThread;
COMMTIMEOUTS ctmoNew = {0}, ctmoOld;
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Memo1->Clear();
DCB dcbCommPort;
// ABRE EL PUERTO
// REEMPLAZAR "COM2" POR "COM1", "COM3", ETC. PARA ABRIR
// OTRO PUERTO
hComm = CreateFile("COM2",
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
0,
0);
// SI EL PUERTO NO PUEDE ABRIRSE ...
if(hComm == INVALID_HANDLE_VALUE) Application->Terminate();
// ESTABLECEMOS LOS TIMEOUTS
GetCommTimeouts(hComm,&ctmoOld);
ctmoNew.ReadTotalTimeoutConstant = 100;
ctmoNew.ReadTotalTimeoutMultiplier = 0;
ctmoNew.WriteTotalTimeoutMultiplier = 0;
ctmoNew.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &ctmoNew);
// ESTABLECEMOS BAUD RATE, PARITY, WORD SIZE, Y STOP BITS.
// HAY OTROS METODOS DE HACER ESTO, PERO ESTE ES EL MAS FACIL
dcbCommPort.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcbCommPort);
BuildCommDCB("9600,N,8,1", &dcbCommPort);
SetCommState(hComm, &dcbCommPort);
// ACTIVAMOS EL THREAD
ReadThread = new TRead(false);
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
// TERMINAMOS EL THREAD.
ReadThread->Terminate();
// ESPERAMOS QUE TERMINE Y CERRAMOS EL PUERTO
Sleep(250);
PurgeComm(hComm, PURGE_RXABORT);
SetCommTimeouts(hComm, &ctmoOld);
CloseHandle(hComm);
}
//--------------------------------------------------------------------------void __fastcall TForm1::Memo1KeyPress(TObject *Sender, char &Key)
{
// TRANSMITE CUALQUIER COSA ESCRITA EN EL MEMO
TransmitCommChar(hComm, Key);
// ESTO PREVEE LA VISUALIZACION DE CARACTERES “BASURA” EN LA PANTALLA
if(Key != 13 && (Key < ' ' || Key > 'z')) Key = 0;
}
//---------------------------------------------------------------------------
5.
El código fuente de la Unit2.cpp...
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
// DEBES INCLUIR LA CABECERA DE LA UNIT1
#include "Unit1.h"
#include "Unit2.h"
extern HANDLE hComm;
char InBuff[100];
#pragma package(smart_init)
//--------------------------------------------------------------------------//
Important: Methods and properties of objects in VCL can only be
//
used in a method called using Synchronize, for example:
//
//
Synchronize(UpdateCaption);
//
//
where UpdateCaption could look like:
//
//
void __fastcall TRead::UpdateCaption()
//
{
//
Form1->Caption = "Updated in a thread";
//
}
//--------------------------------------------------------------------------__fastcall TRead::TRead(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//--------------------------------------------------------------------------void __fastcall TRead::DisplayIt()
{
// EN ESTE EJEMPLO NO SE TIENE EN CUENTA CUANTO TEXTO HA ENTRADO EN EL
// Memo1 QUE PUEDE SER SOLO DE 32K.
// TAMPOCO SE HACE NADA CON LOS CARACTERES NO IMPRIMIBLES
// MUESTRA EL TEXTO RECIBIDO
Form1->Memo1->SetSelTextBuf(InBuff);
}
void __fastcall TRead::Execute()
{
//---- Place thread code here ---DWORD dwBytesRead;
// HACE QUE EL OBJETO TRHEAD SEA DESTRUIDO CUANDO EL THREAD TERMINA
FreeOnTerminate = true;
while(1)
{
// INTENTA LEER DEL PUERTO SERIE
// Y SI HAY ALGO LO VISUALIZA
ReadFile(hComm, InBuff, 50, &dwBytesRead, NULL);
if(dwBytesRead)
{
InBuff[dwBytesRead] = 0; // ACABA LA CADENA EN NULO
Synchronize(DisplayIt);
}
}
}
//---------------------------------------------------------------------------
6.
El archivo cabecera Unit2.h ...
//--------------------------------------------------------------------------#ifndef Unit2H
#define Unit2H
//--------------------------------------------------------------------------#include <Classes.hpp>
//--------------------------------------------------------------------------class TRead : public TThread
{
private:
protected:
void __fastcall DisplayIt(void);
void __fastcall Execute();
public:
__fastcall TRead(bool CreateSuspended);
};
//--------------------------------------------------------------------------#endif
Para probar el ejemplo, puedes enlazar los pines 2 y 3 del RS-232, o bien, escribir algún comando
Hayes hacia el puerto del modem (un ATZ por ejemplo).
Descargar