#include #include #include #include #include #include #include #include // --- 配置 --- // 要打开的串口 const char* SERIAL_PORT = "/dev/ttyS7"; // 波特率 const speed_t BAUD_RATE = B9600; // 要发送的原始十六进制数据 (不带空格) const char* HEX_STRING_TO_SEND = "010300000001840A"; // --- 配置结束 --- /** * @brief 将十六进制字符串转换为字节数组 * @param hex_str 十六进制字符串,如 "010203" * @param data 输出字节数组 * @return int 成功转换的字节数,失败返回 -1 */ int hexStringToBytes(const std::string& hex_str, std::vector& data) { if (hex_str.length() % 2 != 0) { std::cerr << "Error: Hex string length must be even." << std::endl; return -1; } data.clear(); for (size_t i = 0; i < hex_str.length(); i += 2) { std::string byte_str = hex_str.substr(i, 2); try { int8_t byte = static_cast(std::stoul(byte_str, nullptr, 16)); data.push_back(byte); } catch (const std::invalid_argument& e) { std::cerr << "Error: Invalid hex character '" << byte_str << "'" << std::endl; return -1; } catch (const std::out_of_range& e) { std::cerr << "Error: Hex value '" << byte_str << "' is out of range." << std::endl; return -1; } } return data.size(); } /** * @brief 打开并配置串口 * @param port_name 串口设备名 * @param baudrate 波特率 * @return int 成功返回文件描述符,失败返回 -1 */ int openSerialPort(const char* port_name, speed_t baudrate) { int fd = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY); if (fd < 0) { std::cerr << "Error opening serial port " << port_name << ": " << strerror(errno) << std::endl; return -1; } termios options; tcgetattr(fd, &options); // 设置波特率 cfsetispeed(&options, baudrate); cfsetospeed(&options, baudrate); // 8N1 options.c_cflag &= ~PARENB; // 无校验 options.c_cflag &= ~CSTOPB; // 1位停止位 options.c_cflag &= ~CSIZE; // 清除数据位设置 options.c_cflag |= CS8; // 8位数据位 // 启用接收 options.c_cflag |= (CLOCAL | CREAD); // 原始输入模式 options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始输出模式 options.c_oflag &= ~OPOST; // 设置超时 (VTIME=5 表示 5 * 0.1s = 0.5s) options.c_cc[VMIN] = 0; // 不阻塞,只要有数据就读 options.c_cc[VTIME] = 5; // 超时时间 tcsetattr(fd, TCSANOW, &options); tcflush(fd, TCIOFLUSH); std::cout << "Serial port " << port_name << " opened successfully." << std::endl; return fd; } int main() { std::cout << "--- Simple Serial Port Test for /dev/ttyS7 ---" << std::endl; // 1. 转换十六进制字符串为数据 std::vector data_to_send; int bytes_converted = hexStringToBytes(HEX_STRING_TO_SEND, data_to_send); if (bytes_converted < 0) { return 1; } std::cout << "Data to send (" << data_to_send.size() << " bytes): "; for (auto byte : data_to_send) { printf("%02X ", byte); } std::cout << std::endl; // 2. 打开串口 int serial_fd = openSerialPort(SERIAL_PORT, BAUD_RATE); if (serial_fd < 0) { return 1; } // 3. 发送数据 std::cout << "\n>>> Sending data..." << std::endl; if (write(serial_fd, data_to_send.data(), data_to_send.size()) != data_to_send.size()) { std::cerr << "Error writing to serial port: " << strerror(errno) << std::endl; close(serial_fd); return 1; } std::cout << "Data sent." << std::endl; // 4. 尝试读取响应 std::cout << "\n<<< Waiting for response... (will timeout after 3 seconds)" << std::endl; std::vector received_data; fd_set read_fds; struct timeval timeout; ssize_t bytes_read; // 总超时设置为 3 秒 int total_timeout_sec = 3; time_t start_time = time(nullptr); while (difftime(time(nullptr), start_time) < total_timeout_sec) { FD_ZERO(&read_fds); FD_SET(serial_fd, &read_fds); // 每次循环都设置一个0.5秒的select超时 timeout.tv_sec = 0; timeout.tv_usec = 500000; // 0.5s int ready = select(serial_fd + 1, &read_fds, NULL, NULL, &timeout); if (ready < 0) { perror("select error"); break; } else if (ready == 0) { // select 超时,继续循环直到总超时 continue; } // 有数据可读 uint8_t buffer[256]; bytes_read = read(serial_fd, buffer, sizeof(buffer)); if (bytes_read < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { continue; // 没有新数据,继续循环 } perror("read error"); break; } else if (bytes_read == 0) { // 连接关闭 break; } // 将读取到的数据追加到结果向量 for (int i = 0; i < bytes_read; ++i) { received_data.push_back(buffer[i]); } // 打印新收到的数据 std::cout << "Received " << bytes_read << " new bytes: "; for (int i = 0; i < bytes_read; ++i) { printf("%02X ", buffer[i]); } std::cout << std::endl; } // 总超时结束 if (!received_data.empty()) { std::cout << "\n--- Total Received Data (" << received_data.size() << " bytes) ---" << std::endl; for (auto byte : received_data) { printf("%02X ", byte); } std::cout << std::endl; } else { std::cout << "\n--- No data received within the 3-second timeout. ---" << std::endl; } // 5. 关闭串口 close(serial_fd); std::cout << "\nSerial port closed." << std::endl; return 0; }