【嵌入式——QT】Ymodem协议源码

慈云数据 7个月前 (05-09) 技术支持 39 0

Ymodem.h

/**
  * This program is free software: you Can Redistribute it and/or modify
  * it under the terms of the GNU General Public LiceNSE as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the IMPlied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see .
  *
  ******************************************************************************
  */
#ifndef __YMODEM_H
#define __YMODEM_H
/* Header includes -----------------------------------------------------------*/
#include 
/* Macro definitions ---------------------------------------------------------*/
#define YMODEM_PACKET_HEADER    (3)
#define YMODEM_PACKET_TRAILER   (2)
#define YMODEM_PACKET_OVERHEAD  (YMODEM_PACKET_HEADER + YMODEM_PACKET_TRAILER)
#define YMODEM_PACKET_SIZE      (128)
#define YMODEM_PACKET_1K_SIZE   (1024)
#define YMODEM_CODE_CAN_NUMBER  (5)
/* Type definitions ----------------------------------------------------------*/
class Ymodem
{
public:
  enum Code
  {
    CodeNone = 0x00,
    CodeSoh  = 0x01,
    CodeStx  = 0x02,
    CodeEot  = 0x04,
    CodeAck  = 0x06,
    CodeNak  = 0x15,
    CodeCan  = 0x18,
    CodeC    = 0x43,
    CodeA1   = 0x41,
    CodeA2   = 0x61
  };
  enum Stage
  {
    StageNone,
    StageEstablishing,
    StageEstablished,
    StageTransmitting,
    StageFinishing,
    StageFinished
  };
  enum Status
  {
    StatusEstablish,
    StatusTransmit,
    StatusFinish,
    StatuSAbort,
    StatusTimeout,
    StatusError
  };
  Ymodem(uint32_t timeDivide = 499, uint32_t timeMax = 5, uint32_t errorMax = 999);
  void setTimeDivide(uint32_t timeDivide);
  uint32_t getTimeDivide();
  void setTimeMax(uint32_t timeMax);
  uint32_t getTimeMax();
  void setErrorMax(uint32_t errorMax);
  uint32_t getErrorMax();
  void receive();
  void transmit();
  void abort();
private:
  Code receivePacket();
  void receiveStageNone();
  void receiveStageEstablishing();
  void receiveStageEstablished();
  void receiveStageTransmitting();
  void receiveStageFinishing();
  void receiveStageFinished();
  void transmitStageNone();
  void transmitStageEstablishing();
  void transmitStageEstablished();
  void transmitStageTransmitting();
  void transmitStageFinishing();
  void transmitStageFinished();
  uint16_t crc16(uint8_t *buff, uint32_t len);
  virtual Code callback(Status status, uint8_t *buff, uint32_t *len) = 0;
  virtual uint32_t read(uint8_t *buff, uint32_t len)  = 0;
  virtual uint32_t write(uint8_t *buff, uint32_t len) = 0;
  uint32_t timeDivide;
  uint32_t timeMax;
  uint32_t errorMax;
  uint32_t timeCount;
  uint32_t errorCount;
  uint8_t  dataCount;
  Code  code;
  Stage stage;
  uint8_t  rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD];
  uint8_t  txBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD];
  uint32_t rxLength;
  uint32_t txLength;
};
/* Variable declarations -----------------------------------------------------*/
/* Variable definitions ------------------------------------------------------*/
/* Function declarations -----------------------------------------------------*/
/* Function definitions ------------------------------------------------------*/
#endif /* __YMODEM_H */

Ymodem.cpp

/**
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see .
  *
  ******************************************************************************
  */
/* Header includes -----------------------------------------------------------*/
#include "Ymodem.h"
#include 
/* Macro definitions ---------------------------------------------------------*/
/* Type definitions ----------------------------------------------------------*/
/* Variable declarations -----------------------------------------------------*/
/* Variable definitions ------------------------------------------------------*/
/* Function declarations -----------------------------------------------------*/
/* Function definitions ------------------------------------------------------*/
/**
  * @brief  Ymodem constructor.
  * @param  [in] timeDivide: The fractional factor of the time the ymodem is called.
  * @param  [in] timeMax:    The maximum time when calling the ymodem.
  * @param  [in] errorMax:   The maximum error count when calling the ymodem.
  * @note   The longest waiting time = call time / (@timeDivide + 1) * (@timeMax + 1).
  * @return None.
  */
Ymodem::Ymodem(uint32_t timeDivide, uint32_t timeMax, uint32_t errorMax)
{
  this->;timeDivide = timeDivide;
  this->timeMax    = timeMax;
  this->errorMax   = errorMax;
  this->timeCount  = 0;
  this->errorCount = 0;
  this->dataCount  = 0;
  this->code       = CodeNone;
  this->stage      = StageNone;
}
/**
  * @brief  Set the fractional factor of the time the ymodem is called.
  * @param  [in] timeDivide: The fractional factor of the time the ymodem is called.
  * @return None.
  */
void Ymodem::setTimeDivide(uint32_t timeDivide)
{
  this->timeDivide = timeDivide;
}
/**
  * @brief  Get the fractional factor of the time the ymodem is called.
  * @param  None.
  * @return The fractional factor of the time the ymodem is called.
  */
uint32_t Ymodem::getTimeDivide()
{
  return timeDivide;
}
/**
  * @brief  Set the maximum time when calling the ymodem.
  * @param  [in] timeMax: The maximum time when calling the ymodem.
  * @return None.
  */
void Ymodem::setTimeMax(uint32_t timeMax)
{
  this->timeMax = timeMax;
}
/**
  * @brief  Get the maximum time when calling the ymodem.
  * @param  None.
  * @return The maximum time when calling the ymodem.
  */
uint32_t Ymodem::getTimeMax()
{
  return timeMax;
}
/**
  * @brief  Set the maximum error count when calling the ymodem.
  * @param  [in] errorMax: The maximum error count when calling the ymodem.
  * @return None.
  */
void Ymodem::setErrorMax(uint32_t errorMax)
{
  this->errorMax = errorMax;
}
/**
  * @brief  Get the maximum error count when calling the ymodem.
  * @param  None.
  * @return The maximum error count when calling the ymodem.
  */
uint32_t Ymodem::getErrorMax()
{
  return errorMax;
}
/**
  * @brief  Ymodem receive.
  * @param  None.
  * @return None.
  */
void Ymodem::receive()
{
  switch(stage)
  {
    case StageNone:
    {
      receiveStageNone();
      break;
    }
    case StageEstablishing:
    {
      receiveStageEstablishing();
      break;
    }
    case StageEstablished:
    {
      receiveStageEstablished();
      break;
    }
    case StageTransmitting:
    {
      receiveStageTransmitting();
      break;
    }
    case StageFinishing:
    {
      receiveStageFinishing();
      break;
    }
    default:
    {
      receiveStageFinished();
    }
  }
}
/**
  * @brief  Ymodem transmit.
  * @param  None.
  * @return None.
  */
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();
    }
  }
}
/**
  * @brief  Ymodem abort.
  * @param  None.
  * @return None.
  */
void Ymodem::abort()
{
  timeCount  = 0;
  errorCount = 0;
  dataCount  = 0;
  code       = CodeNone;
  stage      = StageNone;
  for(txLength = 0; txLength  0)
    {
      if(rxBuffer[0] == CodeSoh)
      {
        uint32_t len = read(&(rxBuffer[1]), YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1);
        if(len  timeMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  timeMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  timeMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength > 8);
        txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0);
        txLength                                        = txLength + YMODEM_PACKET_OVERHEAD;
        write(txBuffer, txLength);
      }
      else
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  timeMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  errorMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  errorMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  YMODEM_PACKET_SIZE ? CodeStx : CodeSoh;
          txBuffer[1]                                     = 0x01;
          txBuffer[2]                                     = 0xFE;
          txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8);
          txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0);
          txLength                                        = txLength + YMODEM_PACKET_OVERHEAD;
          break;
        }
        case CodeEot:
        {
          timeCount   = 0;
          errorCount  = 0;
          dataCount   = 2;
          code        = CodeNone;
          stage       = StageEstablished;
          txBuffer[0] = CodeEot;
          txLength    = 1;
          write(txBuffer, txLength);
          break;
        }
        default:
        {
          timeCount  = 0;
          errorCount = 0;
          dataCount  = 0;
          code       = CodeNone;
          stage      = StageNone;
          for(txLength = 0; txLength  timeMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  errorMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  YMODEM_PACKET_SIZE ? CodeStx : CodeSoh;
          txBuffer[1]                                     = dataCount;
          txBuffer[2]                                     = 0xFF - dataCount;
          txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8);
          txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0);
          txLength                                        = txLength + YMODEM_PACKET_OVERHEAD;
          write(txBuffer, txLength);
          break;
        }
        case CodeEot:
        {
          timeCount   = 0;
          errorCount  = 0;
          dataCount   = 0;
          code        = CodeNone;
          stage       = StageFinishing;
          txBuffer[0] = CodeEot;
          txLength    = 1;
          write(txBuffer, txLength);
          break;
        }
        default:
        {
          timeCount  = 0;
          errorCount = 0;
          dataCount  = 0;
          code       = CodeNone;
          stage      = StageNone;
          for(txLength = 0; txLength  timeMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength > 8);
      txBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0);
      txLength   = YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD;
      write(txBuffer, txLength);
      break;
    }
    case CodeA1:
    case CodeA2:
    case CodeCan:
    {
      timeCount  = 0;
      errorCount = 0;
      dataCount  = 0;
      code       = CodeNone;
      stage      = StageNone;
      callback(StatusAbort, NULL, NULL);
      break;
    }
    default:
    {
      timeCount++;
      if((timeCount / (timeDivide + 1)) > timeMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  errorMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength  timeMax)
      {
        timeCount  = 0;
        errorCount = 0;
        dataCount  = 0;
        code       = CodeNone;
        stage      = StageNone;
        for(txLength = 0; txLength 
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon