@小鱼 @3152079070 之前的仓库已无法访问,小鱼串口文件没办法上传附件我直接贴在下面,这个串口文件目前只有串口,没有了tcp、udp等功能,酌情使用。```
proto_utils.cpp

/** * @brief 文件描述:协议处理工具,打印、crc、转义与反转义 * @author 小鱼 (fishros@foxmail.com) * @version V1.0.0 * @date 2022-07-17 * @copyright 版权所有:FishBot Open Source Organization */ #include "fish_protocol/protocol_util.h" #include <iostream> namespace fish_protocol { using namespace std; // ------------------------查表法crc8校验------- static const uint8_t crc8tab[] = {0x00,0x5e,0xbc,0xe2,0x61,0x3f,0xdd,0x83,0xc2,0x9c,0x7e,0x20,0xa3,0xfd,0x1f,0x41, 0x9d,0xc3,0x21,0x7f,0xfc,0xa2,0x40,0x1e,0x5f,0x01,0xe3,0xbd,0x3e,0x60,0x82,0xdc, 0x23,0x7d,0x9f,0xc1,0x42,0x1c,0xfe,0xa0,0xe1,0xbf,0x5d,0x03,0x80,0xde,0x3c,0x62, 0xbe,0xe0,0x02,0x5c,0xdf,0x81,0x63,0x3d,0x7c,0x22,0xc0,0x9e,0x1d,0x43,0xa1,0xff, 0x46,0x18,0xfa,0xa4,0x27,0x79,0x9b,0xc5,0x84,0xda,0x38,0x66,0xe5,0xbb,0x59,0x07, 0xdb,0x85,0x67,0x39,0xba,0xe4,0x06,0x58,0x19,0x47,0xa5,0xfb,0x78,0x26,0xc4,0x9a, 0x65,0x3b,0xd9,0x87,0x04,0x5a,0xb8,0xe6,0xa7,0xf9,0x1b,0x45,0xc6,0x98,0x7a,0x24, 0xf8,0xa6,0x44,0x1a,0x99,0xc7,0x25,0x7b,0x3a,0x64,0x86,0xd8,0x5b,0x05,0xe7,0xb9, 0x8c,0xd2,0x30,0x6e,0xed,0xb3,0x51,0x0f,0x4e,0x10,0xf2,0xac,0x2f,0x71,0x93,0xcd, 0x11,0x4f,0xad,0xf3,0x70,0x2e,0xcc,0x92,0xd3,0x8d,0x6f,0x31,0xb2,0xec,0x0e,0x50, 0xaf,0xf1,0x13,0x4d,0xce,0x90,0x72,0x2c,0x6d,0x33,0xd1,0x8f,0x0c,0x52,0xb0,0xee, 0x32,0x6c,0x8e,0xd0,0x53,0x0d,0xef,0xb1,0xf0,0xae,0x4c,0x12,0x91,0xcf,0x2d,0x73, 0xca,0x94,0x76,0x28,0xab,0xf5,0x17,0x49,0x08,0x56,0xb4,0xea,0x69,0x37,0xd5,0x8b, 0x57,0x09,0xeb,0xb5,0x36,0x68,0x8a,0xd4,0x95,0xcb,0x29,0x77,0xf4,0xaa,0x48,0x16, 0xe9,0xb7,0x55,0x0b,0x88,0xd6,0x34,0x6a,0x2b,0x75,0x97,0xc9,0x4a,0x14,0xf6,0xa8, 0x74,0x2a,0xc8,0x96,0x15,0x4b,0xa9,0xf7,0xb6,0xe8,0x0a,0x54,0xd7,0x89,0x6b,0x35}; uint8_t getcrc8tab(const uint8_t *buf, int len) { uint8_t crc = 0x00; while(len--) { crc = crc8tab[crc ^ *buf++]; } return crc; } /**************************** 函数功能:直接计算法获得8位循环冗余校验值 入口参数:数组地址、长度 出口参数:校验值 ******************************/ uint8_t getCrc8(uint8_t *ptr, uint16_t len) { uint8_t crc, i; crc = 0; while(len--) { crc ^= *ptr++; for(i = 0; i < 8; i++) { if(crc&0x01) crc=(crc>>1)^0x8C; else crc >>= 1; } } return crc; } int frame_packing(const uint8_t *buf, uint8_t *frame, uint8_t len, uint8_t func) { uint8_t cnt = 0; frame[cnt++] = FIRST_CODE; frame[cnt++] = func; frame[cnt++] = len; for (int i = 0; i < len; i++) { frame[cnt++] = buf[i]; } frame[cnt++] = getcrc8tab(buf, len); frame[cnt++] = END_CODE; return cnt; } int inverse_frame(uint8_t *result, const uint8_t *frame, uint8_t len, uint8_t& func) { if((frame[0] != FIRST_CODE) || (frame[len - 1] != END_CODE))// 检查帧头帧尾 return 0; for(int i = 3; i < len-2; i++) { result[i - 3] = frame[i]; } if(getcrc8tab(result, frame[2]) != frame[len - 2])// 检查crc8校验 return 0; func = frame[1]; return frame[2]; } } // namespace fish_protocol

serial_protocol.cpp

/** * @brief 文件描述:待完善 * @author 小鱼 (fishros@foxmail.com) * @version V1.0.0 * @date 2022-07-24 * @copyright 版权所有:(鱼香ROS)fishros.org.cn */ #include "fish_protocol/serial_protocol.h" namespace serial_protocol { /// @brief Flush a serial port's buffers. /// /// @param serial_port Port to flush. /// @param what Determines the buffers to flush. /// @param error Set to indicate what error occurred, if any. void SerialProtocol::flush_serial_port( boost::asio::serial_port& serial_port, flush_type what, boost::system::error_code& error) { if (0 == ::tcflush(serial_port.lowest_layer().native_handle(), what)) { error = boost::system::error_code(); } else { error = boost::system::error_code(errno, boost::asio::error::get_system_category()); } } SerialProtocol::~SerialProtocol() { io_service_.stop(); serial_port_.cancel(); serial_port_.close(); } void SerialProtocol::_initSerialProtocol() { boost::system::error_code ec; try { serial_port_.open(protocol_config_.serial_address_, ec); if(!serial_port_.is_open()) throw ec; } catch(boost::system::error_code& ec) { std::cout << ec.message() << std::endl; return ; } std::cout << "串口已打开:" << protocol_config_.serial_address_ << std::endl; serial_port_.set_option(spb::baud_rate(protocol_config_.serial_baut_)); serial_port_.set_option(spb::character_size(8)); serial_port_.set_option(spb::stop_bits(spb::stop_bits::one)); serial_port_.set_option(spb::parity(spb::parity::none)); serial_port_.set_option(spb::flow_control(spb::flow_control::none)); boost::thread td(boost::bind(&boost::asio::io_service::run, &io_service_)); _asyncReadSomeData(); } void SerialProtocol::_recvDataCallback(const boost::system::error_code& error, size_t bytes_transferred) { if (bytes_transferred > 0) { // 回调数据 if(recv_uint8_callback) { recv_uint8_callback(recv_data_buffer_, bytes_transferred); } } _asyncReadSomeData(); } void SerialProtocol::_asyncReadSomeData() { serial_port_.async_read_some( boost::asio::buffer(recv_data_buffer_, sizeof(recv_data_buffer_)), boost::bind(&SerialProtocol::_recvDataCallback, this, boost::placeholders::_1, boost::placeholders::_2)); } int SerialProtocol::ProtocolSendString(const std::string& data) { serial_port_.write_some(boost::asio::buffer(data.data(), data.size())); return 0; } int SerialProtocol::ProtocolSenduint8_t(const std::uint8_t* data, const std::uint8_t len) { serial_port_.write_some(boost::asio::buffer(data, len)); return 0; } void SerialProtocol::SetDataRecvCallback( std::function<void(const std::uint8_t*, const std::uint8_t)> callback) { recv_uint8_callback = callback; } } // namespace fish_protocol

protocol_util.h

/** * @brief 文件描述:待完善 * @author 小鱼 (fishros@foxmail.com) * @version V1.0.0 * @date 2022-07-24 * @copyright 版权所有:(鱼香ROS)fishros.org.cn */ #ifndef _FISH_PROTOCOL_PROTO_UTIL_H_ #define _FISH_PROTOCOL_PROTO_UTIL_H_ #include <cstdint> #include <cstdio> namespace fish_protocol { #define FIRST_CODE 0x55 #define END_CODE 0xBB /** * @brief 截取指定位数据并赋值 * 小端模式: 高位在前(低内存),低位在后(高内存) * */ #define SET_SUB_BYTES1(target, data) target = (data & 0xFF) #define SET_SUB_BYTES2(target, data) target |= ((data << 8) & 0xFF00) /** * @brief 查表法crc8校验 * * @param buf 输入数组 * @param len 数组长度 * @return uint8_t */ uint8_t getcrc8tab(const uint8_t *buf, int len); /** * @brief 直接计算法crc8校验 * * @param buf 输入数组 * @param len 数组长度 * @return uint8_t */ uint8_t getCrc8(const uint8_t *buf, int len); /** * @brief 将数据进行转义 * * @param frame 帧数据 * @param result 结果 * @param len 长度 * @return int 转义完成后新的帧的大小 */ int frame_packing(const uint8_t *buf, uint8_t *frame, uint8_t len, uint8_t func); /** * @brief 将数据帧进行反转义 * * @param frame 帧数据 * @param result 结果 * @param len 长度 * @return int */ int inverse_frame(uint8_t *result, const uint8_t *frame, uint8_t len, uint8_t& func); } // namespace fish_protocol #endif // _PROTO_UTILS_H_

serial_protocol.h

/** * @brief 文件描述:待完善 * @author 小鱼 (fishros@foxmail.com) * @version V1.0.0 * @date 2022-07-24 * @copyright 版权所有:(鱼香ROS)fishros.org.cn */ #ifndef _FISH_PROTOCOL_SERIAL_PROTOCOL_H_ #define _FISH_PROTOCOL_SERIAL_PROTOCOL_H_ #include <unistd.h> #include <boost/asio.hpp> #include <boost/bind.hpp> #include <boost/system/error_code.hpp> #include <boost/system/system_error.hpp> #include <boost/thread.hpp> #include <iostream> #include <string> namespace serial_protocol{ class ProtocolConfig { public: // serial int serial_baut_; std::string serial_address_; ProtocolConfig& operator=(const ProtocolConfig& config) { serial_baut_ = config.serial_baut_; serial_address_ = config.serial_address_; return *this; }; public: ProtocolConfig(){}; ~ProtocolConfig(){}; }; enum flush_type { flush_receive = TCIFLUSH, flush_send = TCOFLUSH, flush_both = TCIOFLUSH }; class SerialProtocol{ using spb = boost::asio::serial_port_base; protected: std::function<void(const std::uint8_t*, const std::uint8_t)> recv_uint8_callback; ProtocolConfig protocol_config_; private: void _asyncReadSomeData(); void _initSerialProtocol(); void _recvDataCallback(const boost::system::error_code& error, size_t bytes_transferred); void flush_serial_port( boost::asio::serial_port& serial_port, flush_type what, boost::system::error_code& error); public: SerialProtocol(const ProtocolConfig& protocol_config) : io_service_(), serial_port_(io_service_) { this->protocol_config_ = protocol_config; _initSerialProtocol(); } ~SerialProtocol(); int ProtocolSendString(const std::string& data); int ProtocolSenduint8_t(const std::uint8_t* data, const std::uint8_t len); void SetDataRecvCallback(std::function<void(const std::uint8_t*, const std::uint8_t)> callback); private: unsigned char recv_data_buffer_[1024] = {0}; boost::asio::io_service io_service_; boost::asio::serial_port serial_port_; }; } // namespace fish_protocol #endif // _FISH_PROTOCOL_SERIAL_PROTOCOL_H_