Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Meta

#551
Cita de: controlado en 17 Noviembre 2015, 21:05 PM
Tambien como opcion podria ser labview su pogramacion es por diagrama de bloques por lo tano es muy facil, compañero ideal de aduino que integra compilacion en exe modulo de rs232(para el arduino) tengo 2012 sp1

Cuando acabe todo lo que tenga que acabar, le meteré mano. Hace un tiempo ya acabé la parte de leer entradas digitales.

https://foro.elhacker.net/electronica/tutorial_lecturas_de_entradas_digitales_con_arduino_y_visual_studio_net_2015-t448563.0.html

Saludos.
#552


Presento tutorial sobre entrada de datos digitales por puerto serie con Arduino controlado por tu propia interfaz hecho bajo Visual Studio .net

Ver enlace.

Ver vídeos.
Vídeo 1.

Vídeo 2.

Ahora me toca seguir con entradas y salidas analógicas.

Para recordar, ya hubo tutorial sobre controlar un Led.

Más tutoriales que puedes ver aquí.

Saludos.
#553
Me respondo a  mi mismo.

Código (csharp) [Seleccionar]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Threading; // No olvidar.

namespace Texto_consola_CS
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WindowWidth = 80;
            Console.WindowHeight = 43;

            Console.Title = "Título del programa en la ventana de la consola.";

            Console.BackgroundColor = ConsoleColor.Black; // Fondo pantalla blanco.
            Console.Clear(); // Limpiar pantalla.
            Console.ForegroundColor = ConsoleColor.Green; // Color texto azul.

            string Cadena = @"El hombre moderno es un viajero que ha olvidado el lugar de su destino, y que
ha de volver a donde viene para saber a donde va.

No busques al amigo para matar las horas, sino búscale con horas para vivir.

Los amigos se convierten con frecuencia en ladrones de nuestro tiempo.

Es difícil decir quién hace el mayor daño: los enemigos con sus peores intenciones o los amigos con las mejores.

Recorre a menudo la senda que lleva al huerto de tu amigo, no sea que la maleza te impida ver el camino.";

            Console.CursorVisible = true;

            foreach (char Letra in Cadena)
            {
                Console.Write(Letra);
                Console.Beep(500, 60);
            }
            Console.ReadKey(); // Pulse cualquier tecla para salir.
        }
    }
}


Saludos.
#554
Resuelto, me respondo a mi mismo.

En Visual C++ CLR se hace así:
Código (cpp) [Seleccionar]
array<Byte>^mBuffer = Encoding::ASCII->GetBytes("ACTUALIZAR"); // Envía comando ACTUALIZAR por el puerto.
serialPort1->Write(mBuffer, 0, mBuffer->Length);

Saludos.
#555
Hola:

Como en las películas de antes, no recuerdo en qué peli sale, un ordenador que al imprimir mensajes, se oye un ruido por cada letra muy rápido.

Hice lo de imprimir cada letra en 10 milisegundos, 0.010 segundos.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Threading; // No olvidar.

namespace Texto_consola_CS
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WindowWidth = 80;
            Console.WindowHeight = 43;

            Console.Title = "Título del programa en la ventana de la consola.";

            Console.BackgroundColor = ConsoleColor.Black; // Fondo pantalla blanco.
            Console.Clear(); // Limpiar pantalla.
            Console.ForegroundColor = ConsoleColor.Green; // Color texto azul.

            string Cadena = @"El hombre moderno es un viajero que ha olvidado el lugar de donde va, y que
ha de volver a donde viene para saber a donde va.

No busques al amigo para matar las horas, sino búscale con horas para vivir.

Los amigos se convierten con frecuencia en ladrones de nuestro tiempo.

Es difícil decir quién hace el mayor daño: los enemigos con sus peores intenciones o los amigos con las mejores.

Recorre a menudo la senda que lleva al huerto de tu amigo, no sea que la maleza te impida ver el camino.";

            Console.CursorVisible = true;

            foreach (char Letra in Cadena)
            {
                Console.Write(Letra);
                Thread.Sleep(2); //medio segundo
            }
            Console.Beep();
            Console.ReadKey(); // Pulse cualquier tecla para salir.
        }
    }
}


Al final de impresión de oye un beep. No encuentro un vídeo de ejemplo por ahora para que vean a lo que me refiero. Cuando el hombre habla con el ordenador en la película y le responde con mesajes que se oye el ruido por cada letra que escriba en pantalla.

Si alguien sabe como se hace, lo explican, no he encontrado nada igual por Internet, lo más parecido es esto.

https://msdn.microsoft.com/es-es/library/4fe3hdb1%28v=vs.110%29.aspx

Pero no es lo mismo.

Cualquier información es de ayuda.

Saludos.
#556
Hola:

En C# para enviar un byte al puerto serie uso esto.

private void button_t_Click(object sender, EventArgs e)
{
   byte[] mBuffer = new byte[1];
   mBuffer[0] = 0x74; //ASCII letter "t".
   serialPort1.Write(mBuffer, 0, mBuffer.Length);
}


En C++/CLR su código es este.


Para enviar de forma de cadena en C# se hace así:
private void button_b_Click(object sender, EventArgs e)
{
   byte[] mBuffer = Encoding.ASCII.GetBytes("Hello World");
   serialPort1.Write(mBuffer, 0, mBuffer.Length);
}


¿Cómo se hace en C++/CLR?

Saludos.
#557
.NET (C#, VB.NET, ASP) / Pasar de C# a C++ CLR.
8 Febrero 2016, 13:14 PM
Hola:

Tengo el código en C# de esta manera. Este código solo recibe datos por el puerto serie.
Código (csharp) [Seleccionar]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.IO.Ports; // No olvidar.
using System.Threading;

namespace Entrada_Arduino_AWF_1_CS
{
    public partial class Form1 : Form
    {
        // Utilizaremos un string como buffer de recepción.
        string Recibidos;

        public Form1()
        {
            InitializeComponent();

            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }

                serialPort1.DataReceived += new SerialDataReceivedEventHandler(Recepcion);
            }
        }

        // Al recibir datos.
        private void Recepcion(object sender, SerialDataReceivedEventArgs e)
        {
            // Acumula los caracteres recibidos a nuestro 'buffer' (string).
            Recibidos += serialPort1.ReadExisting();

            // Invocar o llamar al proceso de tramas.
            Invoke(new EventHandler(Actualizar));
        }

        // Procesar los datos recibidos en el bufer y extraer tramas completas.
        private void Actualizar(object sender, EventArgs e)
        {

            switch (Recibidos)
            {
                case "ON":
                    panel1.BackColor = Color.Green;
                    label_Lectura.Text = "Activado";
                    pictureBox_Dibujo.Image = Properties.Resources.Led_rojo_encendido;
                    Recibidos = "";
                    break;

                case "OFF":
                    panel1.BackColor = Color.Red;
                    label_Lectura.Text = "Desactivado";
                    pictureBox_Dibujo.Image = Properties.Resources.Led_rojo_apagado;
                    Recibidos = "";
                    break;
            }
        }

        // Cuando cierre la aplicación.
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort1.IsOpen) // ¿El puerto está abierto?
            {
                serialPort1.Close(); // Cerrar puerto.
            }
        }
    }
}


He intentado imigar el código de C# a C++/CLR. Pero que va.
Código (cpp) [Seleccionar]
#pragma once

namespace Entrada_Arduino_CPP_CLR_1 {

using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

using namespace System::IO::Ports; // No olvidar.

/// <summary>
/// Resumen de Form_Principal
/// </summary>
public ref class Form_Principal : public System::Windows::Forms::Form
{
// Utilizaremos un string como buffer de recepción.
String^ Recibidos;

public:
Form_Principal(void)
{
InitializeComponent();
//
//TODO: agregar código de constructor aquí
//

if (!serialPort1->IsOpen)
{
try
{
serialPort1->Open();
}
catch (Exception ^ex)
{
MessageBox::Show(ex->ToString());
}

serialPort1->DataReceived += new SerialDataReceivedEventHandler(Recepcion);
}
}

// Al recibir datos.
private void Recepcion(object sender, SerialDataReceivedEventArgs e)
{
// Acumula los caracteres recibidos a nuestro 'buffer' (string).
Recibidos += serialPort1->ReadExisting();

// Invocar o llamar al proceso de tramas.
Invoke(new EventHandler(Actualizar));
}

// Procesar los datos recibidos en el bufer y extraer tramas completas.
private void Actualizar(object sender, EventArgs e)
{

switch (Recibidos)
{
case "ON":
panel1->BackColor = Color::Green;
label_Lectura->Text = "Activado";
pictureBox_Dibujo->Image = Properties::Resources::Led_rojo_encendido;
Recibidos = "";
break;

case "OFF":
panel1->BackColor = Color::Red;
label_Lectura->Text = "Desactivado";
pictureBox_Dibujo->Image = Properties::Resources::Led_rojo_apagado;
Recibidos = "";
break;
}
}

protected:
/// <summary>
/// Limpiar los recursos que se estén usando.
/// </summary>
~Form_Principal()
{
if (components)
{
delete components;
}
}
private: System::Windows::Forms::Label^  label_titulo;
protected:
private: System::Windows::Forms::Panel^  panel1;
private: System::Windows::Forms::Label^  label_Lectura;
private: System::Windows::Forms::PictureBox^  pictureBox_Dibujo;
private: System::IO::Ports::SerialPort^  serialPort1;
private: System::Windows::Forms::Label^  label1;
private: System::ComponentModel::IContainer^  components;

private:
/// <summary>
/// Variable del diseñador necesaria.
/// </summary>


#pragma region Windows Form Designer generated code
/// <summary>
/// Método necesario para admitir el Diseñador. No se puede modificar
/// el contenido de este método con el editor de código.
/// </summary>
void InitializeComponent(void)
{
this->components = (gcnew System::ComponentModel::Container());
System::ComponentModel::ComponentResourceManager^  resources = (gcnew System::ComponentModel::ComponentResourceManager(Form_Principal::typeid));
this->label_titulo = (gcnew System::Windows::Forms::Label());
this->panel1 = (gcnew System::Windows::Forms::Panel());
this->label_Lectura = (gcnew System::Windows::Forms::Label());
this->pictureBox_Dibujo = (gcnew System::Windows::Forms::PictureBox());
this->serialPort1 = (gcnew System::IO::Ports::SerialPort(this->components));
this->label1 = (gcnew System::Windows::Forms::Label());
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->pictureBox_Dibujo))->BeginInit();
this->SuspendLayout();
//
// label_titulo
//
this->label_titulo->AutoSize = true;
this->label_titulo->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 36, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point,
static_cast<System::Byte>(0)));
this->label_titulo->Location = System::Drawing::Point(29, 26);
this->label_titulo->Name = L"label_titulo";
this->label_titulo->Size = System::Drawing::Size(382, 55);
this->label_titulo->TabIndex = 0;
this->label_titulo->Text = L"Visual C++ CLR";
//
// panel1
//
this->panel1->BorderStyle = System::Windows::Forms::BorderStyle::FixedSingle;
this->panel1->Location = System::Drawing::Point(23, 97);
this->panel1->Name = L"panel1";
this->panel1->Size = System::Drawing::Size(100, 100);
this->panel1->TabIndex = 1;
//
// label_Lectura
//
this->label_Lectura->AutoSize = true;
this->label_Lectura->Location = System::Drawing::Point(183, 138);
this->label_Lectura->Name = L"label_Lectura";
this->label_Lectura->Size = System::Drawing::Size(48, 13);
this->label_Lectura->TabIndex = 2;
this->label_Lectura->Text = L"Leyendo";
//
// pictureBox_Dibujo
//
this->pictureBox_Dibujo->Image = (cli::safe_cast<System::Drawing::Image^>(resources->GetObject(L"pictureBox_Dibujo.Image")));
this->pictureBox_Dibujo->Location = System::Drawing::Point(311, 97);
this->pictureBox_Dibujo->Name = L"pictureBox_Dibujo";
this->pictureBox_Dibujo->Size = System::Drawing::Size(100, 100);
this->pictureBox_Dibujo->SizeMode = System::Windows::Forms::PictureBoxSizeMode::StretchImage;
this->pictureBox_Dibujo->TabIndex = 3;
this->pictureBox_Dibujo->TabStop = false;
//
// serialPort1
//
this->serialPort1->BaudRate = 115200;
this->serialPort1->PortName = L"COM4";
this->serialPort1->StopBits = System::IO::Ports::StopBits::Two;
//
// label1
//
this->label1->AutoSize = true;
this->label1->Location = System::Drawing::Point(349, 200);
this->label1->Name = L"label1";
this->label1->Size = System::Drawing::Size(25, 13);
this->label1->TabIndex = 4;
this->label1->Text = L"Led";
//
// Form_Principal
//
this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
this->ClientSize = System::Drawing::Size(436, 262);
this->Controls->Add(this->label1);
this->Controls->Add(this->pictureBox_Dibujo);
this->Controls->Add(this->label_Lectura);
this->Controls->Add(this->panel1);
this->Controls->Add(this->label_titulo);
this->Name = L"Form_Principal";
this->StartPosition = System::Windows::Forms::FormStartPosition::CenterScreen;
this->Text = L"Electrónica PIC - C++ 2015";
(cli::safe_cast<System::ComponentModel::ISupportInitialize^>(this->pictureBox_Dibujo))->EndInit();
this->ResumeLayout(false);
this->PerformLayout();

}
#pragma endregion
};
}


¿Alguna ayuda?

Muchas gracias.
#558
Hola:

Me da otros errores indicado en el código de abajo.
Código (cpp,64,89,216) [Seleccionar]
#include <iostream>
#include <cstring>
#include <windows.h>
// No olvidar.
#include <tchar.h>
#include <conio.h>
#include <strsafe.h>

using namespace std;

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

bool ocupado;
// Prototipos:
HANDLE InicioComunicacion(tipoOpciones*);
bool FinComunicacion(HANDLE);
DWORD Hilo(LPDWORD lpdwParam);
void EscribirSerie(HANDLE, char *);

int main(int argc, char *argv[])
{

TCHAR szOldTitle[MAX_PATH];
   TCHAR szNewTitle[MAX_PATH];

   // Save current console title.

   if( GetConsoleTitle(szOldTitle, MAX_PATH) )
   {
      // Build new console title string.

      StringCchPrintf(szNewTitle, MAX_PATH, TEXT("TEST: %s"), szOldTitle);

      // Set console title to new title
      if( !SetConsoleTitle(szNewTitle) )
      {
         _tprintf(TEXT("SetConsoleTitle failed (%d)\n"), GetLastError());
         return 1;
      }
      else
      {
         _tprintf(TEXT("SetConsoleTitle succeeded.\n"));
      }
   }
   return 0;

    bool salir=false;
    DWORD id;
    char cad[80];
    tipoOpciones Ops;         // Opciones
    HANDLE idComDev;
    HANDLE hHilo;             // Hilo del puerto serie

    ocupado = true;
    // Inicializar opciones del puerto serie:
    strcpy(Ops.Puerto, "COM1");
    Ops.Baudios = 115200;
    Ops.BitsDatos = 8;
    Ops.BitsStop = 2;
    strcpy(Ops.Paridad, "Sin paridad");

    // No se ha establecido comunicación:
    idComDev = InicioComunicacion(&Ops);
    if(idComDev == INVALID_HANDLE_VALUE) {
        cout << "Inicialización puerto serie" << endl;
        cout << "ERROR: No se puede acceder al puerto serie." << endl;
        return 1;
    }
    // Lanzar hilo de lectura del puerto serie:
    hHilo = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Hilo, (LPDWORD)&idComDev, 0, &id);
    if(!hHilo) cout << "Error" << endl;
    // Bucle principal:
    ocupado = false;
    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(idComDev, cad);
        }
    }
    // Liberar hilo:
    CloseHandle(hHilo);
    // Liberar puerto serie:
    FinComunicacion(idComDev);
    return 0;
}

// Iniciar el puerto serie:
HANDLE InicioComunicacion(tipoOpciones *Ops)
{
    bool fSuccess;
    HANDLE idComDev;
    DCB dcb;                  // Puerto serie

    // 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. Inicialización puerto serie" << endl;
        return INVALID_HANDLE_VALUE;
    }
    PurgeComm(idComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

    // Leer estructura de control del puerto serie, cdb:
    fSuccess = GetCommState(idComDev, &dcb);
    if(!fSuccess) {
        cout << "ERROR: GetCommState. Inicialización puerto serie" << endl;
        // Cerrar el puerto, regresar con 0.
        CloseHandle(idComDev);
        return INVALID_HANDLE_VALUE;
    }

    // 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. Inicialización puerto serie" << endl;
        // Cerrar el puerto, regresar con 0.
        CloseHandle(idComDev);
        return INVALID_HANDLE_VALUE;
    }

    //// ASIGNAR TIMOUTS!!!

    return idComDev;
}

// Finalizar comunicación por puerto serie:
bool FinComunicacion(HANDLE idComDev)
{
    // Cerrar el puerto serie:
    CloseHandle(idComDev);
    return true;
}

// Hilo de escucha del puerto serie:
DWORD Hilo(LPDWORD lpdwParam)
{
    DWORD leidos;
    COMSTAT cs;
    char *cad;
    DWORD dwCommEvent;
    HANDLE idComDev = *((HANDLE*)lpdwParam);

    if(!SetCommMask(idComDev, EV_RXCHAR)) {
        cout << "Error al iniciar captura de evento" << endl;
        return 0;
    }
    do {
        if(WaitCommEvent(idComDev, &dwCommEvent, NULL)) {
            SetCommMask(idComDev, EV_RXCHAR);
            while(ocupado);
            ocupado = true;
            if(dwCommEvent & EV_RXCHAR) {
                ClearCommError(idComDev, &leidos, &cs);
                leidos=0;
                cout << "Detectados " << cs.cbInQue << " caracteres" << endl;
                /* Leer buffer desde puerto serie */
                if(cs.cbInQue) {
                    cad = new char[cs.cbInQue+3]; // Caracteres en buffer, más retorno de línea, más nulo
                    ReadFile(idComDev, cad, cs.cbInQue, &leidos, NULL);
                    cad[leidos] = '\n'; // Terminar cadena con salto de línea y nulo
                    cad[leidos+1] = '\r';
                    cad[leidos+2] = 0;
                    cout << cad;
                    delete[] cad;
                }
            } else {
                cout << "Evento: EV_BREAK o EV_ERR" << endl;
                 ClearCommBreak(idComDev);
            }
            ocupado = false;
        } else {
            cout << "Error en WaitCommEvent" << endl;
            ClearCommError(idComDev, NULL, NULL);
        }
        Sleep(10);
    } while(true);
    return 0;
}

void EscribirSerie(HANDLE idComDev, char *buf)
{
    char oBuffer[256];  /* Buffer de salida */
    DWORD iBytesWritten;

    iBytesWritten = 0;
    strcpy(oBuffer, buf);
    while(ocupado);
    ocupado = true;
    WriteFile(idComDev, oBuffer, strlen(oBuffer), &iBytesWritten, NULL);
    ocupado = false;
}


Línea 64.
Citar71   5   C:\Users\Usuario\Desktop\main.cpp   [Error] 'strcpy_instead_use_StringCbCopyA_or_StringCchCopyA' was not declared in this scope

Línea 89.
Citar89   13   C:\Users\Usuario\Desktop\main.cpp   [Error] 'strcat_instead_use_StringCbCatA_or_StringCchCatA' was not declared in this scope

Línea 216.
Citar216   5   C:\Users\Usuario\Desktop\main.cpp   [Error] 'strcpy_instead_use_StringCbCopyA_or_StringCchCopyA' was not declared in this scope
#559
Hola:

Lo traducí, lo que busco simplemente es esto.



Saludos.
#560
Gracias.

He intentado ponerlo en este código pero sale error en el Dev C++ 5.11.

Código (cpp) [Seleccionar]
#include <iostream>
#include <cstring>
#include <windows.h>
// No olvidar.
#include <tchar.h>
//#include <conio.h>
//#include <strsafe.h>

using namespace std;

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

bool ocupado;
// Prototipos:
HANDLE InicioComunicacion(tipoOpciones*);
bool FinComunicacion(HANDLE);
DWORD Hilo(LPDWORD lpdwParam);
void EscribirSerie(HANDLE, char *);

int main(int argc, char *argv[])
{

TCHAR szOldTitle[MAX_PATH];
   TCHAR szNewTitle[MAX_PATH];

   // Save current console title.

   if( GetConsoleTitle(szOldTitle, MAX_PATH) )
   {
      // Build new console title string.

      StringCchPrintf(szNewTitle, MAX_PATH, TEXT("TEST: %s"), szOldTitle);

      // Set console title to new title
      if( !SetConsoleTitle(szNewTitle) )
      {
         _tprintf(TEXT("SetConsoleTitle failed (%d)\n"), GetLastError());
         return 1;
      }
      else
      {
         _tprintf(TEXT("SetConsoleTitle succeeded.\n"));
      }
   }
   return 0;

    bool salir=false;
    DWORD id;
    char cad[80];
    tipoOpciones Ops;         // Opciones
    HANDLE idComDev;
    HANDLE hHilo;             // Hilo del puerto serie

    ocupado = true;
    // Inicializar opciones del puerto serie:
    strcpy(Ops.Puerto, "COM1");
    Ops.Baudios = 115200;
    Ops.BitsDatos = 8;
    Ops.BitsStop = 2;
    strcpy(Ops.Paridad, "Sin paridad");

    // No se ha establecido comunicación:
    idComDev = InicioComunicacion(&Ops);
    if(idComDev == INVALID_HANDLE_VALUE) {
        cout << "Inicialización puerto serie" << endl;
        cout << "ERROR: No se puede acceder al puerto serie." << endl;
        return 1;
    }
    // Lanzar hilo de lectura del puerto serie:
    hHilo = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Hilo, (LPDWORD)&idComDev, 0, &id);
    if(!hHilo) cout << "Error" << endl;
    // Bucle principal:
    ocupado = false;
    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(idComDev, cad);
        }
    }
    // Liberar hilo:
    CloseHandle(hHilo);
    // Liberar puerto serie:
    FinComunicacion(idComDev);
    return 0;
}

// Iniciar el puerto serie:
HANDLE InicioComunicacion(tipoOpciones *Ops)
{
    bool fSuccess;
    HANDLE idComDev;
    DCB dcb;                  // Puerto serie

    // 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. Inicialización puerto serie" << endl;
        return INVALID_HANDLE_VALUE;
    }
    PurgeComm(idComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

    // Leer estructura de control del puerto serie, cdb:
    fSuccess = GetCommState(idComDev, &dcb);
    if(!fSuccess) {
        cout << "ERROR: GetCommState. Inicialización puerto serie" << endl;
        // Cerrar el puerto, regresar con 0.
        CloseHandle(idComDev);
        return INVALID_HANDLE_VALUE;
    }

    // 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. Inicialización puerto serie" << endl;
        // Cerrar el puerto, regresar con 0.
        CloseHandle(idComDev);
        return INVALID_HANDLE_VALUE;
    }

    //// ASIGNAR TIMOUTS!!!

    return idComDev;
}

// Finalizar comunicación por puerto serie:
bool FinComunicacion(HANDLE idComDev)
{
    // Cerrar el puerto serie:
    CloseHandle(idComDev);
    return true;
}

// Hilo de escucha del puerto serie:
DWORD Hilo(LPDWORD lpdwParam)
{
    DWORD leidos;
    COMSTAT cs;
    char *cad;
    DWORD dwCommEvent;
    HANDLE idComDev = *((HANDLE*)lpdwParam);

    if(!SetCommMask(idComDev, EV_RXCHAR)) {
        cout << "Error al iniciar captura de evento" << endl;
        return 0;
    }
    do {
        if(WaitCommEvent(idComDev, &dwCommEvent, NULL)) {
            SetCommMask(idComDev, EV_RXCHAR);
            while(ocupado);
            ocupado = true;
            if(dwCommEvent & EV_RXCHAR) {
                ClearCommError(idComDev, &leidos, &cs);
                leidos=0;
                cout << "Detectados " << cs.cbInQue << " caracteres" << endl;
                /* Leer buffer desde puerto serie */
                if(cs.cbInQue) {
                    cad = new char[cs.cbInQue+3]; // Caracteres en buffer, más retorno de línea, más nulo
                    ReadFile(idComDev, cad, cs.cbInQue, &leidos, NULL);
                    cad[leidos] = '\n'; // Terminar cadena con salto de línea y nulo
                    cad[leidos+1] = '\r';
                    cad[leidos+2] = 0;
                    cout << cad;
                    delete[] cad;
                }
            } else {
                cout << "Evento: EV_BREAK o EV_ERR" << endl;
                 ClearCommBreak(idComDev);
            }
            ocupado = false;
        } else {
            cout << "Error en WaitCommEvent" << endl;
            ClearCommError(idComDev, NULL, NULL);
        }
        Sleep(10);
    } while(true);
    return 0;
}

void EscribirSerie(HANDLE idComDev, char *buf)
{
    char oBuffer[256];  /* Buffer de salida */
    DWORD iBytesWritten;

    iBytesWritten = 0;
    strcpy(oBuffer, buf);
    while(ocupado);
    ocupado = true;
    WriteFile(idComDev, oBuffer, strlen(oBuffer), &iBytesWritten, NULL);
    ocupado = false;
}


47   73   C:\Users\Meta\Desktop\main.cpp   [Error] 'StringCchPrintf' was not declared in this scope


Saludos.