首页 > 编程语言 >C++控制台实现串口类似超级终端收发功能

C++控制台实现串口类似超级终端收发功能

时间:2023-06-01 11:58:27浏览次数:40  
标签:std include read C++ buffer 串口 input 超级终端

 

#include <iostream>
#include <windows.h>
#include <thread>

class SerialPort {
public:
    //构造函数,打开串口并设置参数
    SerialPort(const char* portName) {
        hSerial = CreateFileA(
            portName, GENERIC_READ | GENERIC_WRITE, 0, NULL,
            OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        if (hSerial == INVALID_HANDLE_VALUE) {
            std::cerr << "Error opening serial port\n";
            exit(1);
        }

        // 初始化串口参数
        DCB dcbSerialParams = { 0 };
        COMMTIMEOUTS timeouts = { 0 };
        dcbSerialParams.DCBlength = sizeof(dcbSerialParams);

        if (!GetCommState(hSerial, &dcbSerialParams)) {
            std::cerr << "Error getting serial port state\n";
            CloseHandle(hSerial);
            exit(1);
        }

        // 设置串口参数
        dcbSerialParams.BaudRate = CBR_115200; // 波特率为115200
        dcbSerialParams.ByteSize = 8; // 数据位为8位
        dcbSerialParams.StopBits = ONESTOPBIT; // 停止位为1位
        dcbSerialParams.Parity = NOPARITY; // 无校验位
        if (!SetCommState(hSerial, &dcbSerialParams)) {
            std::cerr << "Error setting serial port state\n";
            CloseHandle(hSerial);
            exit(1);
        }

        // 设置超时时间
        timeouts.ReadIntervalTimeout = 50; // 读取数据之间的间隔时间
        timeouts.ReadTotalTimeoutConstant = 50; // 读取数据的固定超时时间
        timeouts.ReadTotalTimeoutMultiplier = 10; // 读取数据的超时时间倍数
        timeouts.WriteTotalTimeoutConstant = 50; // 写入数据的固定超时时间
        timeouts.WriteTotalTimeoutMultiplier = 10; // 写入数据的超时时间倍数
        if (!SetCommTimeouts(hSerial, &timeouts)) {
            std::cerr << "Error setting serial port timeouts\n";
            CloseHandle(hSerial);
            exit(1);
        }
    }

    //析构函数,关闭串口
    ~SerialPort() {
        CloseHandle(hSerial);
    }

    //向串口写入数据
    bool write(const char* data) {
        DWORD bytes_written;
        if (!WriteFile(hSerial, data, strlen(data), &bytes_written, NULL)) {
            std::cerr << "Error writing to serial port\n";
            return false;
        }
        return true;
    }

    //从串口读取数据
    bool read(char* buffer, DWORD buffer_size, DWORD& bytes_read) {
        if (!ReadFile(hSerial, buffer, buffer_size, &bytes_read, NULL)) {
            std::cerr << "Error reading from serial port\n";
            return false;
        }
        return true;
    }

private:
    HANDLE hSerial;
};

void receive_thread(SerialPort* serial) {
    char buffer[32];
    DWORD bytes_read;
    while (true) {
        if (serial->read(buffer, sizeof(buffer), bytes_read)) {
            if (bytes_read > 0) {
                std::cout.write(buffer, bytes_read);// Print received data
            }
        }
    }
}
void send_thread(SerialPort* serial) {
    char input[32];
    while (true) {
        std::cin.getline(input, sizeof(input));
        if (serial->write(input)) {
            //std::cout << "Sent: " << input << std::endl;
        }
    }
}
int main() {
    SerialPort serial("COM7");
    std::thread t1(receive_thread, &serial);
    std::thread t2(send_thread, &serial);
    t1.join();
    t2.join();
    return 0;
}

 

标签:std,include,read,C++,buffer,串口,input,超级终端
From: https://www.cnblogs.com/lizhiqiang0204/p/17448516.html

相关文章

  • C++模板从入门到精通:初阶篇
    一、泛型编程1.1什么是泛型编程?泛型编程是一种编程风格,其中算法以尽可能抽象的方式编写,而不依赖于将在其上执行这些算法的数据形式1。泛型编程可以提高代码的重用性、可维护性和类型安全性。泛型编程的基础是模板,模板是创建泛型类或函数的蓝图或公式。平常写的函数与泛型编程的模板......
  • C++中分别使用左值形参和右值形参的拷贝构造和移动构造
    #include<iostream>classData{public:Data(){std::cout<<"EMPTY."<<std::endl;}Data(constData&d){std::cout<<"lvaluecopy."<<std::endl;}Data(constData&&d){std::cout......
  • [C++学习] 整型常量
    C++中二进制以0b开头,如0b00001011(值为11);八进制以0开头,如0013(值为11);十六进制以0x开头,如0x001a(值为26);注意:C++中cout是默认将数据以十进制输出,如果要将数据以八进制,十六进制输出应在前面加oct或hex;如:cout<<oct<<0123<<endl; //输出123cout<<hex<<0x1e<<en......
  • mongocxx c++ 14标准,进行多表联合查询
     #include<mongocxx/client.hpp>#include<mongocxx/instance.hpp>#include<mongocxx/uri.hpp>#include<bsoncxx/builder/stream/document.hpp>#include<bsoncxx/json.hpp>#include<bsoncxx/types.hpp>usingbsoncxx::builder::s......
  • C++指针需要知道的小细节
    一、定义和赋值一个普通对象intival=1024;如上述代码所示,将ival定义为一个int对象,并给予初始值1024。二、指针对象的声明int*pi;1、如上述代码所示,当定义/声明某个特定类型的指针时,要在类型名称后加一个*号。2、在这里,pi是int类型对象的指针。三、指针的初始值int*......
  • C++ 在 cout 中使用关系表达式
    用std::cout输出关系运算表达式时,关系表达式要加括号,否则编译会报错。例如:#include<iostream>intmain(intargc,char**argv){std::cout<<1<2<<std::endl;return0;}在linux中编译后报错内容如下:test.cpp:Infunction'intmain(int,char**)':te......
  • C++基础知识系列-4
    C++基础1C++的struct和class的区别区别1:默认继承的权限。不明确指定的情况下,来自class的继承按照private继承处理,来自struct继承按照public处理区别2:成员的默认访问权限。class成员默认是private权限,struct默认是public2C和C++区别struct上的区别:C中无Protection行为,不能定......
  • c++算法:二分
    算法中,有一种比线性查找算力费得更少的一种算法思想,叫“分治”,今天讲的是分治里的二分查找:借助(low+high)/2公式,找到搜索区域内的中间元素。图1中,搜索区域内中间元素的位置是 ⌊(1+10)/2⌋=5,因此中间元素是27,此元素显然不是要找的目标元素。然后就是缩小范围。 下面就是......
  • C++ 初始化赋值
    把值写在小括号中,等于号可以省略(C++标准)inta=(15);intb(20);把值写在花括号中,等于号也可以省略(C++11标准),统一初始化列表注意:在Linux平台下,编译需要加-std=c++11参数inta={15};inta{15};......
  • 不使用microlib实现STM32串口printf重定向:
    不使用microlib实现STM32串口printf重定向:突然发现有一篇markdown忘记上传了,补一下注:使用的是CubeMX生成的工程文件生成后,在usart.c中添加如下代码://usercodebegin0typedefstruct__FILEFILE;struct__FILE{ inthandle;};FILE__stdout;//userco......