问题
I have to write a program in Visual C++ 2010 to communicate via Serial Port (RS232) in Windows 7 32 bit. Can Someone help me to find correct example?
回答1:
Serial Communications: http://msdn.microsoft.com/en-us/library/ff802693.aspx
This article still remains actual after so many years... Code sample included.
回答2:
Here it is a two samples of the same program, one for visual studio 2013 and the other for minGW in Eclipse in Windows 7 32 bits
for visual studio:
stadfx.h
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: mencionar aquí los encabezados adicionales que el programa necesita
#include <conio.h>
#include <string.h>
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
using namespace std;
terminal.cpp
#include "stdafx.h"
void error_de_sistema(char *name) {
// Recupera, formatea y despliega el mensaje del ultimo error
// 'name' que es el argumento pasado al momento del error debe ser una frase en presente
// como por ejemplo "abriendo archivo".
//
//char *ptr = NULL;
WCHAR ptr[1024];
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
0,
GetLastError(),
0,
//(char *)&ptr,
ptr,
1024,
NULL);
//fprintf(stderr, "\nError %s: %s\n", name, ptr);
//fprintf(stderr, "\nError %s: %s\n", name, &ptr);
wcout << endl << "Error " << name << ": " << ptr << endl;
LocalFree(ptr);
}
int _tmain(int argc, _TCHAR* argv[])
{
int ch;
char buffer[1];
HANDLE file;
COMMTIMEOUTS timeouts;
DWORD read, written;
DCB port;
HANDLE keyboard = GetStdHandle(STD_INPUT_HANDLE);
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode;
//char port_name[128] = "\\\\.\\COM3";
LPCWSTR port_name = L"\\\\.\\COM5";
char init[] = ""; // v.gr., "ATZ" resetea un modem por completo.
if (argc > 2)
swprintf_s((wchar_t *)&port_name, 128, L"\\\\.\\COM%c", argv[1][0]);
//sprintf(port_name, "\\\\.\\COM%c", argv[1][0]);
// abre el puerto.
file = CreateFile(port_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == file) {
error_de_sistema("abriendo archivo");
return 1;
}
// obtiene el block de control del dispositivo DCB, y ajusta unos cuantos bits para nuestro enlace.
memset(&port, 0, sizeof(port));
port.DCBlength = sizeof(port);
if (!GetCommState(file, &port))
error_de_sistema("obteniendo el estado del puerto");
//if (!BuildCommDCB("baud=19200 parity=n data=8 stop=1", &port))
if (!BuildCommDCB(L"baud=9600 parity=n data=8 stop=1", &port))
error_de_sistema("creando el bloque DCB de comunicaciones");
if (!SetCommState(file, &port))
error_de_sistema("ajustando la configuracion del puerto");
// Configura los tiempos fuera cortos para el puerto.
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutMultiplier = 1;
timeouts.ReadTotalTimeoutConstant = 1;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant = 1;
if (!SetCommTimeouts(file, &timeouts))
error_de_sistema("configurando los time-outs. del puerto");
// Configura el teclado para una lectura raw (aleatoria y libre).
if (!GetConsoleMode(keyboard, &mode))
error_de_sistema("obteniendo el modo del teclado");
mode &= ~ENABLE_PROCESSED_INPUT;
if (!SetConsoleMode(keyboard, mode))
error_de_sistema("configurando el modo del teclado");
if (!EscapeCommFunction(file, CLRDTR))
error_de_sistema("apagando el DTR");
Sleep(200);
if (!EscapeCommFunction(file, SETDTR))
error_de_sistema("encendiendo el DTR");
if (!WriteFile(file, init, sizeof(init), &written, NULL))
error_de_sistema("escribiendo datos en el puerto");
if (written != sizeof(init))
error_de_sistema("porque no todos los datos se enviaron al puerto");
// ciclo basico de la terminal:
do {
// checa por datos en el puerto y los despliega en pantalla.
ReadFile(file, buffer, sizeof(buffer), &read, NULL);
if (read)
WriteFile(screen, buffer, read, &written, NULL);
// checa por tecla presionada, y lo envia al puerto.
if (_kbhit()) {
ch = _getch();
WriteFile(file, &ch, 1, &written, NULL);
}
} while (ch != 127); // hasta que el usuario pulse ctrl-backspace.
// cierra todo y bye bye.
CloseHandle(keyboard);
CloseHandle(file);
return 0;
}
y para eclipse con minGW
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define STRICT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <iostream>
using namespace std;
void error_de_sistema(char *name) {
// Recupera, formatea y despliega el mensaje del ultimo error
// 'name' que es el argumento pasado al momento del error debe ser una frase en presente
// como por ejemplo "abriendo archivo".
//
char *ptr = NULL;
//WCHAR ptr[1024];
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
0,
GetLastError(),
0,
//(char *)&ptr,
ptr,
1024,
NULL);
//fprintf(stderr, "\nError %s: %s\n", name, ptr);
//fprintf(stderr, "\nError %s: %s\n", name, &ptr);
wcout << endl << "Error " << name << ": " << ptr << endl;
LocalFree(ptr);
}
int main(int argc, char **argv)
{
int ch;
char buffer[1];
char mensaje[256];
HANDLE file;
COMMTIMEOUTS timeouts;
DWORD read, written;
DCB port;
HANDLE keyboard = GetStdHandle(STD_INPUT_HANDLE);
HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode;
char port_name[128] = "\\\\.\\COM5";
//LPCWSTR port_name = L"\\\\.\\COM5";
char init[] = ""; // v.gr., "ATZ" resetea un modem por completo.
if (argc > 2)
//swprintf_s((wchar_t *)&port_name, 128, L"\\\\.\\COM%c", argv [1][0]);
sprintf(port_name, "\\\\.\\COM%c", argv[1][0]);
// abre el puerto.
file = CreateFile(port_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
if (INVALID_HANDLE_VALUE == file) {
strncpy(mensaje, "abriendo archivo", sizeof(mensaje));
error_de_sistema(mensaje);
return 1;
}
// obtiene el block de control del dispositivo DCB, y ajusta unos cuantos bits para nuestro enlace.
memset(&port, 0, sizeof(port));
port.DCBlength = sizeof(port);
if (!GetCommState(file, &port)){
strncpy(mensaje, "obteniendo el estado del puerto", sizeof(mensaje));
error_de_sistema(mensaje);
}
if (!BuildCommDCB("baud=9600 parity=n data=8 stop=1", &port)){
//if (!BuildCommDCB(L"baud=9600 parity=n data=8 stop=1", &port))
strncpy(mensaje, "creando el bloque DCB de comunicaciones", sizeof(mensaje));
error_de_sistema(mensaje);
}
if (!SetCommState(file, &port)){
strncpy(mensaje, "ajustando la configuracion del puerto", sizeof(mensaje));
error_de_sistema(mensaje);
}
// Configura los tiempos fuera cortos para el puerto.
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutMultiplier = 1;
timeouts.ReadTotalTimeoutConstant = 1;
timeouts.WriteTotalTimeoutMultiplier = 1;
timeouts.WriteTotalTimeoutConstant = 1;
if (!SetCommTimeouts(file, &timeouts)){
strncpy(mensaje, "configurando los time-outs. del puerto", sizeof(mensaje));
error_de_sistema(mensaje);
}
// Configura el teclado para una lectura raw (aleatoria y libre).
if (!GetConsoleMode(keyboard, &mode)){
strncpy(mensaje, "obteniendo el modo del teclado", sizeof(mensaje));
error_de_sistema(mensaje);
}
mode &= ~ENABLE_PROCESSED_INPUT;
if (!SetConsoleMode(keyboard, mode)){
strncpy(mensaje, "configurando el modo del teclado", sizeof(mensaje));
error_de_sistema(mensaje);
}
//Mandamos un reset por hardware (algunos sistemas se resetean con el DTR)
if (!EscapeCommFunction(file, CLRDTR)){
strncpy(mensaje, "apagando el DTR", sizeof(mensaje));
error_de_sistema(mensaje);
}
Sleep(200);
if (!EscapeCommFunction(file, SETDTR)){
strncpy(mensaje, "encendiendo el DTR", sizeof(mensaje));
error_de_sistema(mensaje);
}
if (!WriteFile(file, init, sizeof(init), &written, NULL)){
strncpy(mensaje, "escribiendo datos en el puerto", sizeof (mensaje));
error_de_sistema(mensaje);
}
//Por si es necesario enviar algun dato al comenzar el proceso
if (written != sizeof(init)){
strncpy(mensaje, "porque no todos los datos se enviaron al puerto", sizeof(mensaje));
error_de_sistema(mensaje);
}
// ciclo basico de la terminal:
do {
// checa por datos en el puerto y los despliega en pantalla.
ReadFile(file, buffer, sizeof(buffer), &read, NULL);
if (read)
WriteFile(screen, buffer, read, &written, NULL);
// checa por tecla presionada, y si hay alguna, envia el caracter leido al puerto.
if (_kbhit()) {
ch = _getch();
WriteFile(file, &ch, 1, &written, NULL);
}
} while (ch != 127); // termina el ciclo hasta que el usuario pulse ctrl-backspace.
// cierra todo y bye bye.
CloseHandle(keyboard);
CloseHandle(file);
return 0;
}
来源:https://stackoverflow.com/questions/7385228/serial-port-rs232-communication-with-visual-c-2010