网站备案跟域名有什么关系找投资项目的网站

当前位置: 首页 > news >正文

网站备案跟域名有什么关系,找投资项目的网站,制作企业网站页面实训报告,门户网站开发招标【QT】基于UDP/TCP/串口的Ymodom通讯协议客户端 前言Ymodom实现QT实现开源库的二次开发-1开源库的二次开发-2 串口方式实现TCP方式实现UDP方式实现补充#xff1a;文件读取补充#xff1a;QT 封装成EXE 前言 Qt 运行环境 Desktop_Qt_5_11_2_MSVC2015_64bit #xff0c;基于… 【QT】基于UDP/TCP/串口的Ymodom通讯协议客户端 前言Ymodom实现QT实现开源库的二次开发-1开源库的二次开发-2 串口方式实现TCP方式实现UDP方式实现补充文件读取补充QT 封装成EXE 前言 Qt 运行环境 Desktop_Qt_5_11_2_MSVC2015_64bit 基于Ymodom通讯协议开发客户端实现与设备的UDP /TCP /串口通讯。在前期测试过程中主要用了网络调试助手、串口调试助手、Virtual Serial Port Driver虚拟串口。 对Ymodom的了解过程中主要学习了博文Ymodem协议详解 、【嵌入式——QT】QT集成Ymodem协议使用UDP进行传输、qt随手记——ymodem协议使用里面对协议的规则进行了详细的讲述方便理解Ymodom 是什么。 在没有设备的情况下用虚拟设备进行测试发一个文件对应的指令如下

43 ( C)

06 ( Ack) 43 ( C) ……

06 ( Ack)

04 (收 Eot) 15 NAK 04 (收 Eot) 06 ( Ack)

43 ( C)

06 ( Ack)Ymodom实现 该协议包括起始帧、数据帧、结束帧状态变量流转的方向如下 YmodemFileTransmit.h status StatusEstablish-StatusTransmit -StatusFinishymodem.h stage: StageNone- StageEstablishing - StageEstablished - StageTransmitting-StageFinishing-StageFinished -StageNone code: CodeNone里面数据帧要注意传1024或128规则如下 数据大于128则按1024传数据小于128则按128传。 关于数据填充看网上说是以0x1A填充但实际测试发现是按照00填充的。 整个指令流程如下
接收方先发 43C发送方发 文件名文件大小接收方发 06Ack接收方发 43C发送方开始一包包数据的发送每发一包得等接收方回复 06(Ack)后再开始下一包当发完最后一包数据后发送方发 04 (Eot)接收方发 15 NAK发送方再发 04 (Eot)接收方发 06 ( Ack)接收方发 43C开始下一个文件传输如果不在发文件则发送方发一包00数据接收方发 06Ack结束传输。 在传输中使用的指令主要如下 CodeNone 0x00,CodeSoh 0x01, //128字节数据包CodeStx 0x02, //1024字节数据包CodeEot 0x04, //文件传输结束指令CodeAck 0x06, //接收正确指令CodeNak 0x15, //重传当前数据包请求指令CodeCan 0x18, //取消传输指令连续发送5个该命令终止传输CodeC 0x43, //请求数据包CodeA1 0x41,CodeA2 0x61QT实现 主要用得是Ymodem的开源库函数然后对其进行二次开发。 开源库的二次开发-1 里面最主要的一个变更是在传输完成进行二次回复确定时接收方会发一个Ack过来此时会调用transmitStageFinishing()不难发现里面并没有关于Ack 的处理此时会调用default: 处理 如果一直没有发C指令会不断累加定时器调用次数由于设置一次定时器10ms间隔5s后会重发04 (Eot)指令如果超过设置的最大响应时间25s会写取消传输指令。当然正常是不会有问题的但是在测试时候由于输入需要时间时而会出现重发的情况而且要注意这里的5s是从第二次发完 EOT 后开始计算的。因此对transmitStageFinishing() 增加Ack 处理
case CodeAck://sht-240813 add :避免发完ACK后C回复不及时导致多发EOT指令{timeCount 0;errorCount 0;dataCount 0;break;}开源库的二次开发-2 第二个最大变更是关于读取回复指令的长度设置在部分的设备中会存在回复指令加 0D 0A 的情况用于分隔指令因为接收方回复指令中存在连续发2个指令的情况如果有了0D 0A 的加入可以直接 以 06 0D 0A 43 0D 0A 方式发指令当然也可以不用 0D 0A 单纯只是用 06 43 或者间隔一下时间分别发都可以。 既然出现了加 0D 0A 情况那就要对读取进行二次处理在receivePacket() 中将read((rxBuffer[0]), 1)修改为read((rxBuffer[0]), 3)。 串口方式实现 最主要的就是串口收发一定要写好Ymodom 部分主要就是进行虚函数复写就行。 QT serialport#include QSerialPort QSerialPort * serialPort;if (serialPort-open(QSerialPort::ReadWrite) true){//成功打开串口return true;}else{//串口打开失败return false;}//读写指定长度len,存入buff uint32_t YmodemFileTransmitSerial::read(uint8_t* buff, uint32_t len) {return serialPort-read((char)buff, len); }uint32_t YmodemFileTransmitSerial::write(uint8_t buff, uint32_t len) {return serialPort-write((char*)buff, len); }TCP方式实现 QT network#include QTcpSocket QTcpSocket * tcpClient;这里一定要注意平常会有信号触发的方式进行连接成功的判断但为了减少跳转以及代码逻辑的统一这边采用了waitForConnected去进行连接成功与否的判断设置的30000为等待连接时间超过了则返回false。 tcpClient-connectToHost(targetAddr,serverPort);if(tcpClient-waitForConnected(30000)){//连接成功return true;}else{return false;}这里也一定要注意平常进行数据接收我们一般也是采用信号触发的方式但这边不是用得read和write传参分别是存储信息的地址和读取长度返回实际读取长度。当发来一共10个字节然后读了3个后面7个字节会缓存可以下次读因此针对开源库的二次开发-2主要就是影响这里加了0D 0A在读1字节就会有问题。 //———–虚函数实现读取内容—- uint32_t YmodemFileTransmitTcp::read(uint8_t *buff, uint32_t len) {QByteArray array tcpClient-read(len);uint32_t lenArray array.size();uint32_t lenBuff len;uint32_t length qMin(lenArray, lenBuff);memcpy(buff, array, length);return length; } //———–虚函数实现写内容—- uint32_t YmodemFileTransmitTcp::write(uint8_t buff, uint32_t len) {int ret tcpClient-write((char)buff, len);return ret; }UDP方式实现 QT network#include QUdpSocket QUdpSocket* udpClient;UDP也是一样的情况由于不连接通讯倒是不用增加连接步骤但是接收信息不用常用的信号触发实现也是直接用read和write其目的其实都是为了方便代码编写更好使用Ymodom 库确保三种方式逻辑编写规则统一。 //———–虚函数实现读取内容—- uint32_t YmodemFileTransmit::read(uint8_t* buff, uint32_t len) {QNetworkDatagram datagram udpClient-receiveDatagram(len);QByteArray array datagram.data();uint32_t lenArray array.size();uint32_t lenBuff len;uint32_t length qMin(lenArray, lenBuff);memcpy(buff, array, length);return length; } //———–虚函数实现写内容—- uint32_t YmodemFileTransmit::write(uint8_t* buff, uint32_t len) {QHostAddress targetAddr(serverIp);int ret udpClient-writeDatagram((char)buff, len, targetAddr, serverPort);return ret; }补充文件读取 在开发中需要涉及到文件的读取为了方便后续的复用这边也做一个整理 找文件存文件路径 #include QFileDialog #include QMessageBoxvoid BootLoader::on_pushButtonBrowse_clicked() {QString curPath QDir::currentPath();ui-lineEditFilePath-setText(QFileDialog::getOpenFileName(this, u8打开文件, curPath, u8任意文件 (.))); }读文件 #include QFile QFile file;YmodemFileTransmit::YmodemFileTransmit(QObject* parent) :QObject(parent),file(new QFile) { } //————-设置读取文件名——– void YmodemFileTransmit::setFileName(const QString name) {file-setFileName(name); }//获取文件名 文件大小 if(file-open(QFile::ReadOnly) true) {QFileInfo fileInfo(file);fileSize fileInfo.size();fileCount 0;//将文件名fileInfo.fileName().toLocal8Bit().data()存buffstrcpy((char)buff, fileInfo.fileName().toLocal8Bit().data());//将文件大小QByteArray::number(fileInfo.size()).data())存buffstrcpy((char)buff fileInfo.fileName().toLocal8Bit().size() 1, QByteArray::number(fileInfo.size()).data());} //读YMODEM_PACKET_1K_SIZE最大长度的内容存buff返回读取的实际长度。 //而且只要没有file-close();file-read 会移动文件游标读完一次后面接着读fileCount file-read((char)buff, YMODEM_PACKET_1K_SIZE);补充QT 封装成EXE 可以查看大神的博文【QT中如何生成导出.exe可执行文件并打包给其他人使用】里面讲得很清晰。