Hay muchisimos dispositivos que emplean una conexion serie RS-232 para transmitir datos. Incluso aunque aparenten que no disponen de esta conexion es muy posible que utilicen un "puerto serie virtual" emulado sobre otro tipo de conexion (USB, Bluetooth, Infrarrojos, etc.), permitiendonos acceder facilmente a moviles, GPS, sistemas de adquisicion de datos industriales, etc.
Recurriendo a la tecnologia de componetes software, se puede sacar el máximo partido a una conexion serie sin necesidad de conocimientos de programación avanzados. Borland C++ Builder (BCB) no incluye un componente para el uso de puerto serie, pero se puede instalar uno recurriendo a los muchos disponibles en la red.
Si se tiene instalado Visual Basic, se puede usar su componente serie desde BCB, pero, por experiencia, es bastante malo y da muchos problemas. Hay muchisimos mas componentes en internet disponibles para este cometido, pero si hay uno libre ¿porque pagar por uno malo?.
En esta pagina se propone usar el componente gratuito ComPort para acceder a prácticamente todas las características del puerto serie. La pega: cuesta un poquito mas instalarlo.
El componente se descarga en codigo fuente y hay que compilarlo. Para facilitar la tarea, en el siguiente enlace se ha precompilado y esta listo para instalar y usar.
Descargar ComPort 3.0 precompilado. (No es la ultima version. Un dia de estos probare la ultima y lo actualizare).
Los pasos para instalarlos son:
Meter los archivos en un directorio, preferiblemente donde esté Builder.
Entra c:\Archivos de Programa\Borland\CBuilder6
Crea el directorio "comport"
Descomprime los ficheros dentro
Copiar las librerías a algún directorio de busqueda de windows.
Seleccional los fichero *.bpl, *.lib y *.bpi
Copialos en c:\windows\system (quidado con no "moverlos")
Configurar el entorno Builder para que encuentre los ficheros de cabecera.
Arranca Builder
Elige "File"->"Close All"
Ve a "Tools"->"Environment options"->"Library"->"Library path" y añade ";$(BCB)\comport" a la lista
Ve a "Project"->"Options"->"Directories" y añade lo mismo a "Include path" y a "Library path"
Cierra Builder
Importa el paquete comport a la paleta
Arranca Builder de nuevo
Elige "File"->"Close All"
Ve a "Component"->"Install Packages"->"Add (sección Design packages)", ir al directorio de "comport" y elegir "DsgnCPortCB6.bpl"
Aceptar todo
Comprobar que ha salido en la paleta la pestaña "CPortLib" en la barra de componentes, debería estar al final de la barra
Cierra builder sin guardar nada
En el directorio "comport" está el fichero de ayuda con la descripción de la funciones del componente.
Para hacerse una idea de su funcionalidad, supóngase el objeto ComPort1 instancia de la clase TComPort (es decir, hemos arrastrado el componente al formulario y ahora tenemos acceso a el), establecer la configuración del puerto podría ser:
//ComPort1->Port = "COM2"; // usar com2 ComPort1->BaudRate = br9600; // velocidad 9600 ComPort1->DataBits = dbSeven; // bits de datos ComPort1->Parity->Bits = prOdd; // paridad impar ComPort1->StopBits = sbTwoStopBits; // dos bits de stop ComPort1->ShowSetupDialog(); // con esto sale un dialogo y elegimos el com que queremos
Antes de "usar" el puerto hay que "abrirlo". Se debe "cerrar" si se deja de usar o se quiere cambiar la configuración. Este mecanismo permite al S.O. proporcionar a una tarea el uso exclusivo de un puerto.
ComPort1->Open(); // intentar abrir el puerto if (ComPort1->Connected == false) { ShowMessage("Problemas abriendo el puerto serie"); }
Ahora ya se puede enviar algo al puerto. Por ejemplo, se puede enviar cualquier secuencia de datos,
unsigned char datos[]={54,97,10,234}; ... ComPort1->Write (datos, 4);
Y la secuencia 54, 97, 10, 234 se envía por el serie. En el caso de que la configuración del puerto no admita la totalidad de bits del dato, entonces los bits más significativos son descartados. Por ejemplo, si elegimos 6 bits de datos, se descartan los 2 bits de mayor peso de cada dato. Es importante destacar que el programa no espera a que se haya enviado la información físicamente por el cable. Ésta es colocada en un "buffer" y es el S.O. el encargado de ir enviándolo mediante el mecanismo de interrupciones. Así se consigue que nuestro programa continúe haciendo otras tareas.
Para obtener en una variable la información recibida por el canal serie se podría hacer:
char buffer[1000]; int num_datos; num_datos = ComPort1->Read(buffer, 10);
que indica que se saquen 10 datos del tampón de entrada. Si al llamar a la funcion no estan disponibles 10 datos, entonces se esperar a que lo esten.
Es muy habitual que lo enviado por el canal serie sean datos correspondientes a cadenas de caracteres, por lo que se suele facilitar el envío y recepción de caracteres. Por ejemplo, se puede usar la siguiente sintaxis,
ComPort1 -> WriteStr("Hola");
y la secuencia ´H´, ´o´, ´l´,´a´, se envía por el serie.
Para obtener en una variable de cadena la información recibida por el canal serie se podría hacer:
AnsiString a; int num_datos; num_datos = ComPort1 -> ReadStr(a,10);
En realidad no existe diferencia alguna entre enviar/recibir caracteres y datos, pues se trata en los dos casos de datos binarios de n bits.
La mejor forma de "recibir" información sin utilizar técnicas de encuesta (polling) que desperdicien el tiempo de la CPU es aprovechar el evento OnRxChar, que se genera cuando han llegado datos por el puerto serie.
... OnRxChar (TObject Sender, int Count) { ... ComPort1->ReadStr(Label1 -> Caption, Count); }
Esta versión precompilada tiene un fallo, la función propiedad "Port" no funciona. Se deberá usar "ShowSetupDialog".
El siguiente enunciado de una practica de la asignatura Diseño de Sistemas Informaticos Industriales puede ayudar a entender lo anterior mejor.