久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 21798|回復(fù): 2
打印 上一主題 下一主題
收起左側(cè)

YModem通信協(xié)議的補(bǔ)充說明(源碼勝于雄辯)[原創(chuàng)]

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:75926 發(fā)表于 2015-4-4 01:43 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
/**
  ******************************************************************************
  * @file    ymodem_daxia.c
  * @author  wjandsq@163.com
  * @version V2.0.2
  * @date    2014.12.06
  * @brief   Y-Modem 協(xié)議文件接收 (適用于ARM及X86平臺(tái))
  ******************************************************************************
  * @copy
  *
  * Copyright (c) 2013-2014
  *
  */
extern "C" {
#include "crc.h"
#include "crc16.h"
}
#ifndef STM32Fxxx
#include <stdint.h>
#include <stdbool.h>
#endif

#ifdef STM32Fxxx
// 發(fā)送字符串到USB端點(diǎn)(USB虛擬串口)
void VCP_MI_02_IN(uint8_t *buf, uint8_t count);
void VCP_MI_00_IN(uint8_t *buf, uint8_t count);
#else
// 發(fā)送字符串到串口1(發(fā)送完畢關(guān)閉串口1)
void SendStringWithClose(unsigned char * buf, unsigned short len);
#endif
uint16_t Y_Modem_CRC(uint8_t * buf, uint16_t len);
#define     __IO    volatile
/* Includes ------------------------------------------------------------------*/
//#include "ymodem_daxia.h"
#ifdef STM32Fxxx
#include "stm32_flash_read_write.h"
#include "usb_lib.h"
#endif
/* Extern function -----------------------------------------------------------*/
#ifdef STM32Fxxx
extern void NVIC_Configuration(void);
extern void NVIC_DISABLE(void);
extern void ChipHalInit(void);
#endif
/* Extern variables ----------------------------------------------------------*/
extern __IO uint8_t  USART1_Tx_Buffer[];
extern __IO uint16_t USART1_TxLength;
extern __IO uint16_t USART1_TxCount;
extern __IO uint8_t  USART1_Rx_Buffer [];
extern __IO uint8_t  USART1_Rx_Buffer2[];
extern __IO uint32_t USART1_RxCount;
extern __IO uint16_t USART1_Rx_ptr_in;

extern __IO uint16_t Y_Modem_TMP1;
extern __IO uint16_t Over_Time_Cnt;
extern __IO uint32_t into_app_cnt;
extern uint16_t CRC16;
extern uint16_t CRC16_Tmp;
extern uint8_t  FileName[];
extern uint32_t FileLength;
extern uint32_t Write_Counter;
extern __IO bool Flag_App_Rece_OK;
extern __IO bool Flag1_1Ms;    // 系統(tǒng)定時(shí)器1MS標(biāo)志1
extern __IO bool Flag2_1Ms;    // 系統(tǒng)定時(shí)器1MS標(biāo)志2

/* Private define ------------------------------------------------------------*/
#define MODEM_SOH 0x01 //133字節(jié)數(shù)據(jù)包類型,接收正常回應(yīng)0x06(含文件信息的第一個(gè)包接收正常需回應(yīng)0x06、0x43)
#define MODEM_STX 0x02 //1029字節(jié)數(shù)據(jù)包類型,接收正常回應(yīng)0x06
#define MODEM_EOT 0x04 //發(fā)送文件傳輸結(jié)束命令,接收正常回應(yīng)0x06、0x43(啟動(dòng)空包發(fā)送)
#define MODEM_ACK 0x06 //發(fā)送確認(rèn)應(yīng)答,接收方crc校驗(yàn)成功或收到已定義的命令
#define MODEM_NAK 0x15 //發(fā)送重傳當(dāng)前數(shù)據(jù)包請(qǐng)求,接收方crc校驗(yàn)出錯(cuò)
#define MODEM_CAN 0x18 //發(fā)送取消傳輸命令,連續(xù)發(fā)送5個(gè)字符
#define MODEM_C   0x43 //發(fā)送大寫字母C(三種情況下發(fā)送該字符: 1.啟動(dòng)通信握手.2.啟動(dòng)數(shù)據(jù)包發(fā)送.3.啟動(dòng)空包發(fā)送)
#define TIME_OVER_SETUP1  10000
#define TIME_OVER_SETUP2  30000
#ifdef STM32Fxxx
/*
函數(shù)功能: 大于或等于2K的程序數(shù)據(jù),寫入Flash
    小于2048不寫入,直接返回
*/
void Flash_Write_2K(void)
{
uint32_t tmp;
if(USART1_RxCount > Write_Counter){
  tmp = USART1_RxCount - Write_Counter;
  if(tmp >= 2048){
   iap_write_appbin(FLASH_APP1_ADDR + Write_Counter, (uint8_t *)USART1_Rx_Buffer2, tmp);
   Write_Counter += tmp;
  }
}
}
/*
函數(shù)功能: 寫入小于或等于128字節(jié)的程序數(shù)據(jù)
    若最后一個(gè)包小于1024字節(jié), 則發(fā)送128字節(jié)的數(shù)據(jù)包,以(SOH)開始
參數(shù)列表:

*/
void Flash_Write_128(void)
{
uint32_t tmp;
if(USART1_RxCount > Write_Counter){
  tmp = USART1_RxCount - Write_Counter;
  if(tmp <= 128){
           iap_write_appbin(FLASH_APP1_ADDR + Write_Counter, (uint8_t *)USART1_Rx_Buffer2, tmp);                           
           Write_Counter += tmp;
        }
    }
}
/* 虛擬串口MI_02接收監(jiān)控 */
void VCP_MI_02_IN (uint8_t *buf, uint8_t count){
    USB_SIL_Write(EP4_IN, &buf[0], count);
    SetEPTxValid(ENDP4);
}
/* 虛擬串口MI_00接收監(jiān)控 */
void VCP_MI_00_IN (uint8_t *buf, uint8_t count){
USB_SIL_Write(EP1_IN, &buf[0], count);
SetEPTxValid(ENDP1);
}
#endif

// 取消傳輸
void Cancel_Transmission(void)
{
uint8_t USB_IN_buf[5];
  // 取消傳輸
USB_IN_buf[0] = MODEM_CAN;
USB_IN_buf[1] = MODEM_CAN;
USB_IN_buf[2] = MODEM_CAN;
USB_IN_buf[3] = MODEM_CAN;
USB_IN_buf[4] = MODEM_CAN;
#ifdef STM32Fxxx
USB_SIL_Write(EP4_IN, &USB_IN_buf[0], 5);
SetEPTxValid(ENDP4);
#else
#endif
}
// 回復(fù)確認(rèn)
void Send_ACK(void)
{
uint8_t USB_IN_buf[2];
// 回復(fù)確認(rèn)
USB_IN_buf[0] = MODEM_ACK;
#ifdef STM32Fxxx
USB_SIL_Write(EP4_IN, &USB_IN_buf[0], 1);
SetEPTxValid(ENDP4);
#endif
}
// 回復(fù)繼續(xù)
void Send_MODEM_C(void)
{
uint8_t USB_IN_buf[1];
USB_IN_buf[0] = MODEM_C;
#ifdef STM32Fxxx
USB_SIL_Write(EP4_IN, &USB_IN_buf[0], 1);
SetEPTxValid(ENDP4);
#endif
}
// 回復(fù)確認(rèn)、繼續(xù)
void Send_ACK_Continue(void)
{
uint8_t USB_IN_buf[2];
// 回復(fù)確認(rèn)、繼續(xù)
USB_IN_buf[0] = MODEM_ACK;
USB_IN_buf[1] = MODEM_C;
#ifdef STM32Fxxx
USB_SIL_Write(EP4_IN, &USB_IN_buf[0], 2);
SetEPTxValid(ENDP4);
#endif
}
/*
函數(shù)功能: 為實(shí)時(shí)響應(yīng), 需連續(xù)調(diào)用,以盡快處理Y_Modem協(xié)議接收的數(shù)據(jù)
參數(shù)列表:
Flag_Timer_1MS    系統(tǒng)1ms標(biāo)志傳入函數(shù), 但函數(shù)不對(duì)該標(biāo)志做改動(dòng)
Y_Modem_TMP1      全局變量
USART1_Rx_Buffer  4K byte  4K文件內(nèi)容接收緩沖
USART1_Rx_ptr_in  USART1_Rx_Buffer  數(shù)據(jù)指針當(dāng)前位置
USART1_Rx_Buffer2 4K byte  4K文件內(nèi)容寫入Flash緩沖
USART1_RxCount    USART1_Rx_Buffer2 數(shù)據(jù)指針當(dāng)前位置
*/
extern uint8_t Flag_App_Update;
static uint16_t temp_cnt;
static uint16_t temp_cnt2 = 0;
void Y_Modem_Receive(void)
{
uint32_t Y_Modem_TMP2;
uint32_t Y_Modem_TMP3;
uint32_t Y_Modem_TMP4;
uint32_t Y_Modem_TMP5;
uint8_t USB_IN_buf[5];
#ifndef STM32Fxxx
Flag2_1Ms = true;
#endif
switch(Y_Modem_TMP1){
  case 0:
   break;
  case 1:
    if(Flag2_1Ms == true){
     Flag2_1Ms = false;
     if(Flag_App_Update == 1){
      // 更新標(biāo)志上電隨機(jī)設(shè)置為1或從用戶程序跳轉(zhuǎn)過來
      // 上電隨機(jī)設(shè)置為1的情況不能啟動(dòng),所以存在bug
     }else{
      // 更新標(biāo)志上電隨機(jī)設(shè)置為非零值
      if (++temp_cnt2 > 200){
     temp_cnt2  = 0;
                    Flag_App_Update = 0;
                  }
              }
              if (++temp_cnt > 2000){
      temp_cnt = 0;
      Send_MODEM_C();
     #ifdef STM32Fxxx
      USB_IN_buf[0] = *((uint8_t *)0x20004000);
      VCP_MI_00_IN(&USB_IN_buf[0],1);
     #endif
                  // 4K 緩沖清零
                  for(Y_Modem_TMP2 = 0; Y_Modem_TMP2 < 0x1000; ++Y_Modem_TMP2) {
                      USART1_Rx_Buffer[Y_Modem_TMP2] = 0;
                      USART1_Rx_Buffer2[Y_Modem_TMP2] = 0;
                  }   
                  USART1_Rx_ptr_in = 0;
                  USART1_RxCount   = 0;
                  Write_Counter = 0;               
              }
          }            
          if(USART1_Rx_ptr_in > 0){
              if(USART1_Rx_Buffer[0] == MODEM_SOH){
                  if(USART1_Rx_ptr_in >= 133){
                      Y_Modem_TMP1 = 2;
                  }
              }
          }
         break;
     case 2:
          // 第2步,處理128字節(jié)數(shù)據(jù)塊(傳輸文件名,文件大小信息)
   if(Flag2_1Ms == true){
    Flag2_1Ms = false;
    if (++Over_Time_Cnt > TIME_OVER_SETUP1){
     Cancel_Transmission(); // 取消傳輸
     Y_Modem_TMP1 = 0;
     Over_Time_Cnt = 0;
      #ifdef STM32Fxxx
     USB_IN_buf[0] = 0x01;
     VCP_MI_00_IN(&USB_IN_buf[0],1);
    #endif
    }
         }
         if(USART1_Rx_ptr_in > 0){
    // 第2步,如果有數(shù)據(jù)傳輸,則進(jìn)行處理
             // MODEM_SOH 128字節(jié)數(shù)據(jù)塊
             if(USART1_Rx_Buffer[0] == MODEM_SOH){
                 if(USART1_Rx_ptr_in >= 133){
                     CRC16 = Y_Modem_CRC((uint8_t *)&USART1_Rx_Buffer[3], 128);
                     CRC16_Tmp  = USART1_Rx_Buffer[131];
                     CRC16_Tmp  = CRC16_Tmp << 8;
                     CRC16_Tmp |= USART1_Rx_Buffer[132];                           
            
                     if(CRC16_Tmp == CRC16){
                         // 獲取文件名
                         for(Y_Modem_TMP2 = 0; Y_Modem_TMP2 < 128; ++Y_Modem_TMP2) {
                             FileName[Y_Modem_TMP2] = 0;
                         }
                         Y_Modem_TMP3 = 0;
                         for(Y_Modem_TMP2 = 3; Y_Modem_TMP2 < 128; ) {
                             if(USART1_Rx_Buffer[Y_Modem_TMP2]!= 0){
                                 FileName[Y_Modem_TMP3] = USART1_Rx_Buffer[Y_Modem_TMP2];
                             } else {
                                 ++Y_Modem_TMP2;
                                 break;
                             }
                             ++Y_Modem_TMP3;
                             ++Y_Modem_TMP2;
                         }
                         // 獲取文件長(zhǎng)度
                         for(FileLength = 0; Y_Modem_TMP2 <= 133; ++Y_Modem_TMP2) {
                             if(USART1_Rx_Buffer[Y_Modem_TMP2]!= 0){
                                 if((USART1_Rx_Buffer[Y_Modem_TMP2] >= 0x30)
                                     && (USART1_Rx_Buffer[Y_Modem_TMP2] <= 0x39)){
                                     FileLength = FileLength * 10 + USART1_Rx_Buffer[Y_Modem_TMP2] - 0x30;
                                 } else {
                                     break;
                                 }
                             } else {
                                 break;
                             }
                         }
                          // STM32F103C8 只有64K 大于64K 則取消傳輸
                          if(FileLength > 1024 * 64){
                              Cancel_Transmission(); // 取消傳輸
                           
                              Y_Modem_TMP1 = 0;
                          } else {
                              USART1_Rx_ptr_in = 0;
                           
                              Send_ACK_Continue();
                           
                              Over_Time_Cnt = 0;
                              Y_Modem_TMP1 = 3;
                          }
                          into_app_cnt = 0; // 延遲計(jì)數(shù)清0
                     }                           
                 }
             }
         }
         break;
     case 3:
          // 第3步,接收并寫入程序數(shù)據(jù),以2K的字節(jié)數(shù)據(jù)塊寫入
   if(Flag2_1Ms == true){
          Flag2_1Ms = false;
    if (++Over_Time_Cnt > TIME_OVER_SETUP2){
     Cancel_Transmission(); // 取消傳輸
     Y_Modem_TMP1 = 0;
        into_app_cnt = 0; // 延遲計(jì)數(shù)清0
          }
         }      
         if(USART1_Rx_ptr_in > 0){
              // MODEM_STX 1029字節(jié)數(shù)據(jù)塊
             if(USART1_Rx_Buffer[0] == MODEM_STX){
                  // 最后一包數(shù)據(jù)包大于128且小于1024字節(jié)時(shí),補(bǔ)充以0x1A
                 if(USART1_Rx_ptr_in >= 1029){
                     CRC16 = Y_Modem_CRC((uint8_t *)&USART1_Rx_Buffer[3], 1024);
                     CRC16_Tmp  = USART1_Rx_Buffer[1027];
                     CRC16_Tmp  = CRC16_Tmp << 8;
                     CRC16_Tmp |= USART1_Rx_Buffer[1028];                           
            
                     if(CRC16_Tmp == CRC16){
                          Y_Modem_TMP5 = USART1_RxCount - Write_Counter;
                         for(Y_Modem_TMP2 = 0; Y_Modem_TMP2 < 1024; ++Y_Modem_TMP2) {
                              Y_Modem_TMP4 = USART1_RxCount;
                              Y_Modem_TMP4 = Y_Modem_TMP4 + Y_Modem_TMP2;
                             if(Y_Modem_TMP4 < FileLength){
                                 USART1_Rx_Buffer2[Y_Modem_TMP5++] = USART1_Rx_Buffer[Y_Modem_TMP2+3];
                             }else{
                                  // 最后一個(gè)數(shù)據(jù)包大于128且小于1024字節(jié)時(shí),補(bǔ)充的0x1A不復(fù)制,退出循環(huán)
                                 break;
                             }
                             USART1_Rx_Buffer[Y_Modem_TMP2] = 0;
                         }
       USART1_RxCount += Y_Modem_TMP2;
      #ifdef STM32Fxxx
       Flash_Write_2K(); // USART1_RxCount - Write_Counter < 2048, 調(diào)用該函數(shù)無效
      #endif
       for(; Y_Modem_TMP2 <= 1029; ++Y_Modem_TMP2) {
         USART1_Rx_Buffer[Y_Modem_TMP2] = 0;
       }
       USART1_Rx_ptr_in = 0;
       Send_ACK(); // 回復(fù)確認(rèn)
       into_app_cnt = 0; // 延遲計(jì)數(shù)清0
      }else{
        // 出現(xiàn)CRC錯(cuò)誤
       }
     }
    }
     // MODEM_SOH 133字節(jié)數(shù)據(jù)塊
    if(USART1_Rx_Buffer[0] == MODEM_SOH){
      // 最后一包數(shù)據(jù)不足128字節(jié)時(shí),補(bǔ)充以0x1A,總計(jì)補(bǔ)滿133字節(jié)
     if(USART1_Rx_ptr_in >= 133){
      CRC16 = Y_Modem_CRC((uint8_t *)&USART1_Rx_Buffer[3], 128);
      CRC16_Tmp  = USART1_Rx_Buffer[131];
      CRC16_Tmp  = CRC16_Tmp << 8;
      CRC16_Tmp |= USART1_Rx_Buffer[132];
      if(CRC16_Tmp == CRC16){
       Y_Modem_TMP5 = USART1_RxCount - Write_Counter;
       for(Y_Modem_TMP2 = 0; Y_Modem_TMP2 < 128; ++Y_Modem_TMP2) {
        Y_Modem_TMP4  = USART1_RxCount;
        Y_Modem_TMP4 += Y_Modem_TMP2;
        if(Y_Modem_TMP4 < FileLength){
         USART1_Rx_Buffer2[Y_Modem_TMP5++] = USART1_Rx_Buffer[Y_Modem_TMP2+3];
        }else{
         break;
        }
        USART1_Rx_Buffer[Y_Modem_TMP2] = 0;
       }
       USART1_RxCount += Y_Modem_TMP2;
      #ifdef STM32Fxxx
       Flash_Write_128();
      #endif
       for(; Y_Modem_TMP2 <= 133; ++Y_Modem_TMP2) {
        USART1_Rx_Buffer[Y_Modem_TMP2] = 0;
       }
       USART1_Rx_ptr_in = 0;
       Send_ACK(); // 回復(fù)確認(rèn)
       into_app_cnt = 0; // 延遲計(jì)數(shù)清0
       }
                 }
             }
              // 文件傳輸結(jié)束命令
             if(USART1_Rx_Buffer[0] == MODEM_EOT){
     // 文件傳輸結(jié)束
     if(FileLength == USART1_RxCount){
      Flag_App_Rece_OK = true;
     }
     USART1_Rx_ptr_in = 0;
     Send_ACK_Continue(); // 回復(fù)確認(rèn)、繼續(xù)
     Y_Modem_TMP1 = 4;
     into_app_cnt = 0;    // 延遲計(jì)數(shù)清0
    }
              // 取消傳輸命令
             if(USART1_Rx_Buffer[0] == MODEM_CAN){
                 // 取消傳輸
                 for(Y_Modem_TMP2 = 0; Y_Modem_TMP2 <= 1029; ++Y_Modem_TMP2) {
                     USART1_Rx_Buffer[Y_Modem_TMP2] = 0;
                 }
                 USART1_Rx_ptr_in = 0;
                 Y_Modem_TMP1 = 4;
                 into_app_cnt = 0; // 延遲計(jì)數(shù)清0
             }
         }
         break;
     case 4:
         if(Flag2_1Ms == true){
             Flag2_1Ms = false;
          if (++Over_Time_Cnt > TIME_OVER_SETUP1){
     Cancel_Transmission(); // 取消傳輸
     Y_Modem_TMP1 = 0;
     into_app_cnt = 0; // 延遲計(jì)數(shù)清0
          }
          }
          // MODEM_SOH 133字節(jié)數(shù)據(jù)塊
          if(USART1_Rx_Buffer[0] == MODEM_SOH){
              // 最后一包數(shù)據(jù)不足128字節(jié)時(shí),補(bǔ)充以0x1A,總計(jì)補(bǔ)滿133字節(jié)
              if(USART1_Rx_ptr_in >= 133){
                  // 最后一個(gè)空數(shù)據(jù)包,133字節(jié),前3個(gè)字節(jié)是01 00 FF,其余是0
                  CRC16_Tmp = 0;
                  for(Y_Modem_TMP2 = 3; Y_Modem_TMP2 <= 133; ++Y_Modem_TMP2) {
                      CRC16_Tmp += USART1_Rx_Buffer[Y_Modem_TMP2];
                  }
                  if(CRC16_Tmp==0){
                      if(Flag_App_Rece_OK){
                          // 未寫完的程序數(shù)據(jù)寫入,[1-128) OR [1024,2048)
                          if(FileLength > Write_Counter){
                              Y_Modem_TMP4 = FileLength - Write_Counter;
         if(Y_Modem_TMP4){
         #ifdef STM32Fxxx
          iap_write_appbin(FLASH_APP1_ADDR + Write_Counter, (uint8_t *)USART1_Rx_Buffer2, Y_Modem_TMP4);
         #endif
                                  Write_Counter += Y_Modem_TMP4;
                              }
                          }
                      }
       Send_ACK();  // 回復(fù)確認(rèn),結(jié)束文件傳輸
       Y_Modem_TMP1 = 5;     // 文件傳輸結(jié)束
      }
      into_app_cnt = 0; // 延遲計(jì)數(shù)清0
              }
          }
         break;
     case 5:
   if(Flag2_1Ms == true){
    Flag2_1Ms = false;
   #ifndef STM32Fxxx
    if (++Over_Time_Cnt > 500){
   #else
    if (++Over_Time_Cnt > 5000){
   #endif
     Over_Time_Cnt = 0;
     Y_Modem_TMP1 = 0;
     into_app_cnt = 0; // 延遲5秒
    }
   }
   break;
  default:
  #ifdef STM32Fxxx
   __NOP();
   __NOP();
   __NOP();
  #endif
   break;
}   
}
/*
一、Ymodem通信發(fā)送數(shù)據(jù)包的說明
  1 Ymodem通信數(shù)據(jù)包的格式
    數(shù)據(jù)包的格式是: 類型 + 序號(hào) + 序號(hào)反碼 + 數(shù)據(jù)區(qū)(128或1024) + 校驗(yàn)和(兩字節(jié))
  2 Ymodem通信數(shù)據(jù)包的序號(hào)增長(zhǎng)規(guī)律
    數(shù)據(jù)包的序號(hào)從00開始直到255,然后又從00開始。不大于255K字節(jié)的數(shù)據(jù)包,所有發(fā)送數(shù)據(jù)包的
    序號(hào)是唯一的。大于255K的數(shù)據(jù)包,按照1K字節(jié)分包,第一個(gè)數(shù)據(jù)包序號(hào)是1,第二個(gè)數(shù)據(jù)包的序號(hào)是2
    。。。第255個(gè)數(shù)據(jù)包的序號(hào)是255,第256個(gè)數(shù)據(jù)包的序號(hào),又從0開始。
  3 Ymodem通信的大小數(shù)據(jù)包
    Ymodem通信有128字節(jié)和1024字節(jié)兩種類型的數(shù)據(jù)包,數(shù)據(jù)包開頭有3字節(jié)(類型+ 序號(hào)+序號(hào)反碼),
    末尾crc16是2個(gè)字節(jié),所以可以說有133字節(jié)的小數(shù)據(jù)包和1029字節(jié)的大數(shù)據(jù)包。
    (1)133字節(jié)數(shù)據(jù)包的特點(diǎn)、字符填充規(guī)則
      以SOH(0x01)開始的數(shù)據(jù)包,數(shù)據(jù)區(qū)是128字節(jié)。發(fā)送端第一個(gè)含有文件信息的數(shù)據(jù)包是3+128+2 = 133字節(jié)。
      發(fā)送最后一個(gè)數(shù)據(jù)包時(shí),剩余數(shù)據(jù)字節(jié)數(shù)若小于128,則以0x1A填充,仍發(fā)送133字節(jié)數(shù)據(jù)包。
    (2)1029字節(jié)數(shù)據(jù)包的特點(diǎn)、字符填充規(guī)則
      以STX(0x02)開始的數(shù)據(jù)包,數(shù)據(jù)區(qū)是1024字節(jié)。若發(fā)送的文件大于1024字節(jié),文件信息包之后的第一個(gè)
      數(shù)據(jù)包則為1029字節(jié),隨后剩余的數(shù)據(jù)若不小于1024字節(jié),則均以1029大數(shù)據(jù)包發(fā)送。
  4 處理Ymodem通信最后一個(gè)數(shù)據(jù)包時(shí),需要考慮的情況
    Ymodem通信按照1024字節(jié)分包,最后一個(gè)數(shù)據(jù)包的大小不會(huì)超過1024字節(jié)。編程時(shí)需要考慮以下幾種情況:
    (1)數(shù)據(jù)個(gè)數(shù)等于1024字節(jié),按1029字節(jié)發(fā)送。
    (2)數(shù)據(jù)個(gè)數(shù)小于1024字節(jié),但大于128字節(jié),按1029字節(jié)發(fā)送,無效數(shù)據(jù)區(qū)域以0x1A字符填充。
    (3)數(shù)據(jù)個(gè)數(shù)等于128字節(jié),按133字節(jié)發(fā)送。
    (4)數(shù)據(jù)個(gè)數(shù)小于128字節(jié),按133字節(jié)發(fā)送,無效數(shù)據(jù)區(qū)域以0x1A字符填充。
二、Ymodem通信crc16計(jì)算說明:
  1 小包3 + 128 字節(jié),大包 3 + 1024字節(jié),末尾2字節(jié)是crc16。
  2 crc16計(jì)算從第4字節(jié)開始(不包括SOH(0x01) 序號(hào) 序號(hào)反碼三字節(jié)),
     小包計(jì)算長(zhǎng)度128字節(jié),大包計(jì)算長(zhǎng)度1024字節(jié)
  3 最后一個(gè)空包,除前三字節(jié)外全是0,末尾2個(gè)字節(jié)也是0,不用計(jì)算crc16。
三、Ymodem通信命令說明
  #define MODEM_SOH 0x01 //133字節(jié)數(shù)據(jù)包類型,接收正常回應(yīng)0x06(含文件信息的第一個(gè)包接收正常需回應(yīng)0x06、0x43)
  #define MODEM_STX 0x02 //1029字節(jié)數(shù)據(jù)包類型,接收正常回應(yīng)0x06
  #define MODEM_EOT 0x04 //發(fā)送文件傳輸結(jié)束命令,接收正常回應(yīng)0x06、0x43(啟動(dòng)空包發(fā)送)
  #define MODEM_ACK 0x06 //發(fā)送確認(rèn)應(yīng)答,接收方crc校驗(yàn)成功或收到已定義的命令
  #define MODEM_NAK 0x15 //發(fā)送重傳當(dāng)前數(shù)據(jù)包請(qǐng)求,接收方crc校驗(yàn)出錯(cuò)
  #define MODEM_CAN 0x18 //發(fā)送取消傳輸命令,連續(xù)發(fā)送5個(gè)字符
  #define MODEM_C   0x43 //發(fā)送大寫字母C(三種情況下發(fā)送該字符: 1.啟動(dòng)通信握手.2.啟動(dòng)數(shù)據(jù)包發(fā)送.3.啟動(dòng)空包發(fā)送)

*/
uint16_t Y_Modem_CRC(uint8_t * buf, uint16_t len)
{
    uint16_t chsum;
    uint16_t stat;
    uint16_t i;
    uint8_t * in_ptr;
   
    //指向要計(jì)算CRC的緩沖區(qū)開頭
    in_ptr = buf;
    chsum = 0;
    for (stat = len ; stat > 0; stat--) //len是所要計(jì)算的長(zhǎng)度
    {
        chsum = chsum^(uint16_t)(*in_ptr++) << 8;
        for (i=8; i!=0; i--) {
            if (chsum & 0x8000){
                chsum = chsum << 1 ^ 0x1021;
            } else {
                chsum = chsum << 1;
            }
        }
    }
    return chsum;
}



分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:75926 發(fā)表于 2015-4-4 01:43 | 只看該作者
        Ymodem通信協(xié)議的補(bǔ)充說明
一、Ymodem通信發(fā)送數(shù)據(jù)包的說明

  1 Ymodem通信數(shù)據(jù)包的格式

    數(shù)據(jù)包的格式是: 類型 + 序號(hào) + 序號(hào)反碼 + 數(shù)據(jù)區(qū)(128或1024) + 校驗(yàn)和(兩字節(jié))

  2 Ymodem通信數(shù)據(jù)包的序號(hào)增長(zhǎng)規(guī)律

    數(shù)據(jù)包的序號(hào)從00開始直到255,然后又從00開始。不大于255K字節(jié)的數(shù)據(jù)包,所有發(fā)送數(shù)據(jù)包的
    序號(hào)是唯一的。大于255K的數(shù)據(jù)包,按照1K字節(jié)分包,第一個(gè)數(shù)據(jù)包序號(hào)是1,第二個(gè)數(shù)據(jù)包的序號(hào)是2
    。。。第255個(gè)數(shù)據(jù)包的序號(hào)是255,第256個(gè)數(shù)據(jù)包的序號(hào),又從0開始。

  3 Ymodem通信的大小數(shù)據(jù)包
    Ymodem通信有128字節(jié)和1024字節(jié)兩種類型的數(shù)據(jù)包,數(shù)據(jù)包開頭有3字節(jié)(類型+ 序號(hào)+序號(hào)反碼),
    末尾crc16是2個(gè)字節(jié),所以可以說有133字節(jié)的小數(shù)據(jù)包和1029字節(jié)的大數(shù)據(jù)包。

    (1)133字節(jié)數(shù)據(jù)包的特點(diǎn)、字符填充規(guī)則
      以SOH(0x01)開始的數(shù)據(jù)包,數(shù)據(jù)區(qū)是128字節(jié)。發(fā)送端第一個(gè)含有文件信息的數(shù)據(jù)包是3+128+2 = 133字節(jié)。
      發(fā)送最后一個(gè)數(shù)據(jù)包時(shí),剩余數(shù)據(jù)字節(jié)數(shù)若小于128,則以0x1A填充,仍發(fā)送133字節(jié)數(shù)據(jù)包。

    (2)1029字節(jié)數(shù)據(jù)包的特點(diǎn)、字符填充規(guī)則
      以STX(0x02)開始的數(shù)據(jù)包,數(shù)據(jù)區(qū)是1024字節(jié)。若發(fā)送的文件大于1024字節(jié),文件信息包之后的第一個(gè)
      數(shù)據(jù)包則為1029字節(jié),隨后剩余的數(shù)據(jù)若不小于1024字節(jié),則均以1029大數(shù)據(jù)包發(fā)送。

  4 處理Ymodem通信最后一個(gè)數(shù)據(jù)包時(shí),需要考慮的情況
    Ymodem通信按照1024字節(jié)分包,最后一個(gè)數(shù)據(jù)包的大小不會(huì)超過1024字節(jié)。編程時(shí)需要考慮以下幾種情況:
    (1)數(shù)據(jù)個(gè)數(shù)等于1024字節(jié),按1029字節(jié)發(fā)送。
    (2)數(shù)據(jù)個(gè)數(shù)小于1024字節(jié),但大于128字節(jié),按1029字節(jié)發(fā)送,無效數(shù)據(jù)區(qū)域以0x1A字符填充。
    (3)數(shù)據(jù)個(gè)數(shù)等于128字節(jié),按133字節(jié)發(fā)送。
    (4)數(shù)據(jù)個(gè)數(shù)小于128字節(jié),按133字節(jié)發(fā)送,無效數(shù)據(jù)區(qū)域以0x1A字符填充。

二、Ymodem通信crc16計(jì)算說明:
  1 小包3 + 128 字節(jié),大包 3 + 1024字節(jié),末尾2字節(jié)是crc16。
  2 crc16計(jì)算從第4字節(jié)開始(不包括SOH(0x01) 序號(hào) 序號(hào)反碼三字節(jié)),
     小包計(jì)算長(zhǎng)度128字節(jié),大包計(jì)算長(zhǎng)度1024字節(jié)
  3 最后一個(gè)空包,除前三字節(jié)外全是0,末尾2個(gè)字節(jié)也是0,不用計(jì)算crc16。

三、Ymodem通信命令說明

  #define MODEM_SOH 0x01 //133字節(jié)數(shù)據(jù)包類型,接收正常回應(yīng)0x06(含文件信息的第一個(gè)包接收正常需回應(yīng)0x06、0x43)
  #define MODEM_STX 0x02 //1029字節(jié)數(shù)據(jù)包類型,接收正常回應(yīng)0x06
  #define MODEM_EOT 0x04 //發(fā)送文件傳輸結(jié)束命令,接收正常回應(yīng)0x06、0x43(啟動(dòng)空包發(fā)送)
  #define MODEM_ACK 0x06 //發(fā)送確認(rèn)應(yīng)答,接收方crc校驗(yàn)成功或收到已定義的命令
  #define MODEM_NAK 0x15 //發(fā)送重傳當(dāng)前數(shù)據(jù)包請(qǐng)求,接收方crc校驗(yàn)出錯(cuò)
  #define MODEM_CAN 0x18 //發(fā)送取消傳輸命令,連續(xù)發(fā)送5個(gè)字符
  #define MODEM_C   0x43 //發(fā)送大寫字母C(三種情況下發(fā)送該字符: 1.啟動(dòng)通信握手.2.啟動(dòng)數(shù)據(jù)包發(fā)送.3.啟動(dòng)空包發(fā)送)
回復(fù)

使用道具 舉報(bào)

板凳
ID:87577 發(fā)表于 2018-10-25 14:31 | 只看該作者
感謝分享,,,
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 久久se精品一区精品二区 | 亚洲欧美日韩中文字幕一区二区三区 | 成人午夜免费福利视频 | 欧美日韩高清免费 | 久久草视频| 毛片视频免费 | 久久国产一区二区 | 亚洲视频 欧美视频 | 久久精品国产一区二区电影 | 国产精品毛片久久久久久久 | 久久精彩视频 | 欧美性极品xxxx做受 | 91色啪| 国产九九精品视频 | 欧美a级成人淫片免费看 | 国产乱码精品一区二三赶尸艳谈 | 一区二区三区视频在线 | 欧美亚洲第一区 | 国产精品欧美一区二区三区不卡 | jav成人av免费播放 | 亚洲精品乱码久久久久久黑人 | 午夜影院 | 免费观看黄色一级片 | 国产一区二区三区四区在线观看 | 看特级黄色片 | 亚洲一级在线 | 自拍偷拍亚洲视频 | 亚洲精品在线观 | 黑人巨大精品欧美一区二区免费 | 91国内产香蕉 | 狠狠干综合视频 | 拍戏被cao翻了h承欢 | 精品国产欧美一区二区 | 久久久免费 | 美女露尿口视频 | 日韩精品一区二区三区视频播放 | 99国产精品99久久久久久 | 国产农村妇女毛片精品久久麻豆 | 巨大荫蒂视频欧美另类大 | 亚洲精品久久久久久国产精华液 | 国产三级大片 |