Hola:
Tengo un código que encontré sobre el puerto serie, recibir y enviar datos hechos en C++.
// 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 (https://www.visualstudio.com/es-es/downloads/download-visual-studio-vs.aspx) indicado en este documento (https://drive.google.com/file/d/0B6HKwsbbpgrLRGdYeGhHb25MY3M/view) a partir de la página 30.
En el MFC de Visual Studio, hay que incluir dos botones y un richTextBox.
(http://www.subeimagenes.com/img/f-1627777.png)
Imagen, Arduino debe recibir datos desde el puerto serie y enviar que ha sido recibido.
(http://www.subeimagenes.com/img/chat-1558931.png)
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.
Ra2PBfLFuHk
Si les pica la curiosidad, el código de Arduino es este.
/*
* 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.