Escolar Documentos
Profissional Documentos
Cultura Documentos
Septiembre de 2008 COMUNICACIÓN POR EL PUERTO SERIAL UTILIZANDO C++ BUILDER
AlterNEXT
Software Engineering
2. Añadir un nuevo objeto Thread (…File ‐> New...). Cuando
pregunte el nombre para la clase, llamarlo TRead.
Ahora se debería 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
E
Memo1 OnKeyPress
xiste un gran número de casos en que el software 4. El código de la Unit1.cpp ...
necesita emitir algún tipo de salida o resultado hacia el //‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
#include <vcl.h>
exterior del mismo hardware donde se ejecuta, o bien #pragma hdrstop
#include "Unit1.h"
necesita recibir algún tipo de entrada desde algún #include "Unit2.h" // CABECERA DE LA UNIT2 (THREAD)
// VARIABLES GLOBALES
dispositivo “externo”, y es bastante común que estos dispositivos HANDLE hComm = NULL;
externos estén conectados al hardware de computo donde se TRead *ReadThread;
COMMTIMEOUTS ctmoNew = {0}, ctmoOld;
ejecuta el programa (CPU) a través de una conexión por el Puerto
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
Serial, también conocida como interfaz RS‐232. #pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
En este artículo se expone una manera sencilla de conectarse al //‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
puerto serial y enviar o recibir señales utilizando el lenguaje de __fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
programación C++ Builder de CodeGear. Evidentemente este {
}
articulo está destinado a personas con conocimientos en
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
programación de sistemas y familiarizados con el entorno de void __fastcall TForm1::FormCreate(TObject *Sender)
desarrollo RAD Studio. Tomar en cuenta los siguientes puntos para {
Memo1‐>Clear();
mejor compresión del código expuesto: DCB dcbCommPort;
// ABRE EL PUERTO
// REEMPLAZAR "COM2" POR "COM1", "COM3", ETC. PARA ABRIR
// OTRO PUERTO
Los comentarios dados en este color verde son para hComm = CreateFile("COM2",
GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
entender el funcionamiento del ejemplo. // SI EL PUERTO NO PUEDE ABRIRSE ...
El texto escrito en color azul, es el que genera el IDE y no if(hComm == INVALID_HANDLE_VALUE)
Application‐>Terminate();
debemos volver a copiar. // ESTABLECEMOS LOS TIMEOUTS
GetCommTimeouts(hComm,&ctmoOld);
El código de color rojo, es el que debemos introducir para ctmoNew.ReadTotalTimeoutConstant = 100;
ctmoNew.ReadTotalTimeoutMultiplier = 0;
seguir el ejemplo. ctmoNew.WriteTotalTimeoutMultiplier = 0;
ctmoNew.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &ctmoNew);
// ESTABLECEMOS BAUD RATE, PARITY, WORD SIZE, Y STOP BITS.
El ejemplo consiste en un Form con un objeto Memo (para la // HAY OTROS METODOS DE HACER ESTO, PERO ESTE ES EL MAS FACIL
entrada/salida de texto) y un objeto Thread. dcbCommPort.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcbCommPort);
BuildCommDCB("9600,N,8,1", &dcbCommPort);
SetCommState(hComm, &dcbCommPort);
Se empieza con un nuevo proyecto, donde situaremos un Memo // ACTIVAMOS EL THREAD
ReadThread = new TRead(false);
en el Form1. }
Página 1 Álvaro Pinto Torrejón
http://www.alternext.com.bo apinto@alternext.com.bo
Nº 2. Septiembre de 2008 COMUNICACIÓN POR EL PUERTO SERIAL UTILIZANDO C++ BUILDER
AlterNEXT
Software Engineering
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
6. El archivo cabecera Unit2.h ...
{
// TERMINAMOS EL THREAD. //‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
ReadThread‐>Terminate(); #ifndef Unit2H
// ESPERAMOS QUE TERMINE Y CERRAMOS EL PUERTO #define Unit2H
Sleep(250);
PurgeComm(hComm, PURGE_RXABORT); //‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
SetCommTimeouts(hComm, &ctmoOld); #include <Classes.hpp>
CloseHandle(hComm);
} //‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
class TRead : public TThread
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ {
void __fastcall TForm1::Memo1KeyPress(TObject *Sender, char &Key) private:
{ protected:
// TRANSMITE CUALQUIER COSA ESCRITA EN EL MEMO void __fastcall DisplayIt(void);
TransmitCommChar(hComm, Key); void __fastcall Execute();
// ESTO PREVEE LA VISUALIZACION DE CARACTERES “BASURA” EN LA PANTALLA public:
if(Key != 13 && (Key < ' ' || Key > 'z')) __fastcall TRead(bool CreateSuspended);
Key = 0; };
} //‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
#endif
5. El código fuente de la Unit2.cpp...
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
#include <vcl.h> Para probar el ejemplo, se puede enlazar los pines 2 y 3 del RS‐
#pragma hdrstop
// SE DEBE INCLUIR LA CABECERA DE LA UNIT1
232, o bien, escribir algún comando Hayes hacia el puerto del
#include "Unit1.h" modem (un ATZ por ejemplo).
#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);
}
}
}
//‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
Página 2 Álvaro Pinto Torrejón
http://www.alternext.com.bo apinto@alternext.com.bo