Programación de puerto serie usando Win32 API (Windows)

 C Programming >> Programación C >  >> Tags >> API
Programación de puerto serie usando Win32 API (Windows)

A veces necesitamos comunicarnos con un dispositivo externo como una impresora, placa de microcontrolador o cualquier dispositivo serial usando el puerto serial de una máquina con Windows. Hay muchas aplicaciones seriales disponibles como Hercules, HyperTerminal, Docklight, ..etc.

Podemos usar cualquiera de ellos para la comunicación en serie, pero a veces necesitamos crear nuestra propia aplicación en serie personalizada para la comunicación. En Windows, es fácil crear la aplicación serial personalizada usando la API win32.

En esta publicación de blog, aprenderemos a programar el puerto serie utilizando la API de Win32. En Windows, la programación del puerto serie es muy fácil, MSDN proporciona toda la información API win32 necesaria para la programación del puerto serie.

También puede ver los artículos a continuación sobre cómo cambiar las propiedades del puerto COM, como la velocidad en baudios, la paridad usando la API de Windows.

  • Cambiar las propiedades del puerto COM usando la API win32
  • Obtenga el PUERTO COM del dispositivo serie USB usando el VID y el PID

Encontrar el número de puerto COM de un dispositivo

En Windows, el dispositivo serial se mostrará en la sección de puerto com del administrador de dispositivos con el nombre COM1, COM2, COM3, COM4... etc. Generalmente, COM1 y COM2 se refieren a los puertos seriales de hardware presentes en la PC y otro número de puerto com es exportar cuando cualquier dispositivo serial o USB a dispositivo serial conectado a la PC. También es posible que la identificación COM sea virtual (por ejemplo, un puerto COM virtual estático).

En mi computadora portátil, conecté una placa Arduino (Atmega 2560) y su ID COM se mostraría en la sección del puerto com (Panel de control> Administrador de dispositivos> Puertos).

Compiladores e IDE utilizados

Aquí he usado Visual Studio 2013. También puede usar MinGW (Minimalist GNU para Windows) una herramienta de programación de código abierto. Aquí, asumo que sabe cómo crear la aplicación de consola con Visual Studio y que está familiarizado con la API de win32.

Apertura de un puerto serie

En Windows usando CreateFile(), podemos abrir el puerto serie. CreateFile() es una API de Win32 que crea o abre un archivo o dispositivo de E/S.

En caso de éxito, CreateFile() devuelve un identificador que se puede usar para acceder al archivo o dispositivo según las banderas y los atributos especificados.

HANDLE CreateFile(
    LPCTSTR lpFileName,          // pointer to name of the file
    DWORD dwDesiredAccess,       // access (read-write) mode
    DWORD dwShareMode,           // share mode
    LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    // pointer to security attributes
    DWORD dwCreationDisposition,  // how to create
    DWORD dwFlagsAndAttributes,  // file attributes
    HANDLE hTemplateFile         // handle to file with attributes to
    // copy
);

Cerrar un puerto serie

Debe recordar que después de abrir el puerto com usando CreateFile(), debe cerrarlo llamando a CloseHandle(); de lo contrario, no estará disponible para otras aplicaciones.

BOOL CloseHandle(
  HANDLE hObject
);

En caso de éxito, CloseHandle() devuelve cero.

Aplicación de comunicación de puerto serie

Veamos un código de ejemplo donde estoy hablando con un dispositivo Arduino Mega2560. He escrito un pequeño código para mega2560 en el que recibe datos en serie. Si los datos recibidos son "aticleworld", enviará un mensaje "¡Bienvenido a AticleWorld!" o de lo contrario, enviará el mensaje "Envíe el mensaje correcto".

Código de serie Mega2560,

#include <SoftwareSerial.h>

void setup()
{
    // initialize serial ports
    Serial.begin(9600);    // USB serial port 0
}


void loop()
{
    String msg = "";
    // check for data byte on USB serial port
    if (Serial.available())
    {
        // get byte from USB serial port
        while(Serial.available())
        {
            msg = Serial.readString();// read the incoming data as string
        }
        if( msg == "aticleworld")
        {
            //Send data to usb serial port
            Serial.write(" Welcome to AticleWorld !");
        }
        else
        {
            //Send data to usb serial port
            Serial.write("Please Send Correct Message");
        }
    }
}

Puede comprar Mega2560 en Amazon, haga clic aquí

Aplicación Serie para la consola,

En la siguiente aplicación de consola, estoy usando la API win32 para abrir el puerto COM y enviar los datos al puerto COM abierto. Vea el video a continuación donde descargué el código Arduino en la placa Arduino y me comunico con esta placa usando la aplicación de consola.

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>
#include <string.h>

int main(void)
{

    HANDLE hComm;  // Handle to the Serial port
    BOOL   Status; // Status
    DCB dcbSerialParams = { 0 };  // Initializing DCB structure
    COMMTIMEOUTS timeouts = { 0 };  //Initializing timeouts structure
    char SerialBuffer[64] = { 0 }; //Buffer to send and receive data
    DWORD BytesWritten = 0;          // No of bytes written to the port
    DWORD dwEventMask;     // Event mask to trigger
    char  ReadData;        //temperory Character
    DWORD NoBytesRead;     // Bytes read by ReadFile()
    unsigned char loop = 0;
    wchar_t pszPortName[10] = { 0 }; //com port id
    wchar_t PortNo[20] = { 0 }; //contain friendly name



    //Enter the com port id
    printf_s("Enter the Com Port: ");
    wscanf_s(L"%s", pszPortName, (unsigned)_countof(pszPortName));
    swprintf_s(PortNo, 20, L"\\\\.\\%s", pszPortName);

    //Open the serial com port
    hComm = CreateFile(PortNo, //friendly name
                       GENERIC_READ | GENERIC_WRITE,      // Read/Write Access
                       0,                                 // No Sharing, ports cant be shared
                       NULL,                              // No Security
                       OPEN_EXISTING,                     // Open existing port only
                       0,                                 // Non Overlapped I/O
                       NULL);                             // Null for Comm Devices

    if (hComm == INVALID_HANDLE_VALUE)
    {
        printf_s("\n Port can't be opened\n\n");
        goto Exit2;
    }

    //Setting the Parameters for the SerialPort
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

    Status = GetCommState(hComm, &dcbSerialParams); //retreives  the current settings
    if (Status == FALSE)
    {
        printf_s("\nError to Get the Com state\n\n");
        goto Exit1;
    }

    dcbSerialParams.BaudRate = CBR_9600;      //BaudRate = 9600
    dcbSerialParams.ByteSize = 8;             //ByteSize = 8
    dcbSerialParams.StopBits = ONESTOPBIT;    //StopBits = 1
    dcbSerialParams.Parity = NOPARITY;      //Parity = None

    Status = SetCommState(hComm, &dcbSerialParams);
    if (Status == FALSE)
    {
        printf_s("\nError to Setting DCB Structure\n\n");
        goto Exit1;
    }

    //Setting Timeouts
    timeouts.ReadIntervalTimeout = 50;
    timeouts.ReadTotalTimeoutConstant = 50;
    timeouts.ReadTotalTimeoutMultiplier = 10;
    timeouts.WriteTotalTimeoutConstant = 50;
    timeouts.WriteTotalTimeoutMultiplier = 10;
    if (SetCommTimeouts(hComm, &timeouts) == FALSE)
    {
        printf_s("\nError to Setting Time outs");
        goto Exit1;
    }


    printf_s("\n\nEnter your message: ");
    scanf_s("%s", SerialBuffer, (unsigned)_countof(SerialBuffer));


    //Writing data to Serial Port
    Status = WriteFile(hComm,// Handle to the Serialport
                       SerialBuffer,            // Data to be written to the port
                       sizeof(SerialBuffer),   // No of bytes to write into the port
                       &BytesWritten,  // No of bytes written to the port
                       NULL);
    if (Status == FALSE)
    {
        printf_s("\nFail to Written");
        goto Exit1;
    }

    //print numbers of byte written to the serial port
    printf_s("\nNumber of bytes written to the serail port = %d\n\n", BytesWritten);

    //Setting Receive Mask
    Status = SetCommMask(hComm, EV_RXCHAR);

    if (Status == FALSE)
    {
        printf_s("\nError to in Setting CommMask\n\n");
        goto Exit1;
    }


    //Setting WaitComm() Event
    Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received
    if (Status == FALSE)
    {
        printf_s("\nError! in Setting WaitCommEvent()\n\n");
        goto Exit1;
    }

    //Read data and store in a buffer
    do
    {
        Status = ReadFile(hComm, &ReadData, sizeof(ReadData), &NoBytesRead, NULL);
        SerialBuffer[loop] = ReadData;
        ++loop;
    }
    while (NoBytesRead > 0);

    --loop; //Get Actual length of received data

    printf_s("\nNumber of bytes received = %d\n\n", loop);

    //print receive data on console
    printf_s("\n\n");
    int index = 0;
    for (index = 0; index < loop; ++index)
    {
        printf_s("%c", SerialBuffer[index]);
    }

    printf_s("\n\n");

Exit1:
    CloseHandle(hComm);//Closing the Serial Port
Exit2:
    system("pause");
    return 0;
}

Publicaciones recomendadas para ti:

  • Los 5 mejores libros C.
  • Obtenga el PUERTO COM del dispositivo serie USB usando el VID y el PID.
  • Lectura y escritura del registro de Windows usando WinAPI
  • Instalar el monitor de puerto de forma silenciosa sin interacción del usuario.
  • Preguntas de la entrevista de C++ con respuestas.
  • Preguntas de la entrevista de C-Sharp.
  • Preguntas de entrevista de Python con respuesta.
  • Diseño de memoria en C.
  • Preguntas de la entrevista de 100 C, su entrevistador podría preguntar.
  • C Preguntas de entrevista para la experiencia.
  • 10 preguntas sobre la asignación de memoria dinámica
  • Manejo de archivos en C, en pocas horas.



Referencia:https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea