Tengo un código que encontré sobre el puerto serie, recibir y enviar datos hechos en C++.
Código
// Comunicación a través del puerto serie // usando el API de Windows // Modo consola. // (C) Enero de 2013, Salvador Pozo Coronado // Con Clase: http://www.conclase.net // salvador@conclase.net #include <iostream> #include <cstring> #include <windows.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[]) { 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, "COM4"); 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; }
Fuente:
http://articulos.conclase.net/?tema=comunicacion&art=serie&pag=000
Por supuesto, debo modificarlo. Creo una interfaz MFC del C++ bajo Visual Studio Community 2015 indicado en este documento a partir de la página 30.
En el MFC de Visual Studio, hay que incluir dos botones y un richTextBox.
Imagen, Arduino debe recibir datos desde el puerto serie y enviar que ha sido recibido.
Solo quiero que con MFC sea capaz de apagar y encender un Led, tal como lo hago con otro lenguaje, C#, Visual Basic pero este MFC de C++ me cuesta muchísimo.
Si les pica la curiosidad, el código de Arduino es este.
Código
/* * Electrónica PIC. * * Ejemplo: * Encender y apagar un Led con Arduino y Visual Studio 2015. */ int pinLed = 13; // Declaramos la variable pin del Led. char caracter; String comando; void setup() { Serial.begin(9600); } void loop() { pinMode(pinLed, OUTPUT); // Inicializa el pin del Led 1 como salida. /* Voy leyendo carácter a carácter lo que se recibe por el canal * serie (mientras llegue algún dato allí), y los voy concatenando * uno tras otro en una cadena. En la práctica, si usamos el * "Serial monitor" el bucle while acabará cuando pulsemos Enter. * El delay es conveniente para no saturar el canal serie y que la * concatenación se haga de forma ordenada. */ while (Serial.available() > 0) { caracter= Serial.read(); comando.concat(caracter); delay(10); } /* Unavez ya tengo la cadena "acabada", compruebo su valor y hago * que la placa Arduino reaccione según sea este. Aquí podríamos * hacer lo que quiesiéramos: si el comando es "tal", enciende * un Led, si es cual, mueve un motor... y así. */ if (comando.equals("ON") == true) // Led_ON. { digitalWrite(pinLed, HIGH); // Enciende el Led. Serial.println("Led 13 encendido."); } if (comando.equals("OFF") == true) // Led_OFF. { digitalWrite(pinLed, LOW); // Apaga el Led. Serial.println("Led 13 apagado."); } // Limpiamos la cadena para volver a recibir el siguiente comando. comando=""; }
En resumen, a partir del código de C++ para consola, adaptarlo a modo Visual MFC C++, solo enviar ON y OFF y recibir datos de respuesta.
Espero resolver este problema de una vez. C++ me vuelve loco.
Un cordial saludos.