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语言结果都一样。
关键问题修正
- 波特率不匹配:原C++程序设置的是
CBR_9600,但Python程序和传感器实际使用的是115200,必须改为CBR_115200。 - 串口超时配置缺失:Windows默认串口超时会导致
ReadFile立即返回无数据,需要设置合理的超时参数,让程序等待数据到来。 - 字符串终止符处理:读取数据后需要手动添加
\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
相关产品推荐
相关产品推荐

