//*********************************************************************************** // Ver 1.0 // 2020.03.05 1、新建文件。 //*********************************************************************************** #include "config.h" YMODEM_Str YMODEM_Info; void YMODEM_SendChar(INT8U Value) { //YMODEM_Set2Tx(); YMODEM_Send(Value); //DELAY_Ms(10); //YMODEM_Set2Rx(); if (Value == YMODEM_CMD_ACK) { YMODEM_ErrCnt = 0; //错误计数器清零 } else if (Value == YMODEM_CMD_NACK) { YMODEM_ErrCnt++; //错误计数器累加 if (YMODEM_ErrCnt > YMODEM_ERROR_MAX) //超过最大错误次数 { YMODEM_Status = YMODEM_STA_END; } } YMODEM_IdleRest(10); } INT8U YMODEM_CrcCheck(INT8U *ptr, INT32U Len) { INT16U tCRC16, tCRC16_2; tCRC16 = (((INT16U)ptr[Len - 2]) | ((INT16U)ptr[Len - 1])); //读取数据包中的CRC字节 tCRC16_2 = CRC16((ptr + YMODEM_PACKHEAD), (Len - YMODEM_PACKHEAD - 2)); return (tCRC16 == tCRC16_2); } //接收到到的数据包解析 INT8U YMODEM_ReceivePacket(INT8U *ptr_R, INT16U rLen, INT8U *ptr, INT16U *pLen, INT8U cNum) { INT16U tLen = YMODEM_PACKET_128B, tCrc; switch (ptr_R[0]) { case YMODEM_CMD_SOH: tLen = YMODEM_PACKET_128B; break; case YMODEM_CMD_STX: tLen = YMODEM_PACKET_1KB; break; case YMODEM_CMD_EOT: return (YMODEM_CMD_EOT); case YMODEM_CMD_ETX: return (YMODEM_CMD_ETX); case YMODEM_CMD_CA: if (ptr_R[1] == YMODEM_CMD_CA) { return (0); } else { return (0x86); } default: return (0x81); } //if((ptr_R[1] == 0x00) && (YMODEM_FileSta == 0)) if ((ptr_R[1] == 0x00) && (YMODEM_PacketNum == 0)) { return (YMODEM_ERR_NOERR); } if (ptr_R[1] != cNum) { return (0x82); } ptr_R[2] = ~ptr_R[2]; if (ptr_R[2] != cNum) { return (0x83); } if (rLen != (tLen + YMODEM_PACKHEAD + YMODEM_TRAILER)) { return (0x84); } tCrc = CRC16((ptr_R + YMODEM_PACKHEAD), tLen); if (((ptr_R[rLen - 2] << 8) | ptr_R[rLen - 1]) != tCrc) { return (0x85); } //IAP写入到FLASH MEM_Copy(&ptr_R[YMODEM_PACKHEAD], ptr, tLen); *pLen = tLen; return (1); } INT8U YMODEM_ReadFileInfo(INT8U *ptr) { INT8U i; for (i = 0; i < 64; i++) { if (*ptr != 0) { YMODEM_Info.FILE_Name[i] = *ptr++; //读取文件名 } else { ptr++; break; } } YMODEM_Info.FILE_Size = 0; for (i = 0; i < 16; i++) { if ((*ptr != 0x20) && (*ptr >= '0') && (*ptr <= '9')) { YMODEM_Info.FILE_Size *= 10; YMODEM_Info.FILE_Size += *ptr - '0'; } else { break; } ptr++; } return (1); } //YMODEM接收数据处理函数 //*ptr:数据保存缓冲区指针 //*pLen:数据长度指针 INT8U YMODEM_Receive(INT8U *ptr_R, INT16U *ptr_rLen, INT8U *ptr, INT16U *pLen) { YMODEM_FileSta = YMODEM_FILE_VOIDER; //文件接收状态 switch (YMODEM_Status) { case YMODEM_STA_INIT: YMODEM_PacketNum = 0; //接收数据包计数初始化 YMODEM_ErrCnt = 0; //错误计数初始化 YMODEM_AckCnt = 0; //ACK计数初始化 YMODEM_Status = YMODEM_STA_REC_HEAD; //YMODEM工作状态 TASK_TimerStart(TMR_YMODEM, 2000); //YMODEM超时时间设置为1秒 break; case YMODEM_STA_REC_HEAD: if (TASK_TimerState(TMR_YMODEM) == TASK_STA_IDLE) //等待超时 { YMODEM_SendChar(YMODEM_CMD_C); //YMODEM_Status=YMODEM_STA_INIT; break; } if (*ptr_rLen == 0) { break; } YMODEM_ErrCode = YMODEM_ReceivePacket(ptr_R, *ptr_rLen, ptr, pLen, (YMODEM_PacketNum & 0xff)); *ptr_rLen = 0; switch (YMODEM_ErrCode) { case YMODEM_ERR_NOERR: //接收正确 if (ptr_R[YMODEM_PACKHEAD] == 0) //无文件发送 { YMODEM_Status = YMODEM_STA_END; } else //有文件发送 { YMODEM_Status = YMODEM_STA_REC_START; YMODEM_FileSta = YMODEM_FILE_INFO; //返回接收头文件 YMODEM_PacketNum++; YMODEM_AckCnt = 0; YMODEM_ReadFileInfo(&ptr_R[3]); } break; case YMODEM_ERR_END: //接收到结束标志 if (YMODEM_AckCnt > 0) { YMODEM_PacketNum = 0; YMODEM_SendChar(YMODEM_CMD_ACK); //正确应答 } else { YMODEM_SendChar(YMODEM_CMD_NACK); //错误应答 二次确认 } YMODEM_AckCnt++; break; default: //接收数据有误 YMODEM_AckCnt = 0; YMODEM_SendChar(YMODEM_CMD_NACK); //错误应答 break; } TASK_TimerStart(TMR_YMODEM, 2000); break; case YMODEM_STA_REC_START: YMODEM_Status = YMODEM_STA_REC_DATA; YMODEM_SendChar(YMODEM_CMD_ACK); YMODEM_SendChar(YMODEM_CMD_C); break; case YMODEM_STA_REC_DATA: if (TASK_TimerState(TMR_YMODEM) == TASK_STA_IDLE) { YMODEM_Status = YMODEM_STA_END; break; } if (*ptr_rLen == 0) { break; } YMODEM_ErrCode = YMODEM_ReceivePacket(ptr_R, *ptr_rLen, ptr, pLen, (YMODEM_PacketNum & 0xff)); *ptr_rLen = 0; switch (YMODEM_ErrCode) { case YMODEM_ERR_NOERR: //接收正确 YMODEM_FileSta = YMODEM_FILE_DATA; //返回接收数据正确 YMODEM_PacketNum++; YMODEM_AckCnt = 0; YMODEM_SendChar(YMODEM_CMD_ACK); break; case YMODEM_ERR_END: case YMODEM_CMD_EOT: //接收到结束标志 if (YMODEM_AckCnt > 0) { YMODEM_PacketNum = 0; YMODEM_Status = YMODEM_STA_END; YMODEM_SendChar(YMODEM_CMD_ACK); //正确应答 } else { YMODEM_SendChar(YMODEM_CMD_NACK); //错误应答 } YMODEM_AckCnt++; break; default: //接收数据有误 YMODEM_AckCnt = 0; YMODEM_SendChar(YMODEM_CMD_NACK); //错误应答 break; } TASK_TimerStart(TMR_YMODEM, 2000); break; case YMODEM_STA_END: YMODEM_SendChar(YMODEM_CMD_ACK); YMODEM_FileSta = YMODEM_FILE_EXIT; break; } return (YMODEM_FileSta); }