Visual c++ 用Visual C++ 2010实现串口(RS232)通信 在Windows 7×32位中,我必须用Visual C++ 2010编写一个程序,通过串口RS232进行通信。有人能帮我找到正确的例子吗

Visual c++ 用Visual C++ 2010实现串口(RS232)通信 在Windows 7×32位中,我必须用Visual C++ 2010编写一个程序,通过串口RS232进行通信。有人能帮我找到正确的例子吗,visual-c++,windows-7,serial-port,data-transfer,Visual C++,Windows 7,Serial Port,Data Transfer,串行通信: 经过这么多年,这篇文章仍然是真实的。。。包含代码示例。这里是同一程序的两个示例,一个用于visual studio 2013,另一个用于Windows 7 32位Eclipse中的minGW 对于visual studio: stadfx.h #pragma once #include "targetver.h" #include <stdio.h> #include <tchar.h> // TODO: mencionar aquí los encabe

串行通信:


经过这么多年,这篇文章仍然是真实的。。。包含代码示例。

这里是同一程序的两个示例,一个用于visual studio 2013,另一个用于Windows 7 32位Eclipse中的minGW

对于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;
}

谢谢…请给我更多的例子,我在C++方面没有很好的经验。它看起来像是2014年的标准Win32文件I/OAs。这仍然是最好的选择吗?.net更好吗?@baordog:在.net中,最好使用SerialPort类,它实际上是串行通信Windows API的高级包装器。对于跨平台程序考虑使用Booo.@亚历克斯谢谢你回来给我。我想我现在倾向于QT,因为无论如何都有一个GUI元素。