硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1277|回复: 1
收起左侧

YMODEM协议串口文件传输

[复制链接]

19

主题

15

回帖

72

积分

初级会员

积分
72
发表于 2018-3-7 20:26:16 | 显示全部楼层 |阅读模式
YMODEM协议串口文件传输
转载来源:YMODEM协议串口文件传输


GitHub仓库:https://github.com/XinLiGitHub/SerialPortYmodem
PS:博文不再更新,后续更新会在GitHub仓库进行。


    串口通过YMODEM协议进行文件传输。程序中涉及到YMODEM协议知识,详细介绍见维基百科[YMODEM](https://en.wikipedia.org/wiki/YMODEM)。

1,开发环境
      1,框架:Qt 5.7.1

      2,编译器:MSVC2015_64bit

      3,IDE:Qt Creator 4.2.0 社区版
      4,操作系统:Windows 10 专业版

2,程序源码
      Ymodem.h文件

  1. /**
  2.   ******************************************************************************
  3.   * @file    Ymodem.h
  4.   * @author  XinLi
  5.   * @version v1.0
  6.   * @date    21-January-2018
  7.   * @brief   Header file for Ymodem.cpp module.
  8.   ******************************************************************************
  9.   * @attention
  10.   *
  11.   * <h2><center>Copyright &#169; 2018 XinLi</center></h2>
  12.   *
  13.   * This program is free software: you can redistribute it and/or modify
  14.   * it under the terms of the GNU General Public License as published by
  15.   * the Free Software Foundation, either version 3 of the License, or
  16.   * (at your option) any later version.
  17.   *
  18.   * This program is distributed in the hope that it will be useful,
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.   * GNU General Public License for more details.
  22.   *
  23.   * You should have received a copy of the GNU General Public License
  24.   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  25.   *
  26.   ******************************************************************************
  27.   */

  28. #ifndef __YMODEM_H
  29. #define __YMODEM_H

  30. /* Header includes -----------------------------------------------------------*/
  31. #include <stdint.h>

  32. /* Macro definitions ---------------------------------------------------------*/
  33. #define YMODEM_PACKET_HEADER    (3)
  34. #define YMODEM_PACKET_TRAILER   (2)
  35. #define YMODEM_PACKET_OVERHEAD  (YMODEM_PACKET_HEADER + YMODEM_PACKET_TRAILER)
  36. #define YMODEM_PACKET_SIZE      (128)
  37. #define YMODEM_PACKET_1K_SIZE   (1024)

  38. #define YMODEM_CODE_CAN_NUMBER  (5)

  39. /* Type definitions ----------------------------------------------------------*/
  40. class Ymodem
  41. {
  42. public:
  43.   enum Code
  44.   {
  45.     CodeNone = 0x00,
  46.     CodeSoh  = 0x01,
  47.     CodeStx  = 0x02,
  48.     CodeEot  = 0x04,
  49.     CodeAck  = 0x06,
  50.     CodeNak  = 0x15,
  51.     CodeCan  = 0x18,
  52.     CodeC    = 0x43,
  53.     CodeA1   = 0x41,
  54.     CodeA2   = 0x61
  55.   };

  56.   enum Stage
  57.   {
  58.     StageNone,
  59.     StageEstablishing,
  60.     StageEstablished,
  61.     StageTransmitting,
  62.     StageFinishing,
  63.     StageFinished
  64.   };

  65.   enum Status
  66.   {
  67.     StatusEstablish,
  68.     StatusTransmit,
  69.     StatusFinish,
  70.     StatusAbort,
  71.     StatusTimeout,
  72.     StatusError
  73.   };

  74.   Ymodem(uint32_t timeDivide = 499, uint32_t timeMax = 5, uint32_t errorMax = 999);

  75.   void setTimeDivide(uint32_t timeDivide);
  76.   uint32_t getTimeDivide();

  77.   void setTimeMax(uint32_t timeMax);
  78.   uint32_t getTimeMax();

  79.   void setErrorMax(uint32_t errorMax);
  80.   uint32_t getErrorMax();

  81.   void receive();
  82.   void transmit();
  83.   void abort();

  84. private:
  85.   Code receivePacket();

  86.   void receiveStageNone();
  87.   void receiveStageEstablishing();
  88.   void receiveStageEstablished();
  89.   void receiveStageTransmitting();
  90.   void receiveStageFinishing();
  91.   void receiveStageFinished();

  92.   void transmitStageNone();
  93.   void transmitStageEstablishing();
  94.   void transmitStageEstablished();
  95.   void transmitStageTransmitting();
  96.   void transmitStageFinishing();
  97.   void transmitStageFinished();

  98.   uint16_t crc16(uint8_t *buff, uint32_t len);

  99.   virtual Code callback(Status status, uint8_t *buff, uint32_t *len) = 0;

  100.   virtual uint32_t read(uint8_t *buff, uint32_t len)  = 0;
  101.   virtual uint32_t write(uint8_t *buff, uint32_t len) = 0;

  102.   uint32_t timeDivide;
  103.   uint32_t timeMax;
  104.   uint32_t errorMax;

  105.   uint32_t timeCount;
  106.   uint32_t errorCount;
  107.   uint8_t  dataCount;

  108.   Code  code;
  109.   Stage stage;

  110.   uint8_t  rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD];
  111.   uint8_t  txBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD];
  112.   uint32_t rxLength;
  113.   uint32_t txLength;
  114. };

  115. /* Variable declarations -----------------------------------------------------*/
  116. /* Variable definitions ------------------------------------------------------*/
  117. /* Function declarations -----------------------------------------------------*/
  118. /* Function definitions ------------------------------------------------------*/

  119. #endif /* __YMODEM_H */
复制代码

      Ymodem.cpp文件
  1. /**
  2.   ******************************************************************************
  3.   * @file    Ymodem.cpp
  4.   * @author  XinLi
  5.   * @version v1.0
  6.   * @date    21-January-2018
  7.   * @brief   Ymodem protocol module source file.
  8.   ******************************************************************************
  9.   * @attention
  10.   *
  11.   * <h2><center>Copyright &#169; 2018 XinLi</center></h2>
  12.   *
  13.   * This program is free software: you can redistribute it and/or modify
  14.   * it under the terms of the GNU General Public License as published by
  15.   * the Free Software Foundation, either version 3 of the License, or
  16.   * (at your option) any later version.
  17.   *
  18.   * This program is distributed in the hope that it will be useful,
  19.   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.   * GNU General Public License for more details.
  22.   *
  23.   * You should have received a copy of the GNU General Public License
  24.   * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  25.   *
  26.   ******************************************************************************
  27.   */

  28. /* Header includes -----------------------------------------------------------*/
  29. #include "Ymodem.h"
  30. #include <string.h>

  31. /* Macro definitions ---------------------------------------------------------*/
  32. /* Type definitions ----------------------------------------------------------*/
  33. /* Variable declarations -----------------------------------------------------*/
  34. /* Variable definitions ------------------------------------------------------*/
  35. /* Function declarations -----------------------------------------------------*/
  36. /* Function definitions ------------------------------------------------------*/

  37. /**
  38.   * @brief  Ymodem constructor.
  39.   * @param  [in] timeDivide: The fractional factor of the time the ymodem is called.
  40.   * @param  [in] timeMax:    The maximum time when calling the ymodem.
  41.   * @param  [in] errorMax:   The maximum error count when calling the ymodem.
  42.   * @note   The longest waiting time = call time / (@timeDivide + 1) * (@timeMax + 1).
  43.   * @return None.
  44.   */
  45. Ymodem::Ymodem(uint32_t timeDivide, uint32_t timeMax, uint32_t errorMax)
  46. {
  47.   this->timeDivide = timeDivide;
  48.   this->timeMax    = timeMax;
  49.   this->errorMax   = errorMax;

  50.   this->timeCount  = 0;
  51.   this->errorCount = 0;
  52.   this->dataCount  = 0;

  53.   this->code       = CodeNone;
  54.   this->stage      = StageNone;
  55. }

  56. /**
  57.   * @brief  Set the fractional factor of the time the ymodem is called.
  58.   * @param  [in] timeDivide: The fractional factor of the time the ymodem is called.
  59.   * @return None.
  60.   */
  61. void Ymodem::setTimeDivide(uint32_t timeDivide)
  62. {
  63.   this->timeDivide = timeDivide;
  64. }

  65. /**
  66.   * @brief  Get the fractional factor of the time the ymodem is called.
  67.   * @param  None.
  68.   * @return The fractional factor of the time the ymodem is called.
  69.   */
  70. uint32_t Ymodem::getTimeDivide()
  71. {
  72.   return timeDivide;
  73. }

  74. /**
  75.   * @brief  Set the maximum time when calling the ymodem.
  76.   * @param  [in] timeMax: The maximum time when calling the ymodem.
  77.   * @return None.
  78.   */
  79. void Ymodem::setTimeMax(uint32_t timeMax)
  80. {
  81.   this->timeMax = timeMax;
  82. }

  83. /**
  84.   * @brief  Get the maximum time when calling the ymodem.
  85.   * @param  None.
  86.   * @return The maximum time when calling the ymodem.
  87.   */
  88. uint32_t Ymodem::getTimeMax()
  89. {
  90.   return timeMax;
  91. }

  92. /**
  93.   * @brief  Set the maximum error count when calling the ymodem.
  94.   * @param  [in] errorMax: The maximum error count when calling the ymodem.
  95.   * @return None.
  96.   */
  97. void Ymodem::setErrorMax(uint32_t errorMax)
  98. {
  99.   this->errorMax = errorMax;
  100. }

  101. /**
  102.   * @brief  Get the maximum error count when calling the ymodem.
  103.   * @param  None.
  104.   * @return The maximum error count when calling the ymodem.
  105.   */
  106. uint32_t Ymodem::getErrorMax()
  107. {
  108.   return errorMax;
  109. }

  110. /**
  111.   * @brief  Ymodem receive.
  112.   * @param  None.
  113.   * @return None.
  114.   */
  115. void Ymodem::receive()
  116. {
  117.   switch(stage)
  118.   {
  119.     case StageNone:
  120.     {
  121.       receiveStageNone();

  122.       break;
  123.     }

  124.     case StageEstablishing:
  125.     {
  126.       receiveStageEstablishing();

  127.       break;
  128.     }

  129.     case StageEstablished:
  130.     {
  131.       receiveStageEstablished();

  132.       break;
  133.     }

  134.     case StageTransmitting:
  135.     {
  136.       receiveStageTransmitting();

  137.       break;
  138.     }

  139.     case StageFinishing:
  140.     {
  141.       receiveStageFinishing();

  142.       break;
  143.     }

  144.     default:
  145.     {
  146.       receiveStageFinished();
  147.     }
  148.   }
  149. }

  150. /**
  151.   * @brief  Ymodem transmit.
  152.   * @param  None.
  153.   * @return None.
  154.   */
  155. void Ymodem::transmit()
  156. {
  157.   switch(stage)
  158.   {
  159.     case StageNone:
  160.     {
  161.       transmitStageNone();

  162.       break;
  163.     }

  164.     case StageEstablishing:
  165.     {
  166.       transmitStageEstablishing();

  167.       break;
  168.     }

  169.     case StageEstablished:
  170.     {
  171.       transmitStageEstablished();

  172.       break;
  173.     }

  174.     case StageTransmitting:
  175.     {
  176.       transmitStageTransmitting();

  177.       break;
  178.     }

  179.     case StageFinishing:
  180.     {
  181.       transmitStageFinishing();

  182.       break;
  183.     }

  184.     default:
  185.     {
  186.       transmitStageFinished();
  187.     }
  188.   }
  189. }

  190. /**
  191.   * @brief  Ymodem abort.
  192.   * @param  None.
  193.   * @return None.
  194.   */
  195. void Ymodem::abort()
  196. {
  197.   timeCount  = 0;
  198.   errorCount = 0;
  199.   dataCount  = 0;
  200.   code       = CodeNone;
  201.   stage      = StageNone;

  202.   for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  203.   {
  204.     txBuffer[txLength] = CodeCan;
  205.   }

  206.   write(txBuffer, txLength);
  207. }

  208. /**
  209.   * @brief  Receives a packet of data.
  210.   * @param  None.
  211.   * @return Packet type.
  212.   */
  213. Ymodem::Code Ymodem::receivePacket()
  214. {
  215.   if(code == CodeNone)
  216.   {
  217.     if(read(&(rxBuffer[0]), 1) > 0)
  218.     {
  219.       if(rxBuffer[0] == CodeSoh)
  220.       {
  221.         uint32_t len = read(&(rxBuffer[1]), YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1);

  222.         if(len < (YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1))
  223.         {
  224.           rxLength = len + 1;
  225.           code     = CodeSoh;

  226.           return CodeNone;
  227.         }
  228.         else
  229.         {
  230.           return CodeSoh;
  231.         }
  232.       }
  233.       else if(rxBuffer[0] == CodeStx)
  234.       {
  235.         uint32_t len = read(&(rxBuffer[1]), YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 1);

  236.         if(len < (YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 1))
  237.         {
  238.           rxLength = len + 1;
  239.           code     = CodeStx;

  240.           return CodeNone;
  241.         }
  242.         else
  243.         {
  244.           return CodeStx;
  245.         }
  246.       }
  247.       else
  248.       {
  249.         return (Code)(rxBuffer[0]);
  250.       }
  251.     }
  252.     else
  253.     {
  254.       return CodeNone;
  255.     }
  256.   }
  257.   else
  258.   {
  259.     if(code == CodeSoh)
  260.     {
  261.       uint32_t len = read(&(rxBuffer[rxLength]), YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - rxLength);

  262.       if(len < (YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - rxLength))
  263.       {
  264.         rxLength += len;

  265.         return CodeNone;
  266.       }
  267.       else
  268.       {
  269.         code = CodeNone;

  270.         return CodeSoh;
  271.       }
  272.     }
  273.     else if(code == CodeStx)
  274.     {
  275.       uint32_t len = read(&(rxBuffer[rxLength]), YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - rxLength);

  276.       if(len < (YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - rxLength))
  277.       {
  278.         rxLength += len;

  279.         return CodeNone;
  280.       }
  281.       else
  282.       {
  283.         code = CodeNone;

  284.         return CodeStx;
  285.       }
  286.     }
  287.     else
  288.     {
  289.       code = CodeNone;

  290.       return CodeNone;
  291.     }
  292.   }
  293. }

  294. /**
  295.   * @brief  Receive none stage.
  296.   * @param  None.
  297.   * @return None.
  298.   */
  299. void Ymodem::receiveStageNone()
  300. {
  301.   timeCount   = 0;
  302.   errorCount  = 0;
  303.   dataCount   = 0;
  304.   code        = CodeNone;
  305.   stage       = StageEstablishing;
  306.   txBuffer[0] = CodeC;
  307.   txLength    = 1;
  308.   write(txBuffer, txLength);
  309. }

  310. /**
  311.   * @brief  Receive establishing stage.
  312.   * @param  None.
  313.   * @return None.
  314.   */
  315. void Ymodem::receiveStageEstablishing()
  316. {
  317.   switch(receivePacket())
  318.   {
  319.     case CodeSoh:
  320.     {
  321.       uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) |
  322.                      ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0);

  323.       if((rxBuffer[1] == 0x00) && (rxBuffer[2] == 0xFF) &&
  324.          (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE)))
  325.       {
  326.         uint32_t dataLength = YMODEM_PACKET_SIZE;

  327.         if(callback(StatusEstablish, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck)
  328.         {
  329.           timeCount   = 0;
  330.           errorCount  = 0;
  331.           dataCount   = 0;
  332.           code        = CodeNone;
  333.           stage       = StageEstablished;
  334.           txBuffer[0] = CodeAck;
  335.           txBuffer[1] = CodeC;
  336.           txLength    = 2;
  337.           write(txBuffer, txLength);
  338.         }
  339.         else
  340.         {
  341.           timeCount  = 0;
  342.           errorCount = 0;
  343.           dataCount  = 0;
  344.           code       = CodeNone;
  345.           stage      = StageNone;

  346.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  347.           {
  348.             txBuffer[txLength] = CodeCan;
  349.           }

  350.           write(txBuffer, txLength);
  351.         }
  352.       }
  353.       else
  354.       {
  355.         errorCount++;

  356.         if(errorCount > errorMax)
  357.         {
  358.           timeCount  = 0;
  359.           errorCount = 0;
  360.           dataCount  = 0;
  361.           code       = CodeNone;
  362.           stage      = StageNone;

  363.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  364.           {
  365.             txBuffer[txLength] = CodeCan;
  366.           }

  367.           write(txBuffer, txLength);
  368.           callback(StatusError, NULL, NULL);
  369.         }
  370.         else
  371.         {
  372.           txBuffer[0] = CodeC;
  373.           txLength    = 1;
  374.           write(txBuffer, txLength);
  375.         }
  376.       }

  377.       break;
  378.     }

  379.     case CodeA1:
  380.     case CodeA2:
  381.     case CodeCan:
  382.     {
  383.       timeCount  = 0;
  384.       errorCount = 0;
  385.       dataCount  = 0;
  386.       code       = CodeNone;
  387.       stage      = StageNone;
  388.       callback(StatusAbort, NULL, NULL);

  389.       break;
  390.     }

  391.     default:
  392.     {
  393.       timeCount++;

  394.       if((timeCount / (timeDivide + 1)) > timeMax)
  395.       {
  396.         timeCount  = 0;
  397.         errorCount = 0;
  398.         dataCount  = 0;
  399.         code       = CodeNone;
  400.         stage      = StageNone;

  401.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  402.         {
  403.           txBuffer[txLength] = CodeCan;
  404.         }

  405.         write(txBuffer, txLength);
  406.         callback(StatusTimeout, NULL, NULL);
  407.       }
  408.       else if((timeCount % (timeDivide + 1)) == 0)
  409.       {
  410.         txBuffer[0] = CodeC;
  411.         txLength    = 1;
  412.         write(txBuffer, txLength);
  413.       }
  414.     }
  415.   }
  416. }

  417. /**
  418.   * @brief  Receive established stage.
  419.   * @param  None.
  420.   * @return None.
  421.   */
  422. void Ymodem::receiveStageEstablished()
  423. {
  424.   switch(receivePacket())
  425.   {
  426.     case CodeSoh:
  427.     {
  428.       uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) |
  429.                      ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0);

  430.       if((rxBuffer[1] == 0x00) && (rxBuffer[2] == 0xFF) &&
  431.          (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE)))
  432.       {
  433.         errorCount++;

  434.         if(errorCount > errorMax)
  435.         {
  436.           timeCount  = 0;
  437.           errorCount = 0;
  438.           dataCount  = 0;
  439.           code       = CodeNone;
  440.           stage      = StageNone;

  441.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  442.           {
  443.             txBuffer[txLength] = CodeCan;
  444.           }

  445.           write(txBuffer, txLength);
  446.           callback(StatusError, NULL, NULL);
  447.         }
  448.         else
  449.         {
  450.           txBuffer[0] = CodeAck;
  451.           txBuffer[1] = CodeC;
  452.           txLength    = 2;
  453.           write(txBuffer, txLength);
  454.         }
  455.       }
  456.       else if((rxBuffer[1] == 0x01) && (rxBuffer[2] == 0xFE) &&
  457.               (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE)))
  458.       {
  459.         uint32_t dataLength = YMODEM_PACKET_SIZE;

  460.         if(callback(StatusTransmit, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck)
  461.         {
  462.           timeCount   = 0;
  463.           errorCount  = 0;
  464.           dataCount   = 1;
  465.           code        = CodeNone;
  466.           stage       = StageTransmitting;
  467.           txBuffer[0] = CodeAck;
  468.           txLength    = 1;
  469.           write(txBuffer, txLength);
  470.         }
  471.         else
  472.         {
  473.           timeCount  = 0;
  474.           errorCount = 0;
  475.           dataCount  = 0;
  476.           code       = CodeNone;
  477.           stage      = StageNone;

  478.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  479.           {
  480.             txBuffer[txLength] = CodeCan;
  481.           }

  482.           write(txBuffer, txLength);
  483.         }
  484.       }
  485.       else
  486.       {
  487.         errorCount++;

  488.         if(errorCount > errorMax)
  489.         {
  490.           timeCount  = 0;
  491.           errorCount = 0;
  492.           dataCount  = 0;
  493.           code       = CodeNone;
  494.           stage      = StageNone;

  495.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  496.           {
  497.             txBuffer[txLength] = CodeCan;
  498.           }

  499.           write(txBuffer, txLength);
  500.           callback(StatusError, NULL, NULL);
  501.         }
  502.         else
  503.         {
  504.           txBuffer[0] = CodeNak;
  505.           txLength    = 1;
  506.           write(txBuffer, txLength);
  507.         }
  508.       }

  509.       break;
  510.     }

  511.     case CodeStx:
  512.     {
  513.       uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) |
  514.                      ((uint16_t)(rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0);

  515.       if((rxBuffer[1] == 0x01) && (rxBuffer[2] == 0xFE) &&
  516.          (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_1K_SIZE)))
  517.       {
  518.         uint32_t dataLength = YMODEM_PACKET_1K_SIZE;

  519.         if(callback(StatusTransmit, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck)
  520.         {
  521.           timeCount   = 0;
  522.           errorCount  = 0;
  523.           dataCount   = 1;
  524.           code        = CodeNone;
  525.           stage       = StageTransmitting;
  526.           txBuffer[0] = CodeAck;
  527.           txLength    = 1;
  528.           write(txBuffer, txLength);
  529.         }
  530.         else
  531.         {
  532.           timeCount  = 0;
  533.           errorCount = 0;
  534.           dataCount  = 0;
  535.           code       = CodeNone;
  536.           stage      = StageNone;

  537.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  538.           {
  539.             txBuffer[txLength] = CodeCan;
  540.           }

  541.           write(txBuffer, txLength);
  542.         }
  543.       }
  544.       else
  545.       {
  546.         errorCount++;

  547.         if(errorCount > errorMax)
  548.         {
  549.           timeCount  = 0;
  550.           errorCount = 0;
  551.           dataCount  = 0;
  552.           code       = CodeNone;
  553.           stage      = StageNone;

  554.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  555.           {
  556.             txBuffer[txLength] = CodeCan;
  557.           }

  558.           write(txBuffer, txLength);
  559.           callback(StatusError, NULL, NULL);
  560.         }
  561.         else
  562.         {
  563.           txBuffer[0] = CodeNak;
  564.           txLength    = 1;
  565.           write(txBuffer, txLength);
  566.         }
  567.       }

  568.       break;
  569.     }

  570.     case CodeEot:
  571.     {
  572.       timeCount   = 0;
  573.       errorCount  = 0;
  574.       dataCount   = 0;
  575.       code        = CodeNone;
  576.       stage       = StageFinishing;
  577.       txBuffer[0] = CodeNak;
  578.       txLength    = 1;
  579.       write(txBuffer, txLength);

  580.       break;
  581.     }

  582.     case CodeA1:
  583.     case CodeA2:
  584.     case CodeCan:
  585.     {
  586.       timeCount  = 0;
  587.       errorCount = 0;
  588.       dataCount  = 0;
  589.       code       = CodeNone;
  590.       stage      = StageNone;
  591.       callback(StatusAbort, NULL, NULL);

  592.       break;
  593.     }

  594.     default:
  595.     {
  596.       timeCount++;

  597.       if((timeCount / (timeDivide + 1)) > timeMax)
  598.       {
  599.         timeCount  = 0;
  600.         errorCount = 0;
  601.         dataCount  = 0;
  602.         code       = CodeNone;
  603.         stage      = StageNone;

  604.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  605.         {
  606.           txBuffer[txLength] = CodeCan;
  607.         }

  608.         write(txBuffer, txLength);
  609.         callback(StatusError, NULL, NULL);
  610.       }
  611.       else if((timeCount % (timeDivide + 1)) == 0)
  612.       {
  613.         txBuffer[0] = CodeNak;
  614.         txLength    = 1;
  615.         write(txBuffer, txLength);
  616.       }
  617.     }
  618.   }
  619. }

  620. /**
  621.   * @brief  Receive transmitting stage.
  622.   * @param  None.
  623.   * @return None.
  624.   */
  625. void Ymodem::receiveStageTransmitting()
  626. {
  627.   switch(receivePacket())
  628.   {
  629.     case CodeSoh:
  630.     {
  631.       uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) |
  632.                      ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0);

  633.       if((rxBuffer[1] == (uint8_t)(dataCount)) && (rxBuffer[2] == (uint8_t)(0xFF - dataCount)) &&
  634.          (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE)))
  635.       {
  636.         errorCount++;

  637.         if(errorCount > errorMax)
  638.         {
  639.           timeCount  = 0;
  640.           errorCount = 0;
  641.           dataCount  = 0;
  642.           code       = CodeNone;
  643.           stage      = StageNone;

  644.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  645.           {
  646.             txBuffer[txLength] = CodeCan;
  647.           }

  648.           write(txBuffer, txLength);
  649.           callback(StatusError, NULL, NULL);
  650.         }
  651.         else
  652.         {
  653.           txBuffer[0] = CodeAck;
  654.           txLength    = 1;
  655.           write(txBuffer, txLength);
  656.         }
  657.       }
  658.       else if((rxBuffer[1] == (uint8_t)(dataCount + 1)) && (rxBuffer[2] == (uint8_t)(0xFE - dataCount)) &&
  659.               (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE)))
  660.       {
  661.         uint32_t dataLength = YMODEM_PACKET_SIZE;

  662.         if(callback(StatusTransmit, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck)
  663.         {
  664.           timeCount   = 0;
  665.           errorCount  = 0;
  666.           dataCount   = dataCount + 1;
  667.           code        = CodeNone;
  668.           stage       = StageTransmitting;
  669.           txBuffer[0] = CodeAck;
  670.           txLength    = 1;
  671.           write(txBuffer, txLength);
  672.         }
  673.         else
  674.         {
  675.           timeCount  = 0;
  676.           errorCount = 0;
  677.           dataCount  = 0;
  678.           code       = CodeNone;
  679.           stage      = StageNone;

  680.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  681.           {
  682.             txBuffer[txLength] = CodeCan;
  683.           }

  684.           write(txBuffer, txLength);
  685.         }
  686.       }
  687.       else
  688.       {
  689.         errorCount++;

  690.         if(errorCount > errorMax)
  691.         {
  692.           timeCount  = 0;
  693.           errorCount = 0;
  694.           dataCount  = 0;
  695.           code       = CodeNone;
  696.           stage      = StageNone;

  697.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  698.           {
  699.             txBuffer[txLength] = CodeCan;
  700.           }

  701.           write(txBuffer, txLength);
  702.           callback(StatusError, NULL, NULL);
  703.         }
  704.         else
  705.         {
  706.           txBuffer[0] = CodeNak;
  707.           txLength    = 1;
  708.           write(txBuffer, txLength);
  709.         }
  710.       }

  711.       break;
  712.     }

  713.     case CodeStx:
  714.     {
  715.       uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) |
  716.                      ((uint16_t)(rxBuffer[YMODEM_PACKET_1K_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0);

  717.       if((rxBuffer[1] == (uint8_t)(dataCount)) && (rxBuffer[2] == (uint8_t)(0xFF - dataCount)) &&
  718.          (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_1K_SIZE)))
  719.       {
  720.         errorCount++;

  721.         if(errorCount > errorMax)
  722.         {
  723.           timeCount  = 0;
  724.           errorCount = 0;
  725.           dataCount  = 0;
  726.           code       = CodeNone;
  727.           stage      = StageNone;

  728.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  729.           {
  730.             txBuffer[txLength] = CodeCan;
  731.           }

  732.           write(txBuffer, txLength);
  733.           callback(StatusError, NULL, NULL);
  734.         }
  735.         else
  736.         {
  737.           txBuffer[0] = CodeAck;
  738.           txLength    = 1;
  739.           write(txBuffer, txLength);
  740.         }
  741.       }
  742.       else if((rxBuffer[1] == (uint8_t)(dataCount + 1)) && (rxBuffer[2] == (uint8_t)(0xFE - dataCount)) &&
  743.               (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_1K_SIZE)))
  744.       {
  745.         uint32_t dataLength = YMODEM_PACKET_1K_SIZE;

  746.         if(callback(StatusTransmit, &(rxBuffer[YMODEM_PACKET_HEADER]), &dataLength) == CodeAck)
  747.         {
  748.           timeCount   = 0;
  749.           errorCount  = 0;
  750.           dataCount   = dataCount + 1;
  751.           code        = CodeNone;
  752.           stage       = StageTransmitting;
  753.           txBuffer[0] = CodeAck;
  754.           txLength    = 1;
  755.           write(txBuffer, txLength);
  756.         }
  757.         else
  758.         {
  759.           timeCount  = 0;
  760.           errorCount = 0;
  761.           dataCount  = 0;
  762.           code       = CodeNone;
  763.           stage      = StageNone;

  764.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  765.           {
  766.             txBuffer[txLength] = CodeCan;
  767.           }

  768.           write(txBuffer, txLength);
  769.         }
  770.       }
  771.       else
  772.       {
  773.         errorCount++;

  774.         if(errorCount > errorMax)
  775.         {
  776.           timeCount  = 0;
  777.           errorCount = 0;
  778.           dataCount  = 0;
  779.           code       = CodeNone;
  780.           stage      = StageNone;

  781.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  782.           {
  783.             txBuffer[txLength] = CodeCan;
  784.           }

  785.           write(txBuffer, txLength);
  786.           callback(StatusError, NULL, NULL);
  787.         }
  788.         else
  789.         {
  790.           txBuffer[0] = CodeNak;
  791.           txLength    = 1;
  792.           write(txBuffer, txLength);
  793.         }
  794.       }

  795.       break;
  796.     }

  797.     case CodeEot:
  798.     {
  799.       timeCount   = 0;
  800.       errorCount  = 0;
  801.       dataCount   = 0;
  802.       code        = CodeNone;
  803.       stage       = StageFinishing;
  804.       txBuffer[0] = CodeNak;
  805.       txLength    = 1;
  806.       write(txBuffer, txLength);

  807.       break;
  808.     }

  809.     case CodeA1:
  810.     case CodeA2:
  811.     case CodeCan:
  812.     {
  813.       timeCount  = 0;
  814.       errorCount = 0;
  815.       dataCount  = 0;
  816.       code       = CodeNone;
  817.       stage      = StageNone;
  818.       callback(StatusAbort, NULL, NULL);

  819.       break;
  820.     }

  821.     default:
  822.     {
  823.       timeCount++;

  824.       if((timeCount / (timeDivide + 1)) > timeMax)
  825.       {
  826.         timeCount  = 0;
  827.         errorCount = 0;
  828.         dataCount  = 0;
  829.         code       = CodeNone;
  830.         stage      = StageNone;

  831.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  832.         {
  833.           txBuffer[txLength] = CodeCan;
  834.         }

  835.         write(txBuffer, txLength);
  836.         callback(StatusError, NULL, NULL);
  837.       }
  838.       else if((timeCount % (timeDivide + 1)) == 0)
  839.       {
  840.         txBuffer[0] = CodeNak;
  841.         txLength    = 1;
  842.         write(txBuffer, txLength);
  843.       }
  844.     }
  845.   }
  846. }

  847. /**
  848.   * @brief  Receive finishing stage.
  849.   * @param  None.
  850.   * @return None.
  851.   */
  852. void Ymodem::receiveStageFinishing()
  853. {
  854.   switch(receivePacket())
  855.   {
  856.     case CodeEot:
  857.     {
  858.       timeCount   = 0;
  859.       errorCount  = 0;
  860.       dataCount   = 0;
  861.       code        = CodeNone;
  862.       stage       = StageFinished;
  863.       txBuffer[0] = CodeAck;
  864.       txBuffer[1] = CodeC;
  865.       txLength    = 2;
  866.       write(txBuffer, txLength);

  867.       break;
  868.     }

  869.     case CodeA1:
  870.     case CodeA2:
  871.     case CodeCan:
  872.     {
  873.       timeCount  = 0;
  874.       errorCount = 0;
  875.       dataCount  = 0;
  876.       code       = CodeNone;
  877.       stage      = StageNone;
  878.       callback(StatusAbort, NULL, NULL);

  879.       break;
  880.     }

  881.     default:
  882.     {
  883.       timeCount++;

  884.       if((timeCount / (timeDivide + 1)) > timeMax)
  885.       {
  886.         timeCount  = 0;
  887.         errorCount = 0;
  888.         dataCount  = 0;
  889.         code       = CodeNone;
  890.         stage      = StageNone;

  891.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  892.         {
  893.           txBuffer[txLength] = CodeCan;
  894.         }

  895.         write(txBuffer, txLength);
  896.         callback(StatusError, NULL, NULL);
  897.       }
  898.       else if((timeCount % (timeDivide + 1)) == 0)
  899.       {
  900.         txBuffer[0] = CodeNak;
  901.         txLength    = 1;
  902.         write(txBuffer, txLength);
  903.       }
  904.     }
  905.   }
  906. }

  907. /**
  908.   * @brief  Receive finished stage.
  909.   * @param  None.
  910.   * @return None.
  911.   */
  912. void Ymodem::receiveStageFinished()
  913. {
  914.   switch(receivePacket())
  915.   {
  916.     case CodeSoh:
  917.     {
  918.       uint16_t crc = ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2]) << 8) |
  919.                      ((uint16_t)(rxBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1]) << 0);

  920.       if((rxBuffer[1] == 0x00) && (rxBuffer[2] == 0xFF) &&
  921.          (crc == crc16(&(rxBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE)))
  922.       {
  923.         timeCount   = 0;
  924.         errorCount  = 0;
  925.         dataCount   = 0;
  926.         code        = CodeNone;
  927.         stage       = StageNone;
  928.         txBuffer[0] = CodeAck;
  929.         txLength    = 1;
  930.         write(txBuffer, txLength);
  931.         callback(StatusFinish, NULL, NULL);
  932.       }
  933.       else
  934.       {
  935.         errorCount++;

  936.         if(errorCount > errorMax)
  937.         {
  938.           timeCount  = 0;
  939.           errorCount = 0;
  940.           dataCount  = 0;
  941.           code       = CodeNone;
  942.           stage      = StageNone;

  943.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  944.           {
  945.             txBuffer[txLength] = CodeCan;
  946.           }

  947.           write(txBuffer, txLength);
  948.           callback(StatusError, NULL, NULL);
  949.         }
  950.         else
  951.         {
  952.           txBuffer[0] = CodeNak;
  953.           txLength    = 1;
  954.           write(txBuffer, txLength);
  955.         }
  956.       }

  957.       break;
  958.     }

  959.     case CodeEot:
  960.     {
  961.       errorCount++;

  962.       if(errorCount > errorMax)
  963.       {
  964.         timeCount  = 0;
  965.         errorCount = 0;
  966.         dataCount  = 0;
  967.         code       = CodeNone;
  968.         stage      = StageNone;

  969.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  970.         {
  971.           txBuffer[txLength] = CodeCan;
  972.         }

  973.         write(txBuffer, txLength);
  974.         callback(StatusError, NULL, NULL);
  975.       }
  976.       else
  977.       {
  978.         txBuffer[0] = CodeAck;
  979.         txBuffer[1] = CodeC;
  980.         txLength    = 2;
  981.         write(txBuffer, txLength);
  982.       }

  983.       break;
  984.     }

  985.     case CodeA1:
  986.     case CodeA2:
  987.     case CodeCan:
  988.     {
  989.       timeCount  = 0;
  990.       errorCount = 0;
  991.       dataCount  = 0;
  992.       code       = CodeNone;
  993.       stage      = StageNone;
  994.       callback(StatusAbort, NULL, NULL);

  995.       break;
  996.     }

  997.     default:
  998.     {
  999.       timeCount++;

  1000.       if((timeCount / (timeDivide + 1)) > timeMax)
  1001.       {
  1002.         timeCount  = 0;
  1003.         errorCount = 0;
  1004.         dataCount  = 0;
  1005.         code       = CodeNone;
  1006.         stage      = StageNone;

  1007.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1008.         {
  1009.           txBuffer[txLength] = CodeCan;
  1010.         }

  1011.         write(txBuffer, txLength);
  1012.         callback(StatusError, NULL, NULL);
  1013.       }
  1014.       else if((timeCount % (timeDivide + 1)) == 0)
  1015.       {
  1016.         txBuffer[0] = CodeNak;
  1017.         txLength    = 1;
  1018.         write(txBuffer, txLength);
  1019.       }
  1020.     }
  1021.   }
  1022. }

  1023. /**
  1024.   * @brief  Transmit none stage.
  1025.   * @param  None.
  1026.   * @return None.
  1027.   */
  1028. void Ymodem::transmitStageNone()
  1029. {
  1030.   timeCount   = 0;
  1031.   errorCount  = 0;
  1032.   dataCount   = 0;
  1033.   code        = CodeNone;
  1034.   stage       = StageEstablishing;
  1035. }

  1036. /**
  1037.   * @brief  Transmit establishing stage.
  1038.   * @param  None.
  1039.   * @return None.
  1040.   */
  1041. void Ymodem::transmitStageEstablishing()
  1042. {
  1043.   switch(receivePacket())
  1044.   {
  1045.     case CodeC:
  1046.     {
  1047.       memset(&(txBuffer[YMODEM_PACKET_HEADER]), NULL, YMODEM_PACKET_SIZE);

  1048.       if(callback(StatusEstablish, &(txBuffer[YMODEM_PACKET_HEADER]), &(txLength)) == CodeAck)
  1049.       {
  1050.         uint16_t crc = crc16(&(txBuffer[YMODEM_PACKET_HEADER]), txLength);

  1051.         timeCount                                       = 0;
  1052.         errorCount                                      = 0;
  1053.         dataCount                                       = 0;
  1054.         code                                            = CodeNone;
  1055.         stage                                           = StageEstablished;
  1056.         txBuffer[0]                                     = CodeSoh;
  1057.         txBuffer[1]                                     = 0x00;
  1058.         txBuffer[2]                                     = 0xFF;
  1059.         txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8);
  1060.         txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0);
  1061.         txLength                                        = txLength + YMODEM_PACKET_OVERHEAD;
  1062.         write(txBuffer, txLength);
  1063.       }
  1064.       else
  1065.       {
  1066.         timeCount  = 0;
  1067.         errorCount = 0;
  1068.         dataCount  = 0;
  1069.         code       = CodeNone;
  1070.         stage      = StageNone;

  1071.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1072.         {
  1073.           txBuffer[txLength] = CodeCan;
  1074.         }

  1075.         write(txBuffer, txLength);
  1076.       }

  1077.       break;
  1078.     }

  1079.     case CodeA1:
  1080.     case CodeA2:
  1081.     case CodeCan:
  1082.     {
  1083.       timeCount  = 0;
  1084.       errorCount = 0;
  1085.       dataCount  = 0;
  1086.       code       = CodeNone;
  1087.       stage      = StageNone;
  1088.       callback(StatusAbort, NULL, NULL);

  1089.       break;
  1090.     }

  1091.     default:
  1092.     {
  1093.       timeCount++;

  1094.       if((timeCount / (timeDivide + 1)) > timeMax)
  1095.       {
  1096.         timeCount  = 0;
  1097.         errorCount = 0;
  1098.         dataCount  = 0;
  1099.         code       = CodeNone;
  1100.         stage      = StageNone;

  1101.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1102.         {
  1103.           txBuffer[txLength] = CodeCan;
  1104.         }

  1105.         write(txBuffer, txLength);
  1106.         callback(StatusTimeout, NULL, NULL);
  1107.       }
  1108.     }
  1109.   }
  1110. }

  1111. /**
  1112.   * @brief  Transmit established stage.
  1113.   * @param  None.
  1114.   * @return None.
  1115.   */
  1116. void Ymodem::transmitStageEstablished()
  1117. {
  1118.   switch(receivePacket())
  1119.   {
  1120.     case CodeNak:
  1121.     {
  1122.       errorCount++;

  1123.       if(errorCount > errorMax)
  1124.       {
  1125.         timeCount  = 0;
  1126.         errorCount = 0;
  1127.         dataCount  = 0;
  1128.         code       = CodeNone;
  1129.         stage      = StageNone;

  1130.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1131.         {
  1132.           txBuffer[txLength] = CodeCan;
  1133.         }

  1134.         write(txBuffer, txLength);
  1135.         callback(StatusError, NULL, NULL);
  1136.       }
  1137.       else
  1138.       {
  1139.         write(txBuffer, txLength);
  1140.       }

  1141.       break;
  1142.     }

  1143.     case CodeC:
  1144.     {
  1145.       errorCount++;

  1146.       if(errorCount > errorMax)
  1147.       {
  1148.         timeCount  = 0;
  1149.         errorCount = 0;
  1150.         dataCount  = 0;
  1151.         code       = CodeNone;
  1152.         stage      = StageNone;

  1153.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1154.         {
  1155.           txBuffer[txLength] = CodeCan;
  1156.         }

  1157.         write(txBuffer, txLength);
  1158.         callback(StatusError, NULL, NULL);
  1159.       }
  1160.       else
  1161.       {
  1162.         timeCount  = 0;
  1163.         errorCount = 0;
  1164.         dataCount  = dataCount;
  1165.         code       = CodeNone;
  1166.         stage      = (Stage)(stage + dataCount);
  1167.         write(txBuffer, txLength);
  1168.       }

  1169.       break;
  1170.     }

  1171.     case CodeAck:
  1172.     {
  1173.       memset(&(txBuffer[YMODEM_PACKET_HEADER]), NULL, YMODEM_PACKET_1K_SIZE);

  1174.       switch(callback(StatusTransmit, &(txBuffer[YMODEM_PACKET_HEADER]), &(txLength)))
  1175.       {
  1176.         case CodeAck:
  1177.         {
  1178.           uint16_t crc = crc16(&(txBuffer[YMODEM_PACKET_HEADER]), txLength);

  1179.           timeCount                                       = 0;
  1180.           errorCount                                      = 0;
  1181.           dataCount                                       = 1;
  1182.           code                                            = CodeNone;
  1183.           stage                                           = StageEstablished;
  1184.           txBuffer[0]                                     = txLength > YMODEM_PACKET_SIZE ? CodeStx : CodeSoh;
  1185.           txBuffer[1]                                     = 0x01;
  1186.           txBuffer[2]                                     = 0xFE;
  1187.           txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8);
  1188.           txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0);
  1189.           txLength                                        = txLength + YMODEM_PACKET_OVERHEAD;

  1190.           break;
  1191.         }

  1192.         case CodeEot:
  1193.         {
  1194.           timeCount   = 0;
  1195.           errorCount  = 0;
  1196.           dataCount   = 2;
  1197.           code        = CodeNone;
  1198.           stage       = StageEstablished;
  1199.           txBuffer[0] = CodeEot;
  1200.           txLength    = 1;
  1201.           write(txBuffer, txLength);

  1202.           break;
  1203.         }

  1204.         default:
  1205.         {
  1206.           timeCount  = 0;
  1207.           errorCount = 0;
  1208.           dataCount  = 0;
  1209.           code       = CodeNone;
  1210.           stage      = StageNone;

  1211.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1212.           {
  1213.             txBuffer[txLength] = CodeCan;
  1214.           }

  1215.           write(txBuffer, txLength);
  1216.         }
  1217.       }

  1218.       break;
  1219.     }

  1220.     case CodeA1:
  1221.     case CodeA2:
  1222.     case CodeCan:
  1223.     {
  1224.       timeCount  = 0;
  1225.       errorCount = 0;
  1226.       dataCount  = 0;
  1227.       code       = CodeNone;
  1228.       stage      = StageNone;
  1229.       callback(StatusAbort, NULL, NULL);

  1230.       break;
  1231.     }

  1232.     default:
  1233.     {
  1234.       timeCount++;

  1235.       if((timeCount / (timeDivide + 1)) > timeMax)
  1236.       {
  1237.         timeCount  = 0;
  1238.         errorCount = 0;
  1239.         dataCount  = 0;
  1240.         code       = CodeNone;
  1241.         stage      = StageNone;

  1242.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1243.         {
  1244.           txBuffer[txLength] = CodeCan;
  1245.         }

  1246.         write(txBuffer, txLength);
  1247.         callback(StatusError, NULL, NULL);
  1248.       }
  1249.       else if((timeCount % (timeDivide + 1)) == 0)
  1250.       {
  1251.         write(txBuffer, txLength);
  1252.       }
  1253.     }
  1254.   }
  1255. }

  1256. /**
  1257.   * @brief  Transmit transmitting stage.
  1258.   * @param  None.
  1259.   * @return None.
  1260.   */
  1261. void Ymodem::transmitStageTransmitting()
  1262. {
  1263.   switch(receivePacket())
  1264.   {
  1265.     case CodeNak:
  1266.     {
  1267.       errorCount++;

  1268.       if(errorCount > errorMax)
  1269.       {
  1270.         timeCount  = 0;
  1271.         errorCount = 0;
  1272.         dataCount  = 0;
  1273.         code       = CodeNone;
  1274.         stage      = StageNone;

  1275.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1276.         {
  1277.           txBuffer[txLength] = CodeCan;
  1278.         }

  1279.         write(txBuffer, txLength);
  1280.         callback(StatusError, NULL, NULL);
  1281.       }
  1282.       else
  1283.       {
  1284.         write(txBuffer, txLength);
  1285.       }

  1286.       break;
  1287.     }

  1288.     case CodeAck:
  1289.     {
  1290.       memset(&(txBuffer[YMODEM_PACKET_HEADER]), NULL, YMODEM_PACKET_1K_SIZE);

  1291.       switch(callback(StatusTransmit, &(txBuffer[YMODEM_PACKET_HEADER]), &(txLength)))
  1292.       {
  1293.         case CodeAck:
  1294.         {
  1295.           uint16_t crc = crc16(&(txBuffer[YMODEM_PACKET_HEADER]), txLength);

  1296.           timeCount                                       = 0;
  1297.           errorCount                                      = 0;
  1298.           dataCount                                       = dataCount + 1;
  1299.           code                                            = CodeNone;
  1300.           stage                                           = StageTransmitting;
  1301.           txBuffer[0]                                     = txLength > YMODEM_PACKET_SIZE ? CodeStx : CodeSoh;
  1302.           txBuffer[1]                                     = dataCount;
  1303.           txBuffer[2]                                     = 0xFF - dataCount;
  1304.           txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8);
  1305.           txBuffer[txLength + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0);
  1306.           txLength                                        = txLength + YMODEM_PACKET_OVERHEAD;
  1307.           write(txBuffer, txLength);

  1308.           break;
  1309.         }

  1310.         case CodeEot:
  1311.         {
  1312.           timeCount   = 0;
  1313.           errorCount  = 0;
  1314.           dataCount   = 0;
  1315.           code        = CodeNone;
  1316.           stage       = StageFinishing;
  1317.           txBuffer[0] = CodeEot;
  1318.           txLength    = 1;
  1319.           write(txBuffer, txLength);

  1320.           break;
  1321.         }

  1322.         default:
  1323.         {
  1324.           timeCount  = 0;
  1325.           errorCount = 0;
  1326.           dataCount  = 0;
  1327.           code       = CodeNone;
  1328.           stage      = StageNone;

  1329.           for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1330.           {
  1331.             txBuffer[txLength] = CodeCan;
  1332.           }

  1333.           write(txBuffer, txLength);
  1334.         }
  1335.       }

  1336.       break;
  1337.     }

  1338.     case CodeA1:
  1339.     case CodeA2:
  1340.     case CodeCan:
  1341.     {
  1342.       timeCount  = 0;
  1343.       errorCount = 0;
  1344.       dataCount  = 0;
  1345.       code       = CodeNone;
  1346.       stage      = StageNone;
  1347.       callback(StatusAbort, NULL, NULL);

  1348.       break;
  1349.     }

  1350.     default:
  1351.     {
  1352.       timeCount++;

  1353.       if((timeCount / (timeDivide + 1)) > timeMax)
  1354.       {
  1355.         timeCount  = 0;
  1356.         errorCount = 0;
  1357.         dataCount  = 0;
  1358.         code       = CodeNone;
  1359.         stage      = StageNone;

  1360.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1361.         {
  1362.           txBuffer[txLength] = CodeCan;
  1363.         }

  1364.         write(txBuffer, txLength);
  1365.         callback(StatusError, NULL, NULL);
  1366.       }
  1367.       else if((timeCount % (timeDivide + 1)) == 0)
  1368.       {
  1369.         write(txBuffer, txLength);
  1370.       }
  1371.     }
  1372.   }
  1373. }

  1374. /**
  1375.   * @brief  Transmit finishing stage.
  1376.   * @param  None.
  1377.   * @return None.
  1378.   */
  1379. void Ymodem::transmitStageFinishing()
  1380. {
  1381.   switch(receivePacket())
  1382.   {
  1383.     case CodeNak:
  1384.     {
  1385.       timeCount   = 0;
  1386.       errorCount  = 0;
  1387.       dataCount   = 0;
  1388.       code        = CodeNone;
  1389.       stage       = StageFinishing;
  1390.       txBuffer[0] = CodeEot;
  1391.       txLength    = 1;
  1392.       write(txBuffer, txLength);

  1393.       break;
  1394.     }

  1395.     case CodeC:
  1396.     {
  1397.       memset(&(txBuffer[YMODEM_PACKET_HEADER]), NULL, YMODEM_PACKET_SIZE);
  1398.       uint16_t crc = crc16(&(txBuffer[YMODEM_PACKET_HEADER]), YMODEM_PACKET_SIZE);

  1399.       timeCount                                                 = 0;
  1400.       errorCount                                                = 0;
  1401.       dataCount                                                 = 0;
  1402.       code                                                      = CodeNone;
  1403.       stage                                                     = StageFinished;
  1404.       txBuffer[0]                                               = CodeSoh;
  1405.       txBuffer[1]                                               = 0x00;
  1406.       txBuffer[2]                                               = 0xFF;
  1407.       txBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 2] = (uint8_t)(crc >> 8);
  1408.       txBuffer[YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD - 1] = (uint8_t)(crc >> 0);
  1409.       txLength                                                  = YMODEM_PACKET_SIZE + YMODEM_PACKET_OVERHEAD;
  1410.       write(txBuffer, txLength);

  1411.       break;
  1412.     }

  1413.     case CodeA1:
  1414.     case CodeA2:
  1415.     case CodeCan:
  1416.     {
  1417.       timeCount  = 0;
  1418.       errorCount = 0;
  1419.       dataCount  = 0;
  1420.       code       = CodeNone;
  1421.       stage      = StageNone;
  1422.       callback(StatusAbort, NULL, NULL);

  1423.       break;
  1424.     }

  1425.     default:
  1426.     {
  1427.       timeCount++;

  1428.       if((timeCount / (timeDivide + 1)) > timeMax)
  1429.       {
  1430.         timeCount  = 0;
  1431.         errorCount = 0;
  1432.         dataCount  = 0;
  1433.         code       = CodeNone;
  1434.         stage      = StageNone;

  1435.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1436.         {
  1437.           txBuffer[txLength] = CodeCan;
  1438.         }

  1439.         write(txBuffer, txLength);
  1440.         callback(StatusError, NULL, NULL);
  1441.       }
  1442.       else if((timeCount % (timeDivide + 1)) == 0)
  1443.       {
  1444.         write(txBuffer, txLength);
  1445.       }
  1446.     }
  1447.   }
  1448. }

  1449. /**
  1450.   * @brief  Transmit finished stage.
  1451.   * @param  None.
  1452.   * @return None.
  1453.   */
  1454. void Ymodem::transmitStageFinished()
  1455. {
  1456.   switch(receivePacket())
  1457.   {
  1458.     case CodeC:
  1459.     case CodeNak:
  1460.     {
  1461.       errorCount++;

  1462.       if(errorCount > errorMax)
  1463.       {
  1464.         timeCount  = 0;
  1465.         errorCount = 0;
  1466.         dataCount  = 0;
  1467.         code       = CodeNone;
  1468.         stage      = StageNone;

  1469.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1470.         {
  1471.           txBuffer[txLength] = CodeCan;
  1472.         }

  1473.         write(txBuffer, txLength);
  1474.         callback(StatusError, NULL, NULL);
  1475.       }
  1476.       else
  1477.       {
  1478.         write(txBuffer, txLength);
  1479.       }

  1480.       break;
  1481.     }

  1482.     case CodeAck:
  1483.     {
  1484.       timeCount  = 0;
  1485.       errorCount = 0;
  1486.       dataCount  = 0;
  1487.       code       = CodeNone;
  1488.       stage      = StageNone;
  1489.       callback(StatusFinish, NULL, NULL);

  1490.       break;
  1491.     }

  1492.     case CodeA1:
  1493.     case CodeA2:
  1494.     case CodeCan:
  1495.     {
  1496.       timeCount  = 0;
  1497.       errorCount = 0;
  1498.       dataCount  = 0;
  1499.       code       = CodeNone;
  1500.       stage      = StageNone;
  1501.       callback(StatusAbort, NULL, NULL);

  1502.       break;
  1503.     }

  1504.     default:
  1505.     {
  1506.       timeCount++;

  1507.       if((timeCount / (timeDivide + 1)) > timeMax)
  1508.       {
  1509.         timeCount  = 0;
  1510.         errorCount = 0;
  1511.         dataCount  = 0;
  1512.         code       = CodeNone;
  1513.         stage      = StageNone;

  1514.         for(txLength = 0; txLength < YMODEM_CODE_CAN_NUMBER; txLength++)
  1515.         {
  1516.           txBuffer[txLength] = CodeCan;
  1517.         }

  1518.         write(txBuffer, txLength);
  1519.         callback(StatusError, NULL, NULL);
  1520.       }
  1521.       else if((timeCount % (timeDivide + 1)) == 0)
  1522.       {
  1523.         write(txBuffer, txLength);
  1524.       }
  1525.     }
  1526.   }
  1527. }

  1528. /**
  1529.   * @brief  Calculate CRC16 checksum.
  1530.   * @param  [in] buff: The data to be calculated.
  1531.   * @param  [in] len:  The length of the data to be calculated.
  1532.   * @return Calculated CRC16 checksum.
  1533.   */
  1534. uint16_t Ymodem::crc16(uint8_t *buff, uint32_t len)
  1535. {
  1536.   uint16_t crc = 0;

  1537.   while(len--)
  1538.   {
  1539.     crc ^= (uint16_t)(*(buff++)) << 8;

  1540.     for(int i = 0; i < 8; i++)
  1541.     {
  1542.       if(crc & 0x8000)
  1543.       {
  1544.         crc = (crc << 1) ^ 0x1021;
  1545.       }
  1546.       else
  1547.       {
  1548.         crc = crc << 1;
  1549.       }
  1550.     }
  1551.   }

  1552.   return crc;
  1553. }
复制代码

      YmodemFileReceive.h文件
  1. #ifndef YMODEMFILERECEIVE_H
  2. #define YMODEMFILERECEIVE_H

  3. #include <QFile>
  4. #include <QTimer>
  5. #include <QObject>
  6. #include <QSerialPort>
  7. #include "Ymodem.h"

  8. class YmodemFileReceive : public QObject, public Ymodem
  9. {
  10.     Q_OBJECT

  11. public:
  12.     explicit YmodemFileReceive(QObject *parent = 0);
  13.     ~YmodemFileReceive();

  14.     void setFilePath(const QString &path);

  15.     void setPortName(const QString &name);
  16.     void setPortBaudRate(qint32 baudrate);

  17.     bool startReceive();
  18.     void stopReceive();

  19.     int getReceiveProgress();
  20.     Status getReceiveStatus();

  21. signals:
  22.     void receiveProgress(int progress);
  23.     void receiveStatus(YmodemFileReceive::Status status);

  24. private slots:
  25.     void readTimeOut();
  26.     void writeTimeOut();

  27. private:
  28.     Code callback(Status status, uint8_t *buff, uint32_t *len);

  29.     uint32_t read(uint8_t *buff, uint32_t len);
  30.     uint32_t write(uint8_t *buff, uint32_t len);

  31.     QFile       *file;
  32.     QTimer      *readTimer;
  33.     QTimer      *writeTimer;
  34.     QSerialPort *serialPort;

  35.     int      progress;
  36.     Status   status;
  37.     QString  filePath;
  38.     QString  fileName;
  39.     uint64_t fileSize;
  40.     uint64_t fileCount;
  41. };

  42. #endif // YMODEMFILERECEIVE_H
复制代码

      YmodemFileReceive.cpp文件
  1. #include "YmodemFileReceive.h"

  2. #define READ_TIME_OUT   (10)
  3. #define WRITE_TIME_OUT  (100)

  4. YmodemFileReceive::YmodemFileReceive(QObject *parent) :
  5.     QObject(parent),
  6.     file(new QFile),
  7.     readTimer(new QTimer),
  8.     writeTimer(new QTimer),
  9.     serialPort(new QSerialPort)
  10. {
  11.     setTimeDivide(499);
  12.     setTimeMax(5);
  13.     setErrorMax(999);

  14.     serialPort->setPortName("COM1");
  15.     serialPort->setBaudRate(115200);
  16.     serialPort->setDataBits(QSerialPort::Data8);
  17.     serialPort->setStopBits(QSerialPort::OneStop);
  18.     serialPort->setParity(QSerialPort::NoParity);
  19.     serialPort->setFlowControl(QSerialPort::NoFlowControl);

  20.     connect(readTimer, SIGNAL(timeout()), this, SLOT(readTimeOut()));
  21.     connect(writeTimer, SIGNAL(timeout()), this, SLOT(writeTimeOut()));
  22. }

  23. YmodemFileReceive::~YmodemFileReceive()
  24. {
  25.     delete file;
  26.     delete readTimer;
  27.     delete writeTimer;
  28.     delete serialPort;
  29. }

  30. void YmodemFileReceive::setFilePath(const QString &path)
  31. {
  32.     filePath = path + "/";
  33. }

  34. void YmodemFileReceive::setPortName(const QString &name)
  35. {
  36.     serialPort->setPortName(name);
  37. }

  38. void YmodemFileReceive::setPortBaudRate(qint32 baudrate)
  39. {
  40.     serialPort->setBaudRate(baudrate);
  41. }

  42. bool YmodemFileReceive::startReceive()
  43. {
  44.     progress = 0;
  45.     status   = StatusEstablish;

  46.     if(serialPort->open(QSerialPort::ReadWrite) == true)
  47.     {
  48.         readTimer->start(READ_TIME_OUT);

  49.         return true;
  50.     }
  51.     else
  52.     {
  53.         return false;
  54.     }
  55. }

  56. void YmodemFileReceive::stopReceive()
  57. {
  58.     file->close();
  59.     abort();
  60.     status = StatusAbort;
  61.     writeTimer->start(WRITE_TIME_OUT);
  62. }

  63. int YmodemFileReceive::getReceiveProgress()
  64. {
  65.     return progress;
  66. }

  67. Ymodem::Status YmodemFileReceive::getReceiveStatus()
  68. {
  69.     return status;
  70. }

  71. void YmodemFileReceive::readTimeOut()
  72. {
  73.     readTimer->stop();

  74.     receive();

  75.     if((status == StatusEstablish) || (status == StatusTransmit))
  76.     {
  77.         readTimer->start(READ_TIME_OUT);
  78.     }
  79. }

  80. void YmodemFileReceive::writeTimeOut()
  81. {
  82.     writeTimer->stop();
  83.     serialPort->close();
  84.     receiveStatus(status);
  85. }

  86. Ymodem::Code YmodemFileReceive::callback(Status status, uint8_t *buff, uint32_t *len)
  87. {
  88.     switch(status)
  89.     {
  90.         case StatusEstablish:
  91.         {
  92.             if(buff[0] != 0)
  93.             {
  94.                 int  i         =  0;
  95.                 char name[128] = {0};
  96.                 char size[128] = {0};

  97.                 for(int j = 0; buff[i] != 0; i++, j++)
  98.                 {
  99.                     name[j] = buff[i];
  100.                 }

  101.                 i++;

  102.                 for(int j = 0; buff[i] != 0; i++, j++)
  103.                 {
  104.                     size[j] = buff[i];
  105.                 }

  106.                 fileName  = QString::fromLocal8Bit(name);
  107.                 fileSize  = QString(size).toULongLong();
  108.                 fileCount = 0;

  109.                 file->setFileName(filePath + fileName);

  110.                 if(file->open(QFile::WriteOnly) == true)
  111.                 {
  112.                     YmodemFileReceive::status = StatusEstablish;

  113.                     receiveStatus(StatusEstablish);

  114.                     return CodeAck;
  115.                 }
  116.                 else
  117.                 {
  118.                     YmodemFileReceive::status = StatusError;

  119.                     writeTimer->start(WRITE_TIME_OUT);

  120.                     return CodeCan;
  121.                 }
  122.             }
  123.             else
  124.             {
  125.                 YmodemFileReceive::status = StatusError;

  126.                 writeTimer->start(WRITE_TIME_OUT);

  127.                 return CodeCan;
  128.             }
  129.         }

  130.         case StatusTransmit:
  131.         {
  132.             if((fileSize - fileCount) > *len)
  133.             {
  134.                 file->write((char *)buff, *len);

  135.                 fileCount += *len;
  136.             }
  137.             else
  138.             {
  139.                 file->write((char *)buff, fileSize - fileCount);

  140.                 fileCount += fileSize - fileCount;
  141.             }

  142.             progress = (int)(fileCount * 100 / fileSize);

  143.             YmodemFileReceive::status = StatusTransmit;

  144.             receiveProgress(progress);
  145.             receiveStatus(StatusTransmit);

  146.             return CodeAck;
  147.         }

  148.         case StatusFinish:
  149.         {
  150.             file->close();

  151.             YmodemFileReceive::status = StatusFinish;

  152.             writeTimer->start(WRITE_TIME_OUT);

  153.             return CodeAck;
  154.         }

  155.         case StatusAbort:
  156.         {
  157.             file->close();

  158.             YmodemFileReceive::status = StatusAbort;

  159.             writeTimer->start(WRITE_TIME_OUT);

  160.             return CodeCan;
  161.         }

  162.         case StatusTimeout:
  163.         {
  164.             YmodemFileReceive::status = StatusTimeout;

  165.             writeTimer->start(WRITE_TIME_OUT);

  166.             return CodeCan;
  167.         }

  168.         default:
  169.         {
  170.             file->close();

  171.             YmodemFileReceive::status = StatusError;

  172.             writeTimer->start(WRITE_TIME_OUT);

  173.             return CodeCan;
  174.         }
  175.     }
  176. }

  177. uint32_t YmodemFileReceive::read(uint8_t *buff, uint32_t len)
  178. {
  179.     return serialPort->read((char *)buff, len);
  180. }

  181. uint32_t YmodemFileReceive::write(uint8_t *buff, uint32_t len)
  182. {
  183.     return serialPort->write((char *)buff, len);
  184. }
复制代码

      YmodemFileTransmit.h文件
  1. #ifndef YMODEMFILETRANSMIT_H
  2. #define YMODEMFILETRANSMIT_H

  3. #include <QFile>
  4. #include <QTimer>
  5. #include <QObject>
  6. #include <QSerialPort>
  7. #include "Ymodem.h"

  8. class YmodemFileTransmit : public QObject, public Ymodem
  9. {
  10.     Q_OBJECT

  11. public:
  12.     explicit YmodemFileTransmit(QObject *parent = 0);
  13.     ~YmodemFileTransmit();

  14.     void setFileName(const QString &name);

  15.     void setPortName(const QString &name);
  16.     void setPortBaudRate(qint32 baudrate);

  17.     bool startTransmit();
  18.     void stopTransmit();

  19.     int getTransmitProgress();
  20.     Status getTransmitStatus();

  21. signals:
  22.     void transmitProgress(int progress);
  23.     void transmitStatus(YmodemFileTransmit::Status status);

  24. private slots:
  25.     void readTimeOut();
  26.     void writeTimeOut();

  27. private:
  28.     Code callback(Status status, uint8_t *buff, uint32_t *len);

  29.     uint32_t read(uint8_t *buff, uint32_t len);
  30.     uint32_t write(uint8_t *buff, uint32_t len);

  31.     QFile       *file;
  32.     QTimer      *readTimer;
  33.     QTimer      *writeTimer;
  34.     QSerialPort *serialPort;

  35.     int      progress;
  36.     Status   status;
  37.     uint64_t fileSize;
  38.     uint64_t fileCount;
  39. };

  40. #endif // YMODEMFILETRANSMIT_H
复制代码

      YmodemFileTransmit.cpp文件
  1. #include "YmodemFileTransmit.h"
  2. #include <QFileInfo>

  3. #define READ_TIME_OUT   (10)
  4. #define WRITE_TIME_OUT  (100)

  5. YmodemFileTransmit::YmodemFileTransmit(QObject *parent) :
  6.     QObject(parent),
  7.     file(new QFile),
  8.     readTimer(new QTimer),
  9.     writeTimer(new QTimer),
  10.     serialPort(new QSerialPort)
  11. {
  12.     setTimeDivide(499);
  13.     setTimeMax(5);
  14.     setErrorMax(999);

  15.     serialPort->setPortName("COM1");
  16.     serialPort->setBaudRate(115200);
  17.     serialPort->setDataBits(QSerialPort::Data8);
  18.     serialPort->setStopBits(QSerialPort::OneStop);
  19.     serialPort->setParity(QSerialPort::NoParity);
  20.     serialPort->setFlowControl(QSerialPort::NoFlowControl);

  21.     connect(readTimer, SIGNAL(timeout()), this, SLOT(readTimeOut()));
  22.     connect(writeTimer, SIGNAL(timeout()), this, SLOT(writeTimeOut()));
  23. }

  24. YmodemFileTransmit::~YmodemFileTransmit()
  25. {
  26.     delete file;
  27.     delete readTimer;
  28.     delete writeTimer;
  29.     delete serialPort;
  30. }

  31. void YmodemFileTransmit::setFileName(const QString &name)
  32. {
  33.     file->setFileName(name);
  34. }

  35. void YmodemFileTransmit::setPortName(const QString &name)
  36. {
  37.     serialPort->setPortName(name);
  38. }

  39. void YmodemFileTransmit::setPortBaudRate(qint32 baudrate)
  40. {
  41.     serialPort->setBaudRate(baudrate);
  42. }

  43. bool YmodemFileTransmit::startTransmit()
  44. {
  45.     progress = 0;
  46.     status   = StatusEstablish;

  47.     if(serialPort->open(QSerialPort::ReadWrite) == true)
  48.     {
  49.         readTimer->start(READ_TIME_OUT);

  50.         return true;
  51.     }
  52.     else
  53.     {
  54.         return false;
  55.     }
  56. }

  57. void YmodemFileTransmit::stopTransmit()
  58. {
  59.     file->close();
  60.     abort();
  61.     status = StatusAbort;
  62.     writeTimer->start(WRITE_TIME_OUT);
  63. }

  64. int YmodemFileTransmit::getTransmitProgress()
  65. {
  66.     return progress;
  67. }

  68. Ymodem::Status YmodemFileTransmit::getTransmitStatus()
  69. {
  70.     return status;
  71. }

  72. void YmodemFileTransmit::readTimeOut()
  73. {
  74.     readTimer->stop();

  75.     transmit();

  76.     if((status == StatusEstablish) || (status == StatusTransmit))
  77.     {
  78.         readTimer->start(READ_TIME_OUT);
  79.     }
  80. }

  81. void YmodemFileTransmit::writeTimeOut()
  82. {
  83.     writeTimer->stop();
  84.     serialPort->close();
  85.     transmitStatus(status);
  86. }

  87. Ymodem::Code YmodemFileTransmit::callback(Status status, uint8_t *buff, uint32_t *len)
  88. {
  89.     switch(status)
  90.     {
  91.         case StatusEstablish:
  92.         {
  93.             if(file->open(QFile::ReadOnly) == true)
  94.             {
  95.                 QFileInfo fileInfo(*file);

  96.                 fileSize  = fileInfo.size();
  97.                 fileCount = 0;

  98.                 strcpy((char *)buff, fileInfo.fileName().toLocal8Bit().data());
  99.                 strcpy((char *)buff + fileInfo.fileName().toLocal8Bit().size() + 1, QByteArray::number(fileInfo.size()).data());

  100.                 *len = YMODEM_PACKET_SIZE;

  101.                 YmodemFileTransmit::status = StatusEstablish;

  102.                 transmitStatus(StatusEstablish);

  103.                 return CodeAck;
  104.             }
  105.             else
  106.             {
  107.                 YmodemFileTransmit::status = StatusError;

  108.                 writeTimer->start(WRITE_TIME_OUT);

  109.                 return CodeCan;
  110.             }
  111.         }

  112.         case StatusTransmit:
  113.         {
  114.             if(fileSize != fileCount)
  115.             {
  116.                 if((fileSize - fileCount) > YMODEM_PACKET_SIZE)
  117.                 {
  118.                     fileCount += file->read((char *)buff, YMODEM_PACKET_1K_SIZE);

  119.                     *len = YMODEM_PACKET_1K_SIZE;
  120.                 }
  121.                 else
  122.                 {
  123.                     fileCount += file->read((char *)buff, YMODEM_PACKET_SIZE);

  124.                     *len = YMODEM_PACKET_SIZE;
  125.                 }

  126.                 progress = (int)(fileCount * 100 / fileSize);

  127.                 YmodemFileTransmit::status = StatusTransmit;

  128.                 transmitProgress(progress);
  129.                 transmitStatus(StatusTransmit);

  130.                 return CodeAck;
  131.             }
  132.             else
  133.             {
  134.                 YmodemFileTransmit::status = StatusTransmit;

  135.                 transmitStatus(StatusTransmit);

  136.                 return CodeEot;
  137.             }
  138.         }

  139.         case StatusFinish:
  140.         {
  141.             file->close();

  142.             YmodemFileTransmit::status = StatusFinish;

  143.             writeTimer->start(WRITE_TIME_OUT);

  144.             return CodeAck;
  145.         }

  146.         case StatusAbort:
  147.         {
  148.             file->close();

  149.             YmodemFileTransmit::status = StatusAbort;

  150.             writeTimer->start(WRITE_TIME_OUT);

  151.             return CodeCan;
  152.         }

  153.         case StatusTimeout:
  154.         {
  155.             YmodemFileTransmit::status = StatusTimeout;

  156.             writeTimer->start(WRITE_TIME_OUT);

  157.             return CodeCan;
  158.         }

  159.         default:
  160.         {
  161.             file->close();

  162.             YmodemFileTransmit::status = StatusError;

  163.             writeTimer->start(WRITE_TIME_OUT);

  164.             return CodeCan;
  165.         }
  166.     }
  167. }

  168. uint32_t YmodemFileTransmit::read(uint8_t *buff, uint32_t len)
  169. {
  170.     return serialPort->read((char *)buff, len);
  171. }

  172. uint32_t YmodemFileTransmit::write(uint8_t *buff, uint32_t len)
  173. {
  174.     return serialPort->write((char *)buff, len);
  175. }
复制代码

      widget.ui文件
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <ui version="4.0">
  3. <class>Widget</class>
  4. <widget class="QWidget" name="Widget">
  5.   <property name="geometry">
  6.    <rect>
  7.     <x>0</x>
  8.     <y>0</y>
  9.     <width>444</width>
  10.     <height>255</height>
  11.    </rect>
  12.   </property>
  13.   <property name="minimumSize">
  14.    <size>
  15.     <width>444</width>
  16.     <height>255</height>
  17.    </size>
  18.   </property>
  19.   <property name="maximumSize">
  20.    <size>
  21.     <width>444</width>
  22.     <height>255</height>
  23.    </size>
  24.   </property>
  25.   <property name="windowTitle">
  26.    <string>SerialPortYmodem</string>
  27.   </property>
  28.   <layout class="QVBoxLayout" name="verticalLayout_3">
  29.    <item>
  30.     <widget class="QGroupBox" name="groupBox">
  31.      <property name="title">
  32.       <string>串口配置</string>
  33.      </property>
  34.      <layout class="QHBoxLayout" name="horizontalLayout">
  35.       <item>
  36.        <widget class="QLabel" name="label">
  37.         <property name="text">
  38.          <string>端口:</string>
  39.         </property>
  40.        </widget>
  41.       </item>
  42.       <item>
  43.        <widget class="QComboBox" name="comPort">
  44.         <property name="maxVisibleItems">
  45.          <number>12</number>
  46.         </property>
  47.        </widget>
  48.       </item>
  49.       <item>
  50.        <spacer name="horizontalSpacer">
  51.         <property name="orientation">
  52.          <enum>Qt::Horizontal</enum>
  53.         </property>
  54.         <property name="sizeHint" stdset="0">
  55.          <size>
  56.           <width>40</width>
  57.           <height>20</height>
  58.          </size>
  59.         </property>
  60.        </spacer>
  61.       </item>
  62.       <item>
  63.        <widget class="QLabel" name="label_2">
  64.         <property name="text">
  65.          <string>波特率:</string>
  66.         </property>
  67.        </widget>
  68.       </item>
  69.       <item>
  70.        <widget class="QComboBox" name="comBaudRate">
  71.         <property name="currentText">
  72.          <string>115200</string>
  73.         </property>
  74.         <property name="currentIndex">
  75.          <number>3</number>
  76.         </property>
  77.         <property name="maxVisibleItems">
  78.          <number>12</number>
  79.         </property>
  80.         <item>
  81.          <property name="text">
  82.           <string>921600</string>
  83.          </property>
  84.         </item>
  85.         <item>
  86.          <property name="text">
  87.           <string>460800</string>
  88.          </property>
  89.         </item>
  90.         <item>
  91.          <property name="text">
  92.           <string>230400</string>
  93.          </property>
  94.         </item>
  95.         <item>
  96.          <property name="text">
  97.           <string>115200</string>
  98.          </property>
  99.         </item>
  100.         <item>
  101.          <property name="text">
  102.           <string>57600</string>
  103.          </property>
  104.         </item>
  105.         <item>
  106.          <property name="text">
  107.           <string>38400</string>
  108.          </property>
  109.         </item>
  110.         <item>
  111.          <property name="text">
  112.           <string>19200</string>
  113.          </property>
  114.         </item>
  115.         <item>
  116.          <property name="text">
  117.           <string>9600</string>
  118.          </property>
  119.         </item>
  120.         <item>
  121.          <property name="text">
  122.           <string>4800</string>
  123.          </property>
  124.         </item>
  125.         <item>
  126.          <property name="text">
  127.           <string>2400</string>
  128.          </property>
  129.         </item>
  130.         <item>
  131.          <property name="text">
  132.           <string>1200</string>
  133.          </property>
  134.         </item>
  135.        </widget>
  136.       </item>
  137.       <item>
  138.        <spacer name="horizontalSpacer_2">
  139.         <property name="orientation">
  140.          <enum>Qt::Horizontal</enum>
  141.         </property>
  142.         <property name="sizeHint" stdset="0">
  143.          <size>
  144.           <width>40</width>
  145.           <height>20</height>
  146.          </size>
  147.         </property>
  148.        </spacer>
  149.       </item>
  150.       <item>
  151.        <widget class="QPushButton" name="comButton">
  152.         <property name="text">
  153.          <string>打开</string>
  154.         </property>
  155.        </widget>
  156.       </item>
  157.      </layout>
  158.     </widget>
  159.    </item>
  160.    <item>
  161.     <widget class="QGroupBox" name="groupBox_2">
  162.      <property name="title">
  163.       <string>文件发送</string>
  164.      </property>
  165.      <layout class="QVBoxLayout" name="verticalLayout">
  166.       <item>
  167.        <layout class="QHBoxLayout" name="horizontalLayout_2">
  168.         <item>
  169.          <widget class="QLabel" name="label_3">
  170.           <property name="text">
  171.            <string>文件路径:</string>
  172.           </property>
  173.          </widget>
  174.         </item>
  175.         <item>
  176.          <widget class="QLineEdit" name="transmitPath">
  177.           <property name="readOnly">
  178.            <bool>true</bool>
  179.           </property>
  180.          </widget>
  181.         </item>
  182.         <item>
  183.          <widget class="QPushButton" name="transmitBrowse">
  184.           <property name="enabled">
  185.            <bool>false</bool>
  186.           </property>
  187.           <property name="text">
  188.            <string>浏览...</string>
  189.           </property>
  190.          </widget>
  191.         </item>
  192.         <item>
  193.          <widget class="QPushButton" name="transmitButton">
  194.           <property name="enabled">
  195.            <bool>false</bool>
  196.           </property>
  197.           <property name="text">
  198.            <string>发送</string>
  199.           </property>
  200.          </widget>
  201.         </item>
  202.        </layout>
  203.       </item>
  204.       <item>
  205.        <layout class="QHBoxLayout" name="horizontalLayout_3">
  206.         <item>
  207.          <widget class="QLabel" name="label_5">
  208.           <property name="text">
  209.            <string>传输进度:</string>
  210.           </property>
  211.          </widget>
  212.         </item>
  213.         <item>
  214.          <widget class="QProgressBar" name="transmitProgress">
  215.           <property name="value">
  216.            <number>0</number>
  217.           </property>
  218.          </widget>
  219.         </item>
  220.        </layout>
  221.       </item>
  222.      </layout>
  223.     </widget>
  224.    </item>
  225.    <item>
  226.     <widget class="QGroupBox" name="groupBox_3">
  227.      <property name="title">
  228.       <string>文件接收</string>
  229.      </property>
  230.      <layout class="QVBoxLayout" name="verticalLayout_2">
  231.       <item>
  232.        <layout class="QHBoxLayout" name="horizontalLayout_4">
  233.         <item>
  234.          <widget class="QLabel" name="label_4">
  235.           <property name="text">
  236.            <string>文件路径:</string>
  237.           </property>
  238.          </widget>
  239.         </item>
  240.         <item>
  241.          <widget class="QLineEdit" name="receivePath">
  242.           <property name="readOnly">
  243.            <bool>true</bool>
  244.           </property>
  245.          </widget>
  246.         </item>
  247.         <item>
  248.          <widget class="QPushButton" name="receiveBrowse">
  249.           <property name="enabled">
  250.            <bool>false</bool>
  251.           </property>
  252.           <property name="text">
  253.            <string>浏览...</string>
  254.           </property>
  255.          </widget>
  256.         </item>
  257.         <item>
  258.          <widget class="QPushButton" name="receiveButton">
  259.           <property name="enabled">
  260.            <bool>false</bool>
  261.           </property>
  262.           <property name="text">
  263.            <string>接收</string>
  264.           </property>
  265.          </widget>
  266.         </item>
  267.        </layout>
  268.       </item>
  269.       <item>
  270.        <layout class="QHBoxLayout" name="horizontalLayout_5">
  271.         <item>
  272.          <widget class="QLabel" name="label_6">
  273.           <property name="text">
  274.            <string>传输进度:</string>
  275.           </property>
  276.          </widget>
  277.         </item>
  278.         <item>
  279.          <widget class="QProgressBar" name="receiveProgress">
  280.           <property name="value">
  281.            <number>0</number>
  282.           </property>
  283.          </widget>
  284.         </item>
  285.        </layout>
  286.       </item>
  287.      </layout>
  288.     </widget>
  289.    </item>
  290.   </layout>
  291. </widget>
  292. <layoutdefault spacing="6" margin="11"/>
  293. <resources/>
  294. <connections/>
  295. </ui>
复制代码

      widget.h文件
  1. #ifndef WIDGET_H
  2. #define WIDGET_H

  3. #include <QWidget>
  4. #include "YmodemFileTransmit.h"
  5. #include "YmodemFileReceive.h"

  6. namespace Ui {
  7. class Widget;
  8. }

  9. class Widget : public QWidget
  10. {
  11.     Q_OBJECT

  12. public:
  13.     explicit Widget(QWidget *parent = 0);
  14.     ~Widget();

  15. private slots:
  16.     void on_comButton_clicked();
  17.     void on_transmitBrowse_clicked();
  18.     void on_receiveBrowse_clicked();
  19.     void on_transmitButton_clicked();
  20.     void on_receiveButton_clicked();
  21.     void transmitProgress(int progress);
  22.     void receiveProgress(int progress);
  23.     void transmitStatus(YmodemFileTransmit::Status status);
  24.     void receiveStatus(YmodemFileReceive::Status status);

  25. private:
  26.     Ui::Widget *ui;
  27.     QSerialPort *serialPort;
  28.     YmodemFileTransmit *ymodemFileTransmit;
  29.     YmodemFileReceive *ymodemFileReceive;

  30.     bool transmitButtonStatus;
  31.     bool receiveButtonStatus;
  32. };

  33. #endif // WIDGET_H
复制代码

      widget.cpp文件
  1. #include "widget.h"
  2. #include "ui_widget.h"
  3. #include <QMessageBox>
  4. #include <QFileDialog>
  5. #include <QSerialPortInfo>

  6. Widget::Widget(QWidget *parent) :
  7.     QWidget(parent),
  8.     ui(new Ui::Widget),
  9.     serialPort(new QSerialPort),
  10.     ymodemFileTransmit(new YmodemFileTransmit),
  11.     ymodemFileReceive(new YmodemFileReceive)
  12. {
  13.     transmitButtonStatus = false;
  14.     receiveButtonStatus  = false;

  15.     ui->setupUi(this);

  16.     QSerialPortInfo serialPortInfo;

  17.     foreach(serialPortInfo, QSerialPortInfo::availablePorts())
  18.     {
  19.         ui->comPort->addItem(serialPortInfo.portName());
  20.     }

  21.     serialPort->setPortName("COM1");
  22.     serialPort->setBaudRate(115200);
  23.     serialPort->setDataBits(QSerialPort::Data8);
  24.     serialPort->setStopBits(QSerialPort::OneStop);
  25.     serialPort->setParity(QSerialPort::NoParity);
  26.     serialPort->setFlowControl(QSerialPort::NoFlowControl);

  27.     connect(ymodemFileTransmit, SIGNAL(transmitProgress(int)), this, SLOT(transmitProgress(int)));
  28.     connect(ymodemFileReceive, SIGNAL(receiveProgress(int)), this, SLOT(receiveProgress(int)));

  29.    connect(ymodemFileTransmit,
  30. SIGNAL(transmitStatus(YmodemFileTransmit::Status)), this,
  31. SLOT(transmitStatus(YmodemFileTransmit::Status)));
  32.    
  33. connect(ymodemFileReceive,
  34. SIGNAL(receiveStatus(YmodemFileReceive::Status)), this,
  35. SLOT(receiveStatus(YmodemFileReceive::Status)));
  36. }

  37. Widget::~Widget()
  38. {
  39.     delete ui;
  40.     delete serialPort;
  41.     delete ymodemFileTransmit;
  42.     delete ymodemFileReceive;
  43. }

  44. void Widget::on_comButton_clicked()
  45. {
  46.     static bool button_status = false;

  47.     if(button_status == false)
  48.     {
  49.         serialPort->setPortName(ui->comPort->currentText());
  50.         serialPort->setBaudRate(ui->comBaudRate->currentText().toInt());

  51.         if(serialPort->open(QSerialPort::ReadWrite) == true)
  52.         {
  53.             button_status = true;

  54.             ui->comPort->setDisabled(true);
  55.             ui->comBaudRate->setDisabled(true);
  56.             ui->comButton->setText(u8"关闭串口");

  57.             ui->transmitBrowse->setEnabled(true);
  58.             ui->receiveBrowse->setEnabled(true);

  59.             if(ui->transmitPath->text().isEmpty() != true)
  60.             {
  61.                 ui->transmitButton->setEnabled(true);
  62.             }

  63.             if(ui->receivePath->text().isEmpty() != true)
  64.             {
  65.                 ui->receiveButton->setEnabled(true);
  66.             }
  67.         }
  68.         else
  69.         {
  70.             QMessageBox::warning(this, u8"串口打开失败", u8"请检查串口是否已被占用!", u8"关闭");
  71.         }
  72.     }
  73.     else
  74.     {
  75.         button_status = false;

  76.         serialPort->close();

  77.         ui->comPort->setEnabled(true);
  78.         ui->comBaudRate->setEnabled(true);
  79.         ui->comButton->setText(u8"打开串口");

  80.         ui->transmitBrowse->setDisabled(true);
  81.         ui->transmitButton->setDisabled(true);

  82.         ui->receiveBrowse->setDisabled(true);
  83.         ui->receiveButton->setDisabled(true);
  84.     }
  85. }

  86. void Widget::on_transmitBrowse_clicked()
  87. {
  88.     ui->transmitPath->setText(QFileDialog::getOpenFileName(this, u8"打开文件", ".", u8"任意文件 (*.*)"));

  89.     if(ui->transmitPath->text().isEmpty() != true)
  90.     {
  91.         ui->transmitButton->setEnabled(true);
  92.     }
  93.     else
  94.     {
  95.         ui->transmitButton->setDisabled(true);
  96.     }
  97. }

  98. void Widget::on_receiveBrowse_clicked()
  99. {
  100.     ui->receivePath->setText(QFileDialog::getExistingDirectory(this, u8"选择目录", ".", QFileDialog::ShowDirsOnly));

  101.     if(ui->receivePath->text().isEmpty() != true)
  102.     {
  103.         ui->receiveButton->setEnabled(true);
  104.     }
  105.     else
  106.     {
  107.         ui->receiveButton->setDisabled(true);
  108.     }
  109. }

  110. void Widget::on_transmitButton_clicked()
  111. {
  112.     if(transmitButtonStatus == false)
  113.     {
  114.         serialPort->close();

  115.         ymodemFileTransmit->setFileName(ui->transmitPath->text());
  116.         ymodemFileTransmit->setPortName(ui->comPort->currentText());
  117.         ymodemFileTransmit->setPortBaudRate(ui->comBaudRate->currentText().toInt());

  118.         if(ymodemFileTransmit->startTransmit() == true)
  119.         {
  120.             transmitButtonStatus = true;

  121.             ui->comButton->setDisabled(true);

  122.             ui->receiveBrowse->setDisabled(true);
  123.             ui->receiveButton->setDisabled(true);

  124.             ui->transmitBrowse->setDisabled(true);
  125.             ui->transmitButton->setText(u8"取消");
  126.             ui->transmitProgress->setValue(0);
  127.         }
  128.         else
  129.         {
  130.             QMessageBox::warning(this, u8"失败", u8"文件发送失败!", u8"关闭");
  131.         }
  132.     }
  133.     else
  134.     {
  135.         ymodemFileTransmit->stopTransmit();
  136.     }
  137. }

  138. void Widget::on_receiveButton_clicked()
  139. {
  140.     if(receiveButtonStatus == false)
  141.     {
  142.         serialPort->close();

  143.         ymodemFileReceive->setFilePath(ui->receivePath->text());
  144.         ymodemFileReceive->setPortName(ui->comPort->currentText());
  145.         ymodemFileReceive->setPortBaudRate(ui->comBaudRate->currentText().toInt());

  146.         if(ymodemFileReceive->startReceive() == true)
  147.         {
  148.             receiveButtonStatus = true;

  149.             ui->comButton->setDisabled(true);

  150.             ui->transmitBrowse->setDisabled(true);
  151.             ui->transmitButton->setDisabled(true);

  152.             ui->receiveBrowse->setDisabled(true);
  153.             ui->receiveButton->setText(u8"取消");
  154.             ui->receiveProgress->setValue(0);
  155.         }
  156.         else
  157.         {
  158.             QMessageBox::warning(this, u8"失败", u8"文件接收失败!", u8"关闭");
  159.         }
  160.     }
  161.     else
  162.     {
  163.         ymodemFileReceive->stopReceive();
  164.     }
  165. }

  166. void Widget::transmitProgress(int progress)
  167. {
  168.     ui->transmitProgress->setValue(progress);
  169. }

  170. void Widget::receiveProgress(int progress)
  171. {
  172.     ui->receiveProgress->setValue(progress);
  173. }

  174. void Widget::transmitStatus(Ymodem::Status status)
  175. {
  176.     switch(status)
  177.     {
  178.         case YmodemFileTransmit::StatusEstablish:
  179.         {
  180.             break;
  181.         }

  182.         case YmodemFileTransmit::StatusTransmit:
  183.         {
  184.             break;
  185.         }

  186.         case YmodemFileTransmit::StatusFinish:
  187.         {
  188.             transmitButtonStatus = false;

  189.             ui->comButton->setEnabled(true);

  190.             ui->receiveBrowse->setEnabled(true);

  191.             if(ui->receivePath->text().isEmpty() != true)
  192.             {
  193.                 ui->receiveButton->setEnabled(true);
  194.             }

  195.             ui->transmitBrowse->setEnabled(true);
  196.             ui->transmitButton->setText(u8"发送");

  197.             QMessageBox::warning(this, u8"成功", u8"文件发送成功!", u8"关闭");

  198.             break;
  199.         }

  200.         case YmodemFileTransmit::StatusAbort:
  201.         {
  202.             transmitButtonStatus = false;

  203.             ui->comButton->setEnabled(true);

  204.             ui->receiveBrowse->setEnabled(true);

  205.             if(ui->receivePath->text().isEmpty() != true)
  206.             {
  207.                 ui->receiveButton->setEnabled(true);
  208.             }

  209.             ui->transmitBrowse->setEnabled(true);
  210.             ui->transmitButton->setText(u8"发送");

  211.             QMessageBox::warning(this, u8"失败", u8"文件发送失败!", u8"关闭");

  212.             break;
  213.         }

  214.         case YmodemFileTransmit::StatusTimeout:
  215.         {
  216.             transmitButtonStatus = false;

  217.             ui->comButton->setEnabled(true);

  218.             ui->receiveBrowse->setEnabled(true);

  219.             if(ui->receivePath->text().isEmpty() != true)
  220.             {
  221.                 ui->receiveButton->setEnabled(true);
  222.             }

  223.             ui->transmitBrowse->setEnabled(true);
  224.             ui->transmitButton->setText(u8"发送");

  225.             QMessageBox::warning(this, u8"失败", u8"文件发送失败!", u8"关闭");

  226.             break;
  227.         }

  228.         default:
  229.         {
  230.             transmitButtonStatus = false;

  231.             ui->comButton->setEnabled(true);

  232.             ui->receiveBrowse->setEnabled(true);

  233.             if(ui->receivePath->text().isEmpty() != true)
  234.             {
  235.                 ui->receiveButton->setEnabled(true);
  236.             }

  237.             ui->transmitBrowse->setEnabled(true);
  238.             ui->transmitButton->setText(u8"发送");

  239.             QMessageBox::warning(this, u8"失败", u8"文件发送失败!", u8"关闭");
  240.         }
  241.     }
  242. }

  243. void Widget::receiveStatus(YmodemFileReceive::Status status)
  244. {
  245.     switch(status)
  246.     {
  247.         case YmodemFileReceive::StatusEstablish:
  248.         {
  249.             break;
  250.         }

  251.         case YmodemFileReceive::StatusTransmit:
  252.         {
  253.             break;
  254.         }

  255.         case YmodemFileReceive::StatusFinish:
  256.         {
  257.             receiveButtonStatus = false;

  258.             ui->comButton->setEnabled(true);

  259.             ui->transmitBrowse->setEnabled(true);

  260.             if(ui->transmitPath->text().isEmpty() != true)
  261.             {
  262.                 ui->transmitButton->setEnabled(true);
  263.             }

  264.             ui->receiveBrowse->setEnabled(true);
  265.             ui->receiveButton->setText(u8"接收");

  266.             QMessageBox::warning(this, u8"成功", u8"文件接收成功!", u8"关闭");

  267.             break;
  268.         }

  269.         case YmodemFileReceive::StatusAbort:
  270.         {
  271.             receiveButtonStatus = false;

  272.             ui->comButton->setEnabled(true);

  273.             ui->transmitBrowse->setEnabled(true);

  274.             if(ui->transmitPath->text().isEmpty() != true)
  275.             {
  276.                 ui->transmitButton->setEnabled(true);
  277.             }

  278.             ui->receiveBrowse->setEnabled(true);
  279.             ui->receiveButton->setText(u8"接收");

  280.             QMessageBox::warning(this, u8"失败", u8"文件接收失败!", u8"关闭");

  281.             break;
  282.         }

  283.         case YmodemFileReceive::StatusTimeout:
  284.         {
  285.             receiveButtonStatus = false;

  286.             ui->comButton->setEnabled(true);

  287.             ui->transmitBrowse->setEnabled(true);

  288.             if(ui->transmitPath->text().isEmpty() != true)
  289.             {
  290.                 ui->transmitButton->setEnabled(true);
  291.             }

  292.             ui->receiveBrowse->setEnabled(true);
  293.             ui->receiveButton->setText(u8"接收");

  294.             QMessageBox::warning(this, u8"失败", u8"文件接收失败!", u8"关闭");

  295.             break;
  296.         }

  297.         default:
  298.         {
  299.             receiveButtonStatus = false;

  300.             ui->comButton->setEnabled(true);

  301.             ui->transmitBrowse->setEnabled(true);

  302.             if(ui->transmitPath->text().isEmpty() != true)
  303.             {
  304.                 ui->transmitButton->setEnabled(true);
  305.             }

  306.             ui->receiveBrowse->setEnabled(true);
  307.             ui->receiveButton->setText(u8"接收");

  308.             QMessageBox::warning(this, u8"失败", u8"文件接收失败!", u8"关闭");
  309.         }
  310.     }
  311. }
复制代码

      main.cpp文件
  1. #include "widget.h"
  2. #include <QApplication>

  3. int main(int argc, char *argv[])
  4. {
  5.     QApplication a(argc, argv);
  6.     Widget w;
  7.     w.show();

  8.     return a.exec();
  9. }
复制代码

      SerialPortYmodem.pro文件
  1. #-------------------------------------------------
  2. #
  3. # Project created by QtCreator 2018-01-20T23:00:46
  4. #
  5. #-------------------------------------------------

  6. QT       += core gui
  7. QT       += serialport

  8. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

  9. TARGET = SerialPortYmodem
  10. TEMPLATE = app

  11. # The following define makes your compiler emit warnings if you use
  12. # any feature of Qt which as been marked as deprecated (the exact warnings
  13. # depend on your compiler). Please consult the documentation of the
  14. # deprecated API in order to know how to port your code away from it.
  15. DEFINES += QT_DEPRECATED_WARNINGS

  16. # You can also make your code fail to compile if you use deprecated APIs.
  17. # In order to do so, uncomment the following line.
  18. # You can also select to disable deprecated APIs only up to a certain version of Qt.
  19. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0


  20. SOURCES += main.cpp\
  21.         widget.cpp \
  22.     YmodemFileReceive.cpp \
  23.     Ymodem.cpp \
  24.     YmodemFileTransmit.cpp

  25. HEADERS  += widget.h \
  26.     Ymodem.h \
  27.     YmodemFileReceive.h \
  28.     YmodemFileTransmit.h

  29. FORMS    += widget.ui

  30. RC_ICONS = SerialPortYmodem.ico
复制代码

      SerialPortYmodem.ico文件

3,运行效果













回复

使用道具 举报

19

主题

15

回帖

72

积分

初级会员

积分
72
 楼主| 发表于 2018-3-7 20:26:40 | 显示全部楼层
可以用来做用户程序升级的上位机软件。GitHub仓库有工程,还有资料。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-5 07:14 , Processed in 0.159010 second(s), 23 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表