Práctica programación cliente-servidor RS232.pdf

download Práctica programación cliente-servidor RS232.pdf

of 14

Transcript of Práctica programación cliente-servidor RS232.pdf

  • ndice general

    2. Programacin RS-232 en C 2

    2.1. Objetivos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

    2.2. Librera Serie utilizada. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

    2.2.1. Funcin OpenSerialPort. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

    2.2.2. Funcin SerialSendByte. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

    2.2.3. Funcin SerialReceiveByte. . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

    2.2.4. Funcin CloseSerialPort. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

    2.3. Ejemplos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

    2.3.1. Envo y recepcin de un byte y un float. . . . . . . . . . . . . . . . . . . . 6

    2.3.2. Envo y recepcin de vectores y struct. . . . . . . . . . . . . . . . . . . . . 9

    1

  • 2Programacin RS-232 en C

    2.1. Objetivos.

    El sistema operativo Windows tiene la librera para la programacin del puerto serie RS-232. Para utilizar dicha librera hay que incluir en los programas en C el fichero de cabecera windows.h mediante la directiva de preprocesamiento #include. La librera que se va a utilizar en prcticas es la librera serie (serie.h). Est basada en las funciones originales de windows.h. Al final de la prctica el alumno debe ser capaz de:

    1. Programar en C la comunicacin RS-232 utilizando la librera de serie.h.

    2. Enviar informacin entre aplicaciones C de diferente tipo: byte, float, vectores y es-tructuras.

    2.2. Librera Serie utilizada.

    Como se ha dicho anteriormente, se va a utilizar una librera serie en concreto (serie.h).Esta librera permite realizar transferencias byte a byte o de ficheros, opcin esta ltima queno se estudiar. Tambin, en las funciones originales de windows.h, se pueden hacer otrotipo de transferencias que no se estudiarn. Las 4 funciones a utilizar son las siguientes:

    1. Abrir un puerto serie: Captura el puerto para realizar el intercambio de informacin atravs de l. Slo lo puede tener una aplicacin simultneamente.

    2. Transferir un byte por un puerto: Enva un byte por el puerto.

    3. Obtener un byte por un puerto: Recibe un byte por un puerto.

    2

  • 2.2. Librera Serie utilizada. |3|

    4. Cerrar un puerto serie: Liberar un puerto. Es muy importante terminar los programasimplementados correctamente, ya que es necesario liberar el puerto para que otraaplicacin lo capture de nuevo.

    A continuacin se detallar el funcionamiento de las funciones.

    2.2.1. Funcin OpenSerialPort.

    La funcin para abrir un puerto es OpenSerialPort y tiene la siguiente estructura:

    // Abre el puerto serieHANDLE OpenSerialPort(

    char *psPort, // "COM1","COM2"DWORD bBaudRate, // CBR_9600, CBR_19200. CBR_56000BYTE bByteSize, // 7,8BYTE bParity, // NOPARITY, EVENPARITY, ODDPARITYBYTE bStopBits, // ONESTOPBIT, ONE5STOPBITS, TWOSTOPBITSDWORD ReadTimeout // Programmable Read Timeout

    );

    Los parmetros son:

    psPort: Indica que puerto es el que se desea abrir. Es una cadena del tipo COM1, COM2,. . ., COM9. Valores con ms de un dgito en la identificacin han dado problemas enlas pruebas de la librera serie.

    bBaudRate: Tasa de transferencia de baudios. Las etiquetas a usar sern: CBR_9600,CBR_19200, CBR_56000, etc. En las prcticas siempre se usar 9600 baudios.

    bByteSize: Nmero de bits transmitidos. Las posibilidades son 7 u 8 (en realidad entre 5 y8, este caso no lo he probado). En las prcticas se utilizarn 8 bits, es decir, un byte.

    bParity: Paridad utilizada para la deteccin de errores. Las posibles etiquetas son NOPA-RITY, EVENPARITY y ODDPARITY. En las prcticas no se utilizar comprobacin deparidad, etiqueta NOPARITY.

    bStopBits: Nmero de bits de stop. Los posibles valores son ONESTOPBIT, ONE5STOPBITSy TWOSTOPBITS. En las prcticas se utilizar un bit de stop (ONESTOPBIT ).

    ReadTimeout: La librera permite definir un timeout que indica el tiempo que se esperarpara que se lea/escriba un valor. En nuestro caso no se definir timeout, se pasar unvalor FALSE.

    Como puede verse, esta funcin devuelve un valor de tipo HANDLE. Este tipo puede serdefinido como un manejador, y es el identificador del puerto que se usa dentro del pro-grama C. En el resto de las funciones, las operaciones sobre el puerto se definen utilizandodicho manejador (a partir de ahora ser denominado HANDLE).

    Un ejemplo de invocacin de esta funcin sobre el puerto COM8 es:

  • 2.2. Librera Serie utilizada. |4|

    HANDLE hPort; // HANDLE para manejar el puertoBOOL timeout = FALSE; // No se usa el timeout// hPort es asignado al HANDLE devuelto por OpenSerialPorthPort = OpenSerialPort("COM8",CBR_9600,8,NOPARITY,ONESTOPBIT,timeout);

    2.2.2. Funcin SerialSendByte.

    La funcin para enviar un byte por un puerto es SerialSendByte y tiene la siguienteestructura:

    // Transferencia de un BYTE, el del parametro byteBOOL SerialSendByte(HANDLE hPort, BYTE byte);// Devuelve TRUE si todo correcto

    Los parmetros son:

    hPort: Es el HANDLE sobre el que se transmite, previamente hay que haberlo inicializadocon la funcin OpenSerialPort.

    byte: Es el byte a transferir.

    Esta funcin devuelve un valor del tipo BOOL, TRUE si todo ha ido correctamente yFALSE en caso contrario.

    Este ejemplo muestra cmo enviar un BYTE (el valor 2 como carcter, su cdigo ASCII)por un puerto:

    HANDLE hPort;BOOL bRes;BYTE opc;

    // Primero se debe colocar la apertura de puerto y otras acciones previasopc = 2;// envio de variable opcbRes = SerialSendByte(hPort,opc);

    El siguiente ejemplo muestra cmo enviar un valor float, BYTE a BYTE, utilizando lafuncin SerialSendByte:

    HANDLE hPort;BOOL bRes;BYTE *v;float f;int i;// Primero se debe colocar la apertura de puerto y otras acciones previasv = (BYTE *) &f;f = 23.45;for(i=0; i

  • 2.2. Librera Serie utilizada. |5|

    La idea consiste en que, dado que un float tiene sizeof(float) bytes (usualmente 4 bytes),se utiliza un puntero de tipo BYTE que permite enviar byte a byte los bits del float. Entonces,en el ejemplo, para enviar un float se utiliza el puntero v (de tipo BYTE) que apunta al float,y posteriormente se enva el float como 4 (sizeof(float)) envos de 1 byte utilizando el punterov (ver bucle en el ejemplo).

    2.2.3. Funcin SerialReceiveByte.

    La funcin para recibir un byte por un puerto es OpenSerialPort y tiene la siguienteestructura:

    // Recibe un byte en pbyteBOOL SerialReceiveByte(HANDLE hPort, BYTE *pbyte, BOOL *pTimeout);// Si recibe OK devuelve TRUE & pTimeout a TRUE// Si error al recibir devuelve FALSE

    Los parmetros son:

    hPort: Es el HANDLE del puerto por el que se recibe el byte, previamente hay que haberloinicializado con la funcin OpenSerialPort.

    pbyte: Es un puntero a donde se desea que se copie el byte recibido (paso por referencia).

    pTimeout: Se utiliza para que la funcin devuelva si ha ocurrido un timeout.

    Esta funcin devuelve un valor del tipo BOOL, TRUE si todo ha ido correctamente yFALSE en caso contrario.

    El siguiente ejemplo muestra cmo recibir un byte por un puerto:

    BOOL timeout = FALSE, bRes;HANDLE hPort;BYTE byte;// Primero se debe colocar la apertura de puerto y otras acciones previas// se recibe el byte en la variable byte por referenciabRes = SerialReceiveByte(hPort,&byte,&timeout);printf("Valor recibido = %d\n", byte);

    El siguiente ejemplo muestra cmo recibir un valor float utilizando la funcin SerialRe-ceiveByte que solamente recibe un byte.

    HANDLE hPort;BOOL timeout = FALSE, bRes;BYTE *v;float f;int i;// Primero se debe colocar la apertura de puerto y otras acciones previasv = (BYTE *) &f; // El puntero v apunta al float f// Realiza el bucle tantas veces como bytes tiene un float

  • 2.3. Ejemplos. |6|

    for(i=0; i

  • 2.3. Ejemplos. |7|

    Programa Cliente

    #include "serie.h"#include "windows.h"#include "stdio.h"int main(){

    HANDLE hPort;BOOL bRes, timeout=FALSE;BYTE opc, *v;int i;float f;

    // Se leera una zona como un grupo de 4 (sizeof(float)) bytes// o como float, segun interesev = (BYTE *) &f;hPort=OpenSerialPort("COM8",CBR_9600,8,NOPARITY,ONESTOPBIT,0);if (hPort==INVALID_HANDLE_VALUE) {

    printf("Error abriendo puerto COM8");return 1;

    }while(opc!=0){

    printf("0) Salir\n");printf("1) Incrementar real\n");printf("2) Decrementar real\n");scanf("%c", &opc);getchar();if (opc==0) {

    // envio de peticion de serviciobRes = SerialSendByte(hPort,opc);

    } else {if ((opc==1) || (opc==2)) {

    // envio de peticion de serviciobRes = SerialSendByte(hPort,opc);// lectura de resultado// Realiza el bucle tantas veces como bytes tiene un floatfor(i=0; i

  • 2.3. Ejemplos. |8|

    Programa Servidor

    #include "serie.h"#include "windows.h"#include "stdio.h"int main(){

    HANDLE hPort, timeout = FALSE;BOOL bRes;BYTE byte = a, *v;int i;float valor;

    // Se leera una zona como un grupo de 4 (sizeof(float)) bytes// o como float, segun interesev = (BYTE *) &valor;hPort=OpenSerialPort("COM9",CBR_9600,8,NOPARITY,ONESTOPBIT,0);if (hPort==INVALID_HANDLE_VALUE) {

    printf("Error abriendo puerto COM9");return 1;

    }valor = 0;printf("SERVIDOR DE MANEJO DE FLOAT\n");while (byte!=0) {

    // lectura de serviciobRes = SerialReceiveByte(hPort,&byte,&timeout);if ((byte==1) || (byte==2)) {

    printf("Peticion de servicio %c. ", byte);// realizacion de accionswitch(byte) {

    case 1:valor = valor + 0.1;break;

    case 2:valor = valor - 0.1;break;

    }printf("Valor variable float = %f\n", valor);for(i=0; i

  • 2.3. Ejemplos. |9|

    2.3.2. Envo y recepcin de vectores y struct.

    En este ejemplo se mostrar el envo y recepcin de vectores y estructuras. El servidoratiende peticiones para manejar la siguiente estructura mediante un mdulo software:

    struct operadores {int a;int b;float result;

    };

    Los atributos a y b son dos enteros que podrn ser asignados mediante sendas peticiones.El atributo result tomar el valor segn la peticin recibida: mximo de a o b, mnimo de a ob, o media de a o b. Las posibles actuaciones sobre la estructura son:

    1. Asignar atributo a.

    2. Asignar atributo b.

    3. Asignar atributo result con el mnimo de a o b.

    4. Asignar atributo result con el mximo de a o b.

    5. Asignar atributo result con la media de a o b.

    6. Devolver al cliente el valor del campo result.

    7. Devolver al cliente la estructura completa.

    Figura 2.1: Mensajera del ejemplo.

    La Figura 2.1 muestra cmo funciona la mensajera entre cliente y servidor. Para lacomunicacin de las peticiones del cliente al servidor se utiliza un vector de enteros detamao 2, donde cada componente toma los siguientes valores:

    v[0]: Un valor comprendido entre 1 y 7 que representa la peticin.

    v[1]: Valor del parmetro de la peticin si es necesario. Este parmetro slo se utilizaen las peticiones 1 y 2 para indicar el valor a asignar en a o b respectivamente.

  • 2.3. Ejemplos. |10|

    Respecto a las respuestas del servidor en base a la peticin pedida el servidor slo deberesponder a 2 de las 7 peticiones. En la peticin 6 devuelve un float al cliente que es el valordel atributo result de la estructura, mientras que en la peticin 7 devuelve la estructuracompleta.

    Programa Cliente

    #include "serie.h"#include "windows.h"#include "stdio.h"struct operadores {

    int a;int b;float result;

    };int main(){

    HANDLE hPort;BOOL bRes, timeout=FALSE;int i, vector[2]; // servicio en posicion 0 y parametro en posicion 1BYTE *v, *r;float f;struct operadores estruc;

    v = (BYTE *) vector; // v lee y escribe el vector de byte en byte

    hPort=OpenSerialPort("COM8",CBR_9600,8,NOPARITY,ONESTOPBIT,5000);if (hPort==INVALID_HANDLE_VALUE) {

    printf("Error abriendo puerto COM8");return 1;

    }vector[0] = -1; // distinto de 0printf("CLIENTE\n");while(vector[0]!=0){

    printf("\n0) Salir\n")printf("1) Asignar A\n");printf("2) Asignar B\n");printf("3) Minimo\n");printf("4) Maximo\n");printf("5) Media\n");printf("6) Recibir float resultado\n");printf("7) Recibir struct completo\n");vector[1] = -1; // no parametro// Leer peticion en v[0]scanf("%d", &vector[0]);getchar();if ((vector[0]>=0) && (vector[0]

  • 2.3. Ejemplos. |11|

    for(i=0; i

  • 2.3. Ejemplos. |12|

    printf("Error abriendo puerto COM9");return 1;

    }

    vector[0] = -1; // distinto de 0 para entrar en whileprintf("SERVIDOR\n\n");while (vector[0]!=0) {// lectura de serviciofor(i=0; i=0) && (vector[0]

  • 2.3. Ejemplos. |13|

    return 1;}

    } // fin del if ((vector[0]>=0) ...} // fin del while// MUY IMPORTANTE: cerrar el puertoCloseSerialPort(hPort);

    }