Autor Tema: Puerto serie en C  (Leído 25824 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado exque

  • PIC10
  • *
  • Mensajes: 10
Puerto serie en C
« en: 23 de Abril de 2008, 06:46:10 »
Hola a todos! He encontrado un código para poder enviar y recibir datos desde el puerto serie. Tengo conectado el srf08 en el COM2 y con este código quedría enviar los comandos para que hagas las medidas y recibir los datos.
Este es el código:
Código: [Seleccionar]
// Librerías
#include <iostream.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <windows.h>

// Tipo de datos:
typedef struct
{
    char Puerto[5];
    int Baudios;
    int BitsDatos;
    int BitsStop;
    char Paridad[25];
} tipoOpciones;

// Variables globales:
tipoOpciones Ops;           // Opciones
HGLOBAL hCadena, hSalida;   // Buffers
char *cad, *sal;
DCB dcb;                    // Puerto Serie
HANDLE idComDev;
bool Comunicacion;
HANDLE hHilo;               // Hilo del puerto serie

// Prototipos:
void IniciarBuffers();
void LiberarBuffers();
bool InicioComunicacion(void);
bool FinComunicacion(void);
DWORD Hilo(LPDWORD lpdwParam);
void LeeSerie();
void EscribirSerie (char *buf);

// Programa:
int main (int argc, char *argv[])
{
    bool salir=false;
    DWORD param, id;
   
    //Inicializar opciones del puerto serie:
    strcpy (Ops.Puerto, "COM2");
    Ops.Baudios = 9600;
    Ops.BitsDatos = 8;
    Ops.BitsStop = 1;
    strcpy (Ops.Paridad, "Sin paridad");
   
    // Inicialización Buffers:
    IniciarBuffers();
    // No se ha establecido comunicación:
    Comunicacion = false;
    if(!InicioComunicacion())
    {
        cout << "Inicializacion puerto serie" << endl;
        cout << "ERROR: No se puede acceder al puerto serie." << endl;
        LiberarBuffers();
        system("PAUSE");
        return 1;
    }
    else cout <<"Inicializacion puerto serie.....Correcto" << endl << endl;
   
    // Lanzar hilo de lectura del puerto serie:
    hHilo = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE)Hilo, &param, 0, &id);
    if(!hHilo) cout << "ERROR" << endl;
    else cout << "- Hilo de lectura lanzado." << endl << endl;
           
    // Bucle principal:
    while (!salir)
    {
    // Leer un comando:
            cin.getline (cad, 80);
            // Si es "salir", abandonar el bucle:
            if(!strcmp (cad, "salir")) salir = true;
            else
            {
                // Si no, enviar cadena por el puerto serie:
                strcat (cad, "\r");
                EscribirSerie (cad);
            }
    }
       
    // Liberar Hilo:
    CloseHandle (hHilo);
   
    // Liberar puerto serie:
    FinComunicacion();
    LiberarBuffers();
    system("PAUSE");
    return 0;
    }

// Reservar memoria global para buffers del puerto serie:
void IniciarBuffers()
{
    hCadena = GlobalAlloc (GMEM_MOVEABLE, 4096);
    hSalida = GlobalAlloc (GMEM_MOVEABLE, 4096);
    cad = (char *) GlobalLock (hCadena);
    sal = (char *) GlobalLock (hSalida);
}

// Liberar memoria global de buffers del puerto serie:
void LiberarBuffers()
{
    GlobalUnlock (hCadena);
    GlobalUnlock (hSalida);
    GlobalFree (hCadena);
    GlobalFree (hSalida);
}

// Iniciar el puerto serie:
bool InicioComunicacion(void)
{
    bool fSuccess;
   
    // Abrir el fichero asociado al puerto:
    idComDev = CreateFile (Ops.Puerto, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    if(idComDev == INVALID_HANDLE_VALUE)
    {
        cout << "ERROR: CreateFile. Inicializacion puerto serie" << endl;
        system("PAUSE");
        return false;
    }
    else cout << "CreateFile.....Correcto" << endl << endl;
   
    // Leer estructura de control del puerto serie, cdb:
    fSuccess = GetCommState (idComDev, &dcb);
    if(!fSuccess)
    {
        cout << "ERROR: GetCommState. Inicializacion puerto serie" << endl;
        system("PAUSE");
        return false;
    }
    else cout << "GetCommState.....Correcto" << endl << endl;
   
    // Modificar el dcb según las opciones definidas:
    dcb.BaudRate = Ops.Baudios;
    dcb.ByteSize = Ops.BitsDatos;
   
    if(!strcmp(Ops.Paridad, "Sin paridad")) dcb.Parity = NOPARITY;
    if(!strcmp(Ops.Paridad, "Paridad par")) dcb.Parity = EVENPARITY;
    if(!strcmp(Ops.Paridad, "Paridad impar")) dcb.Parity = ODDPARITY;
   
    switch (Ops.BitsStop)
    {
        case (1):
            dcb.StopBits = ONESTOPBIT;
            break;
        case (2):
            dcb.StopBits = TWOSTOPBITS;
            break;
    }
   
    // Modificar la estructura de control del puerto serie:
    fSuccess = SetCommState (idComDev, &dcb);
    if(!fSuccess)
    {
        cout << "ERROR: SetCommStatus. Inicializacion puerto serie" << endl;
        system("PAUSE");
        return false;
    }
    else cout << "SetCommStatus.....Correcto" << endl << endl;
       
    // Especifica que queremos monitorizar la recepción de datos:
    if(!SetCommMask (idComDev, EV_RXCHAR))
    {
        cout << "No se pudo activar el evento de lectura." << endl;
        system("PAUSE");
        return false;
    }
    else cout << "- Se ha activado el evento de lectura." << endl << endl;
   
    // Comunicación establecida:
    Comunicacion = true;
    return true;
}
// Finalizar comunicación por puerto serie:
bool FinComunicacion (void)
{
    // Liberar máscara de eventos del puerto serie:
    SetCommMask (idComDev, 0);
   
    // Cerrar el puerto serie:
    CloseHandle (idComDev);
    // Comunicación interrumpida:
    Comunicacion = false;
    return true;
}

// Hilo de escucha del puerto serie:
DWORD Hilo (LPDWORD lpdwParam)
{
    DWORD dwEvtMask;
    do
    {
        if(WaitCommEvent(idComDev, &dwEvtMask, NULL))
            if(dwEvtMask & EV_RXCHAR) LeeSerie();
    }
    while (true);
    return 0;
}

// Leer datos del puerto serie:
void LeeSerie()
{
    DWORD x;
    COMSTAT cs;
   
    // Actualizar COMSTAT; sirve para averiguar el número de bytes en el buffer de entrada:
    ClearCommError (idComDev, &x, &cs);
    // Leer cs.cbInQue caracteres:
    ReadFile (idComDev, cad, cs.cbInQue, &x, NULL);
    // Actualizar el fin de cadena:
    cad[x] = 0;
    // Mostrar caracteres leídos:
    cout << cad;
    return;
}

void EscribirSerie (char *buf)
{
    char Buffer[1024];
    DWORD n, l, p, err;
   
    strcpy (Buffer, buf);
    l = strlen (Buffer);
    p = 0;
    while (1)
    {
        if (!WriteFile (idComDev, &Buffer[p], l-p, &n, NULL))
        {
            err = GetLastError();
            if(err != ERROR_IO_PENDING)
            {
                Comunicacion = false;
                return;
            }
        }
        l -= n;
        p += n;
    }
}


Lo compila bien, sin errores. El fallo está que cuando ejecuta sale todo correcto hasta el hilo ha sido lanzado..entonces ahí se queda bloqueado, no muestra nada más y no puedo escribir ni nada..a ver si alguien me puede hechar una mano para poder enviarle los ocmandos y recibir los datos del sensor. Gracias

Desconectado sander

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 627
Re: Puerto serie en C
« Respuesta #1 en: 23 de Abril de 2008, 10:43:28 »
En que sistema operativo estas probando?


Saludos
La electrónica es el arte de manipular señales eléctricas que transportan información
Jan Davidse

Visita mi blog
Visita mi canal de youtube

Desconectado exque

  • PIC10
  • *
  • Mensajes: 10
Re: Puerto serie en C
« Respuesta #2 en: 24 de Abril de 2008, 04:56:38 »
en windows xp

Desconectado sergis

  • PIC10
  • *
  • Mensajes: 1
Re: Puerto serie en C
« Respuesta #3 en: 28 de Mayo de 2008, 00:31:36 »
Hostia tio, me has salvado la vida , he pasado horas buscando en la web pero al fin he conseguido la solucion, me ha servido muy bien, venga gracias....

Desconectado Lenbinary

  • PIC10
  • *
  • Mensajes: 6
Re: Puerto serie en C
« Respuesta #4 en: 21 de Septiembre de 2009, 07:42:33 »
Buenas a todos. Este es mi primer post en el foro y respondo para aclarar que este software no sirve para WinXp. Lo he probado en un equipo con Win98 y si funciona. Es más, me gustaría comprobar  (pero no me he es posible porque no tengo dos ordenadores con win98) que la comunicación es posible, pero WinXp se queda colgado. He intentado adquirir carácteres a través del hyperterminal pero no he conseguido ningún resultado.

Un saludo

Desconectado tsk

  • PIC18
  • ****
  • Mensajes: 258
Re: Puerto serie en C
« Respuesta #5 en: 21 de Septiembre de 2009, 16:42:07 »
Porque no pruebas las librerías LnxComm son muy fáciles de usar y funcionan tanto en Windows como en Linux

Desconectado RB2000

  • PIC10
  • *
  • Mensajes: 18
Re: Puerto serie en C
« Respuesta #6 en: 26 de Septiembre de 2009, 02:00:01 »
Me queda una duda, está escrito en C o en C++?. Gracias.