#include "ModbusRTU.h" #include <iostream> #include <cstring> // For memcpy ModbusRTU::ModbusRTU(boost::asio::io_service& io_service, const std::string& port_name) : serial(io_service, port_name) { serial.set_option(boost::asio::serial_port_base::baud_rate(9600)); serial.set_option(boost::asio::serial_port_base::character_size(8)); serial.set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none)); serial.set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one)); } template<typename T> void ModbusRTU::writeData(uint8_t slave_id, uint8_t function_code, uint16_t start_address, T value) { uint8_t frame[8 + sizeof(T)]; frame[0] = slave_id; frame[1] = function_code; frame[2] = (start_address >> 8) & 0xFF; frame[3] = start_address & 0xFF; std::memcpy(&frame[4], &value, sizeof(T)); uint16_t crc = calculateCRC(frame, 4 + sizeof(T)); frame[4 + sizeof(T)] = crc & 0xFF; frame[5 + sizeof(T)] = (crc >> 8) & 0xFF; boost::asio::write(serial, boost::asio::buffer(frame, 6 + sizeof(T))); } template<typename T> T ModbusRTU::readData(uint8_t slave_id, uint8_t function_code, uint16_t start_address, uint16_t num_registers) { uint8_t frame[8]; frame[0] = slave_id; frame[1] = function_code; frame[2] = (start_address >> 8) & 0xFF; frame[3] = start_address & 0xFF; frame[4] = (num_registers >> 8) & 0xFF; frame[5] = num_registers & 0xFF; uint16_t crc = calculateCRC(frame, 6); frame[6] = crc & 0xFF; frame[7] = (crc >> 8) & 0xFF; boost::asio::write(serial, boost::asio::buffer(frame, 8)); uint8_t response[256]; size_t length = serial.read_some(boost::asio::buffer(response, 256)); if (length > 0 && response[1] == function_code) { T result = 0; for (size_t i = 0; i < sizeof(T); ++i) { reinterpret_cast<uint8_t*>(&result)[i] = response[3 + i]; } return result; } else { std::cerr << "错误:无效的响应或没有收到响应。" << std::endl; } return T(); // 返回类型 T 的默认值 } uint16_t ModbusRTU::calculateCRC(const uint8_t* data, size_t length) { uint16_t crc = 0xFFFF; for (size_t i = 0; i < length; ++i) { crc ^= data[i]; for (int j = 0; j < 8; ++j) { if (crc & 1) crc = (crc >> 1) ^ 0xA001; else crc >>= 1; } } return crc; } void main() { try { boost::asio::io_service io_service; ModbusRTU modbus(io_service, "/dev/ttyS0"); // 根据你的实际串口设备调整 uint8_t slave_id = 1; // 从站地址 uint16_t start_address = 0x0001; // 起始寄存器地址 uint16_t value_to_write = 12345; // 要写入的值 // 写入数据 modbus.writeData<uint16_t>(slave_id, 0x06, start_address, value_to_write); // 0x06 是写单寄存器的功能码 std::cout << "数据已写入。" << std::endl; // 读取数据 uint16_t read_value = modbus.readData<uint16_t>(slave_id, 0x03, start_address, 1); // 0x03 是读保持寄存器的功能码 std::cout << "读取的数据: " << read_value << std::endl; } catch (const std::exception& e) { std::cerr << "异常: " << e.what() << std::endl; return 1; } return 0; }