C++ RS-485通讯示例

时间:2024-04-17 09:53:41

RS-485是一种半双工的通信协议,经常用于工业控制模块间的通信,因其传输距离远,不容易出错的特点,应用广泛。

此为windows下示例,linux需做相应修改。

#pragma once
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

class Net485
{
public:
    Net485(long baud_rate, wchar_t* port_name);
    bool send(BYTE data[], int length);
protected:
    void set_up_serial_port(long baud);

private:

    HANDLE serial_port;

};

#include "Net485.h"
#include <iostream>

Net485::Net485(long baud_rate, wchar_t* port_name)
{
    const wchar_t name[8] = L"COM4";
    serial_port = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
    if (serial_port == INVALID_HANDLE_VALUE)
    {
        fprintf(stderr, "Error opening portn");
        CloseHandle(serial_port);
    }
    else 
    {
        set_up_serial_port(baud_rate);
    }
}

bool Net485::send(BYTE data[],int length)
{
    if (serial_port == INVALID_HANDLE_VALUE)
    {
        printf("发送失败::INVALID_HANDLE_VALUE");
        return false;
    }

    DWORD dwTx = 0;
    BOOL ret = FALSE;
    DWORD dwLength = length;

    Sleep(10);

    if (dwLength > 0)
    {
        ret = WriteFile(serial_port, data, dwLength, &dwTx, NULL);
        if (ret == FALSE)
        {
            printf("发送失败");
            return false;
        }
    }

    return true;
}

void Net485::set_up_serial_port(long baud)
{
    DCB properties;

    // 设置读写缓冲区
    GetCommState(serial_port, &properties);

    switch (baud)
    {
    case 1200:
        properties.BaudRate = CBR_1200;
        break;
    case 2400:
        properties.BaudRate = CBR_2400;
        break;
    case 4800:
        properties.BaudRate = CBR_4800;
        break;
    case 9600:
        properties.BaudRate = CBR_9600;
        break;
    case 14400:
        properties.BaudRate = CBR_14400;
        break;
    case 19200:
        properties.BaudRate = CBR_19200;
        break;
    case 38400:
        properties.BaudRate = CBR_38400;
        break;
    default:
        fprintf(stderr, "Invalid baud rate: %ldn", baud);
        exit(0);
        break;
    }

    properties.Parity = NOPARITY;
    properties.ByteSize = 8;
    properties.StopBits = ONESTOPBIT;

    SetCommState(serial_port, &properties);

    //在读写串口前,用 PurgeComm 函数清空缓冲区
    PurgeComm(serial_port, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_TXABORT | PURGE_TXABORT);

    return;
}

使用示例

/// 485PLC通信
Net485* net = new Net485(9600,L"COM4");

BYTE data[2];
data[0] = 0x01;
if (info.th == 1) {

    data[1] = 0x11;
}
else {

    data[1] = 0x12;
}
net->send(data,sizeof(data));