1 概述
XMODEM协议是一种使用拨号调制解调器的个人计算机通信中广泛使用的异步文件运输协议。这种协议以128字节块的形式传输数据,并且每个块都使用一个校验和过程来进行错误检测。使用循环冗余校验的与XMODEM相应的一种协议称为XMODEM-CRC。还有一种是XMODEM-1K,它以1024字节一块来传输数据。YMODEM也是一种XMODEM的实现。它包括XMODEM-1K的所有特征,另外在一次单一会话期间为发送一组文件,增加了批处理文件传输模式。
本文利用C++实现XYModem-1K协议,并利用Qt串口类QSerialPort实现数据读写。
3 实现
YModem_5">3.3 YModem
该模块定义和实现了YModem协议。
YModem_7">3.3.1 YModem定义
class YModem : public XModem
{
public:YModem();
protected:bool tx_start(std::string const& filename, std::string const& filesize);bool tx_end();
private:void do_start(std::string const& filename, std::string const& filesize);;void do_end();
};
函数列表:
- tx_start 发送开始帧,并确认状态
- tx_end 发送结束帧,并确认状态
- do_start 发送开始帧
- do_end 发送结束帧
YModem_27">3.3.2 YModem实现
3.3.2.1 tx_start
bool YModem::tx_start(std::string const& filename, std::string const& filesize)
{do_start(filename, filesize);uint8_t code = get_code();if(code != ACK)return false;code = get_code();if(code != C)return false;return true;
}
函数流程:
- 发送开始帧
- 获取操作码
- 获得非ACK操作码,失败返回
- 获取操作码
- 获得确认操作码C,成功返回,否则失败返回
3.3.2.2 tx_end
bool YModem::tx_end()
{do_end();if(get_code() == ACK)return true;return false;
}
函数流程:
- 发送结束帧
- 获取操作码
- 如果是ACK码,成功返回,否则失败返回
3.3.2.3 do_start
void YModem::do_start(std::string const& filename, std::string const& filesize)
{uint8_t frame[FRAME_SIZE1] = { SOH, 0, not_id(0) };memcpy(&frame[FRAME_HEAD], filename.c_str(), filename.size());memcpy(&frame[FRAME_HEAD + filename.size() + 1], filesize.c_str(), filesize.size());uint16_t crc = crc16(frame + FRAME_HEAD, SIZE1);frame[FRAME_HEAD + SIZE1] = (uint8_t)(crc >> 8);frame[FRAME_HEAD + SIZE1 + 1] = (uint8_t)(crc >> 0);write(frame, sizeof(frame));next_id();
}
函数流程:
- 构造开始帧头
- 设置文件名称和文件大小
- 设置CRC值
- 发送开始帧
3.3.2.4 do_end
void YModem::do_end()
{uint8_t frame[FRAME_SIZE1] = { SOH, 0, not_id(0) };uint16_t crc = crc16(frame + FRAME_HEAD, SIZE1);frame[FRAME_HEAD + SIZE1] = (uint8_t)(crc << 8);frame[FRAME_HEAD + SIZE1 + 1] = (uint8_t)(crc << 0);write(frame, FRAME_SIZE1);
}
函数流程: