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

SHT4X传感器Python转C/C++串口读取程序问题求助

串口读取SHT4X传感器数据的C++程序问题解决

我用Python控制台程序可以从COM7端口、波特率115200的SHT4X Turnkey传感器读取文本数据,但用C++写同类程序时,无法获取传感器MicroPython程序通过print发送的数据,仅输出:

Serial port opened successfully.
No data received for 10 attempts. Exiting.

请问怎么修改C++程序才能正确读取?改用C语言会不会更好?

传感器MicroPython程序

import time
import board
import adafruit_sht4x

convertToF = lambda celsius: (celsius * 9/5) + 32

i2c = board.I2C()  # uses board.SCL and board.SDA
sht = adafruit_sht4x.SHT4x(i2c)
print("Found SHT4x with serial number", hex(sht.serial_number))

sht.mode = adafruit_sht4x.Mode.NOHEAT_HIGHPRECISION
print("Current mode is: ", adafruit_sht4x.Mode.string[sht.mode])
print()

while True:
    temperature, relative_humidity = sht.measurements
    print(f"Temperature: {convertToF(temperature):0.1f} F")
    print(f"Humidity: {relative_humidity:0.1f} %")
    print("")
    time.sleep(1)

控制台Python程序

import serial #To read data from the board
import time #To wait

# Connect to the serial port
connection = serial.Serial('COM7', 115200)

# Check if the serial port is open
if connection.is_open:
    print("Serial Port Connection Established")
else:
    print("Serial Port Connection Failed")
    exit()  # Exit the program if connection fails

# Set a maximum number of iterations with no data before terminating
max_no_data_iterations = 10

# Main Program Loop
while max_no_data_iterations > 0:
    try:
        # Read from serial port
        line = connection.readline().decode().strip()
    except Exception as e:
        print(f"Error reading from serial port: {e}")
        exit()

    # Check if serial port line is empty
    if line:
        print(line)
        max_no_data_iterations = 10  # Reset the counter if data is received
    else:
        max_no_data_iterations -= 1  # Decrement the counter if no data is received

    # Wait to prevent high CPU usage
    time.sleep(0.05)

# Print a message before exiting
print("Program terminated due to no data received.")

控制台C++程序(原版本)

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

int main() {
    HANDLE hSerial;
    DCB dcbSerialParams = { 0 };
    COMMTIMEOUTS timeouts = { 0 };
    int noDataCount = 0;

    // Open the serial port
    hSerial = CreateFileW(L"\\\\.\\COM7", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hSerial == INVALID_HANDLE_VALUE) {
        std::cerr << "Error opening serial port" << std::endl;
        return 1;
    }

    std::cout << "Serial port opened successfully." << std::endl;

    // Set the baud rate
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    GetCommState(hSerial, &dcbSerialParams);
    dcbSerialParams.BaudRate = CBR_9600;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;
    if (!SetCommState(hSerial, &dcbSerialParams)) {
        std::cerr << "Error setting serial port state" << std::endl;
        CloseHandle(hSerial);
        return 1;
    }

    while (true) {
        char buffer[100];
        DWORD bytesRead;

        if (ReadFile(hSerial, buffer, sizeof(buffer), &bytesRead, NULL)) {
            if (bytesRead > 0) {
                std::cout.write(buffer, bytesRead);
                noDataCount = 0;
            } else {
                noDataCount++;
                if (noDataCount >= 10) {
                    std::cerr << "No data received for 10 attempts. Exiting." << std::endl;
                    break;
                }
            }
        } else {
            std::cerr << "Error reading from serial port" << std::endl;
            break;
        }
    }

    CloseHandle(hSerial);
    return 0;
}

我试过把波特率从115200改成9600没用,用termios.h替代windows.h也无效,循环里加/删sleep函数、改用C语言结果都一样。


关键问题修正

  1. 波特率不匹配:原C++程序设置的是CBR_9600,但Python程序和传感器实际使用的是115200,必须改为CBR_115200。
  2. 串口超时配置缺失:Windows默认串口超时会导致ReadFile立即返回无数据,需要设置合理的超时参数,让程序等待数据到来。
  3. 字符串终止符处理:读取数据后需要手动添加\0,避免输出乱码。

修改后的C++程序

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

int main() {
    HANDLE hSerial;
    DCB dcbSerialParams = { 0 };
    COMMTIMEOUTS timeouts = { 0 };
    int noDataCount = 0;

    // 打开串口
    hSerial = CreateFileW(L"\\\\.\\COM7", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hSerial == INVALID_HANDLE_VALUE) {
        std::cerr << "打开串口失败" << std::endl;
        return 1;
    }

    std::cout << "串口打开成功。" << std::endl;

    // 读取并配置串口参数
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        std::cerr << "获取串口状态失败" << std::endl;
        CloseHandle(hSerial);
        return 1;
    }
    // 修正波特率为115200
    dcbSerialParams.BaudRate = CBR_115200;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;
    if (!SetCommState(hSerial, &dcbSerialParams)) {
        std::cerr << "设置串口状态失败" << std::endl;
        CloseHandle(hSerial);
        return 1;
    }

    // 配置超时:总等待1000ms,间隔超时10ms
    timeouts.ReadIntervalTimeout = 10;
    timeouts.ReadTotalTimeoutConstant = 1000;
    timeouts.ReadTotalTimeoutMultiplier = 0;
    timeouts.WriteTotalTimeoutConstant = 0;
    timeouts.WriteTotalTimeoutMultiplier = 0;
    if (!SetCommTimeouts(hSerial, &timeouts)) {
        std::cerr << "设置超时失败" << std::endl;
        CloseHandle(hSerial);
        return 1;
    }

    while (true) {
        char buffer[100];
        DWORD bytesRead;

        if (ReadFile(hSerial, buffer, sizeof(buffer)-1, &bytesRead, NULL)) {
            if (bytesRead > 0) {
                // 添加字符串终止符,避免乱码
                buffer[bytesRead] = '\0';
                std::cout << buffer;
                noDataCount = 0;
            } else {
                noDataCount++;
                if (noDataCount >= 10) {
                    std::cerr << "连续10次未收到数据,退出。" << std::endl;
                    break;
                }
            }
        } else {
            std::cerr << "读取串口数据失败" << std::endl;
            break;
        }
    }

    CloseHandle(hSerial);
    return 0;
}

关于改用C语言的问题

没必要改用C语言,C和C在Windows串口操作上核心都是调用Win32 API,逻辑完全一致。只要修正上述问题,C程序就能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 06:46:01