202 lines
5.9 KiB
C++
202 lines
5.9 KiB
C++
#include <iostream>
|
|
#include <vector>
|
|
#include <fcntl.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
#include <cstring>
|
|
#include <cerrno>
|
|
#include <sys/select.h>
|
|
|
|
// --- 配置 ---
|
|
// 要打开的串口
|
|
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<uint8_t>& 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<uint8_t>(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<uint8_t> 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<uint8_t> 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;
|
|
}
|