怎么在网上做公司的网站,家庭电影网站建设,影视公司名字,网站开发最好用什么语言【嵌入式——QT】QT集成Ymodem协议使用UDP进行传输 Ymodem协议帧的数据格式帧头包号校验 通讯过程握手信号起始帧数据帧结束帧代码块 Ymodem命令 QT实现YmodemFileTransmit.hYmodemFileTransmit.cppBootLoader.hBootLoader.cppYmodem协议源码 Ymodem协议
帧的数据格式
帧头、… 【嵌入式——QT】QT集成Ymodem协议使用UDP进行传输 Ymodem协议帧的数据格式帧头包号校验 通讯过程握手信号起始帧数据帧结束帧代码块 Ymodem命令 QT实现YmodemFileTransmit.hYmodemFileTransmit.cppBootLoader.hBootLoader.cppYmodem协议源码 Ymodem协议
帧的数据格式
帧头、包号、包号反码、数据、校验。
帧头包号包号反码数据校验高位校验低位Soh/Stx0x000xFFDATACRC_HCRC_L
帧头
以Soh(0x01)开始的数据包信息块是128字节该帧类型总长度为133字节。 以Stx(0x02)开始的数据包信息块是1024字节该帧类型总长度为1029字节。
包号
包号是为数据块的编号将要传送的数据进行分块编号只有一个字节范围为0~255。大于255的则归零重复计算。
校验
Ymodem采用的是CRC16校验算法校验值为2字节。
uint16_t Ymodem::crc16(uint8_t *buff, uint32_t len)
{uint16_t crc 0;while(len--){crc ^ (uint16_t)(*(buff)) 8;for(int i 0; i 8; i){if(crc 0x8000){crc (crc 1) ^ 0x1021;}else{crc crc 1;}}}return crc;
}通讯过程
握手信号
发送方收到接收方发送的CodeC(0x43)命令后才可以开始发送起始帧。
起始帧
帧头包号包号反码文件名称文件大小填充区校验高位校验低位CodeSoh0x000xFFFileName0x00FileSize0x00NULL(0x00)CRC_HCRC_L
文件名称后必须添加0x00作为结束文件大小值后必须加0x00作为结束余下的位置以0x00填充。
数据帧
帧头包号包号反码有效数据校验高位校验低位CodeSoh/CodeStx0x000xFFDATACRC_HCRC_L
对于SOH帧若余下数据小于128字节则以0x1A填充该帧长度仍为133字节 对于STX帧需考虑几种情况
余下数据等于1024字节以1029长度帧发送余下数据小于1024字节但大于128字节以1029字节帧长度发送无效数据以0x1A填充余下数据等于128字节以133字节帧长度发送余下数据小于128字节以133字节帧长度发送无效数据以0x1A填充
结束帧
帧头包号包号反码数据区校验高位校验低位CodeSoh0x000xFFDATACRC_HCRC_L数据区校验都以0x00填充。
代码块
void Ymodem::transmit()
{switch(stage){case StageNone:{transmitStageNone();break;}case StageEstablishing:{transmitStageEstablishing();break;}case StageEstablished:{transmitStageEstablished();break;}case StageTransmitting:{transmitStageTransmitting();break;}case StageFinishing:{transmitStageFinishing();break;}default:{transmitStageFinished();}}
}
Ymodem命令
CodeEot、CodeCan由发送端发送 CodeAck、CodeNak、CodeC由接收端发送
命令命令码备注CodeNone0x00CodeSoh0x01133字节长度CodeStx0x021024字节长度CodeEot0x04文件传输结束指令CodeAck0x06接收正确指令CodeNak0x15重传当前数据包请求指令CodeCan0x18取消传输指令连续发送5个该命令终止传输CodeC0x43字符CCodeA10x41CodeA20x61
QT实现
YmodemFileTransmit.h
#ifndef YMODEMFILETRANSMIT_H
#define YMODEMFILETRANSMIT_H#include QFile
#include QTimer
#include QObject
#include Ymodem.h
#include QUdpSocketclass YmodemFileTransmit : public QObject, public Ymodem
{Q_OBJECTpublic:explicit YmodemFileTransmit(QObject* parent nullptr);~YmodemFileTransmit();void setFileName(const QString name);void setIpAddress(const QString ip);void setPortNumber(quint16 port);bool startTransmit();void stopTransmit();int getTransmitProgress();Status getTransmitStatus();signals:void transmitProgress(int progress);void transmitStatus(YmodemFileTransmit::Status status);public slots:void readTimeOut();void writeTimeOut();private:Code callback(Status status, uint8_t* buff, uint32_t* len);uint32_t read(uint8_t* buff, uint32_t len);uint32_t write(uint8_t* buff, uint32_t len);QFile* file;QTimer* readTimer;QTimer* writeTimer;QUdpSocket* udpClient;int progress;Status status;uint64_t fileSize;uint64_t fileCount;QString serverIp;uint16_t serverPort;
};#endif // YMODEMFILETRANSMIT_H
YmodemFileTransmit.cpp
#include YmodemFileTransmit.h
#include QFileInfo
#include QNetworkDatagram
#include QThread#define READ_TIME_OUT (10)
#define WRITE_TIME_OUT (1000)YmodemFileTransmit::YmodemFileTransmit(QObject* parent) :QObject(parent),file(new QFile),readTimer(new QTimer),writeTimer(new QTimer),udpClient(new QUdpSocket)
{setTimeDivide(499);setTimeMax(5);setErrorMax(999);connect(readTimer, SIGNAL(timeout()), this, SLOT(readTimeOut()));connect(writeTimer, SIGNAL(timeout()), this, SLOT(writeTimeOut()));
}YmodemFileTransmit::~YmodemFileTransmit()
{delete file;delete readTimer;delete writeTimer;delete udpClient;
}void YmodemFileTransmit::setFileName(const QString name)
{file-setFileName(name);
}void YmodemFileTransmit::setIpAddress(const QString ip)
{serverIp ip;
}void YmodemFileTransmit::setPortNumber(quint16 port)
{serverPort port;
}bool YmodemFileTransmit::startTransmit()
{progress 0;status StatusEstablish;QByteArray array;array.append(0x02);array.append(0x01);array.append(0xFF);array.append(0x07);array.append(0x01);array.append(0x09);array.append(0x03);QHostAddress targetAddr(serverIp);int ret udpClient-writeDatagram(array, targetAddr, serverPort);if(ret 0) {QThread::msleep(50);readTimer-start(READ_TIME_OUT);return true;} else {return false;}
}void YmodemFileTransmit::stopTransmit()
{file-close();abort();status StatusAbort;writeTimer-start(WRITE_TIME_OUT);
}int YmodemFileTransmit::getTransmitProgress()
{return progress;
}Ymodem::Status YmodemFileTransmit::getTransmitStatus()
{return status;
}void YmodemFileTransmit::readTimeOut()
{readTimer-stop();transmit();if((status StatusEstablish) || (status StatusTransmit)) {readTimer-start(READ_TIME_OUT);}
}void YmodemFileTransmit::writeTimeOut()
{writeTimer-stop();transmitStatus(status);
}Ymodem::Code YmodemFileTransmit::callback(Status status, uint8_t* buff, uint32_t* len)
{switch(status) {case StatusEstablish:if(file-open(QFile::ReadOnly) true) {QFileInfo fileInfo(*file);fileSize fileInfo.size();fileCount 0;strcpy((char*)buff, fileInfo.fileName().toLocal8Bit().data());strcpy((char*)buff fileInfo.fileName().toLocal8Bit().size() 1, QByteArray::number(fileInfo.size()).data());*len YMODEM_PACKET_SIZE;YmodemFileTransmit::status StatusEstablish;transmitStatus(StatusEstablish);return CodeAck;} else {YmodemFileTransmit::status StatusError;writeTimer-start(WRITE_TIME_OUT);return CodeCan;}case StatusTransmit:if(fileSize ! fileCount) {if((fileSize - fileCount) YMODEM_PACKET_SIZE) {fileCount file-read((char*)buff, YMODEM_PACKET_1K_SIZE);*len YMODEM_PACKET_1K_SIZE;} else {fileCount file-read((char*)buff, YMODEM_PACKET_SIZE);*len YMODEM_PACKET_SIZE;}progress (int)(fileCount * 100 / fileSize);YmodemFileTransmit::status StatusTransmit;transmitProgress(progress);transmitStatus(StatusTransmit);return CodeAck;} else {YmodemFileTransmit::status StatusTransmit;transmitStatus(StatusTransmit);return CodeEot;}case StatusFinish:file-close();YmodemFileTransmit::status StatusFinish;writeTimer-start(WRITE_TIME_OUT);return CodeAck;case StatusAbort:file-close();YmodemFileTransmit::status StatusAbort;writeTimer-start(WRITE_TIME_OUT);return CodeCan;case StatusTimeout:YmodemFileTransmit::status StatusTimeout;writeTimer-start(WRITE_TIME_OUT);return CodeCan;default:file-close();YmodemFileTransmit::status StatusError;writeTimer-start(WRITE_TIME_OUT);return CodeCan;}
}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;
}
BootLoader.h
#ifndef BOOTLOADER_H
#define BOOTLOADER_H#include QWidget
#include QUdpSocket
#include YmodemFileTransmit.hQT_BEGIN_NAMESPACE
namespace Ui
{class BootLoader;
}
QT_END_NAMESPACEclass BootLoader : public QWidget
{Q_OBJECTpublic:BootLoader(QWidget* parent nullptr);~BootLoader();YmodemFileTransmit* ymodemFileTransmit;public slots:void on_pushButtonConnect_clicked();void on_pushButtonBrowse_clicked();void on_pushButtonSend_clicked();void readData();void transmitProgress(int progress);void transmitStatus(YmodemFileTransmit::Status status);private:Ui::BootLoader* ui;bool firemwareTransmitStatus;QUdpSocket* udpClient;
};
#endif // BOOTLOADER_H
BootLoader.cpp
#include BootLoader.h
#include ui_BootLoader.h
#include QByteArray
#include QDebug
#include QNetworkDatagram
#include QFileDialog
#include QMessageBox#define SERVER_ADDR 192.168.xxx.xxx
#define SERVER_PORT 4002BootLoader::BootLoader(QWidget* parent): QWidget(parent), ui(new Ui::BootLoader)
{ui-setupUi(this);this-setWindowTitle(tr(EthernetYmodem));this-setWindowIcon(QIcon(:/images/main.ico));ymodemFileTransmit new YmodemFileTransmit();connect(ymodemFileTransmit, SIGNAL(transmitProgress(int)), this, SLOT(transmitProgress(int)));connect(ymodemFileTransmit, SIGNAL(transmitStatus(YmodemFileTransmit::Status)), this, SLOT(transmitStatus(YmodemFileTransmit::Status)));udpClient new QUdpSocket(this);connect(udpClient, QUdpSocket::readyRead, this, BootLoader::readData);firemwareTransmitStatus false;ui-pushButtonSend-setEnabled(false);ui-pushButtonConnect-setEnabled(true);
}BootLoader::~BootLoader()
{delete ui;
}void BootLoader::on_pushButtonConnect_clicked()
{QByteArray array;array.append(0x02);array.append(0x01);array.append(0xFF);array.append(0x07);array.append(0x01);array.append(0x09);array.append(0x03);QHostAddress targetAddr(SERVER_ADDR);int ret udpClient-writeDatagram(array, targetAddr, SERVER_PORT);qDebug()retret;
}void BootLoader::on_pushButtonBrowse_clicked()
{QString curPath QDir::currentPath();ui-lineEditFilePath-setText(QFileDialog::getOpenFileName(this, u8打开文件, curPath, u8任意文件 (*.*)));
}void BootLoader::on_pushButtonSend_clicked()
{udpClient-abort();if(ui-lineEditFilePath-text().isEmpty()) {QMessageBox::warning(this, tr(!!!), tr(Please select a file!));return;}if(firemwareTransmitStatus false) {ymodemFileTransmit-setFileName(ui-lineEditFilePath-text());ymodemFileTransmit-setIpAddress(SERVER_ADDR);ymodemFileTransmit-setPortNumber(SERVER_PORT);if(ymodemFileTransmit-startTransmit() true) {firemwareTransmitStatus true;ui-progressBar-setValue(0);ui-pushButtonSend-setText(tr(Cancel));ui-pushButtonConnect-setEnabled(false);} else {QMessageBox::warning(this, tr(Failure), tr(File failed to send!), tr(Closed));ui-pushButtonSend-setText(tr(Send));ui-pushButtonConnect-setEnabled(true);}} else {ymodemFileTransmit-stopTransmit();ui-pushButtonSend-setText(tr(Send));ui-pushButtonConnect-setEnabled(true);}
}void BootLoader::readData()
{while(udpClient-hasPendingDatagrams()) {QNetworkDatagram datagram udpClient-receiveDatagram();QByteArray receivedData datagram.data();qDebug() Received data: receivedData;if(receivedData.size() 0 receivedData[0] (char)0x43) {ui-pushButtonSend-setEnabled(true);ui-pushButtonConnect-setEnabled(false);}}
}void BootLoader::transmitProgress(int progress)
{ui-progressBar-setValue(progress);
}void BootLoader::transmitStatus(Ymodem::Status status)
{switch(status) {case YmodemFileTransmit::StatusEstablish:break;case YmodemFileTransmit::StatusTransmit:break;case YmodemFileTransmit::StatusFinish:firemwareTransmitStatus false;QMessageBox::information(this, tr(OK), tr(Upgrade successed!), QMessageBox::Yes);ui-pushButtonSend-setText(tr(Send));ui-pushButtonSend-setEnabled(false);ui-pushButtonConnect-setEnabled(true);break;case YmodemFileTransmit::StatusAbort:firemwareTransmitStatus false;QMessageBox::warning(this, tr(failure), tr(File failed to send!), tr(Closed));break;case YmodemFileTransmit::StatusTimeout:firemwareTransmitStatus false;QMessageBox::warning(this, tr(failure), tr(File failed to send!), tr(Closed));break;default:firemwareTransmitStatus false;QMessageBox::warning(this, tr(failure), tr(File failed to send!), tr(Closed));}
}
Ymodem协议源码
源码链接