You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Win32 API串口通信:如何查询可读取字节数?

Win32串口查询可读取字节数的正确方法

串口不属于普通磁盘文件,GetFileSizeEx()函数仅适用于磁盘文件操作,无法用来查询串口缓冲区的待读取字节数。要实现类似Arduino中Serial.available()的功能,应该使用Win32 API提供的ClearCommError()函数。

核心逻辑

ClearCommError()函数可获取串口的通信错误状态,同时填充COMSTAT结构体,其中的cbInQue字段就是当前串口输入缓冲区中等待读取的字节总数。

修改后的代码示例

替换你原代码中调用GetFileSizeEx()的部分,同时修复空指针导致的异常问题:

#include <Windows.h>
#include <iostream>
#include <string>

int main() {
    HANDLE hFile;
    hFile = CreateFile("COM4",
        GENERIC_READ | GENERIC_WRITE,
        0,
        0,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        0);

    if(hFile == INVALID_HANDLE_VALUE) {
        std::cout << "bad handle" << std::endl;
        return 0;
    }
    DCB cerialParams = {0};
    cerialParams.DCBlength = sizeof(cerialParams);
    if(!GetCommState(hFile, &cerialParams)) {
        std::cout << "GetCommState failed" << std::endl;
        CloseHandle(hFile);
        return 0;
    }

    cerialParams.BaudRate = CBR_9600;
    cerialParams.ByteSize = 8;
    cerialParams.StopBits = ONESTOPBIT;
    cerialParams.Parity = NOPARITY;

    if(!SetCommState(hFile, &cerialParams)) {
        std::cout << "SetCommState failed" << std::endl;
        CloseHandle(hFile);
        return 0;
    }

    COMMTIMEOUTS timeouts = {0};
    timeouts.ReadIntervalTimeout = 500;
    timeouts.ReadTotalTimeoutConstant = 500;
    timeouts.ReadTotalTimeoutMultiplier = 10;

    timeouts.WriteTotalTimeoutConstant = 500;
    timeouts.WriteTotalTimeoutMultiplier = 10;

    if(!SetCommTimeouts(hFile, &timeouts)) {
        std::cout << "SetCommTimeouts failed" << std::endl;
        CloseHandle(hFile);
        return 0;
    }
    
    // 替换GetFileSizeEx的正确逻辑
    DWORD errors;
    COMSTAT stat;
    if (ClearCommError(hFile, &errors, &stat)) {
        std::cout << "当前可读取字节数: " << stat.cbInQue << std::endl;
    } else {
        std::cout << "ClearCommError调用失败,错误码: " << GetLastError() << std::endl;
    }

    CloseHandle(hFile);
    return 0;
}

关键说明

  1. ClearCommError()会清除当前的通信错误状态,同时返回串口的实时状态
  2. COMSTAT结构体的cbInQue字段准确反映了输入缓冲区中未读取的字节数
  3. 你原代码中PLARGE_INTEGER fSizeStruct{0}是一个空指针,调用GetFileSizeEx()会导致内存访问异常,这也是控制台输出失效的直接原因

内容的提问来源于stack exchange,提问作者crispeeweevile

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 20:27:26