void comn_DataReceived(object sender, SerialDataReceivedEventArgs e) { if (!start) { return; } try { if (!transmittingYmodem) { string msg = string.Empty; if (transmitState == YmodeSendState.WAIT_START) { char c = (char)comn.ReadChar(); msg += c; //接收到'C'--CRC16 if (c == 'C') { //rMainform.ShowMCUMsg("\n\r Waiting for the file to be sent ...\n\r"); transmittingYmodem = true; YmodeStateChanged?.Invoke(12, "进入Ymode模式"); recData.Clear(); } else { msg += comn.ReadExisting(); //读取串口缓冲区数据 comn.Write(new[] { (byte)0x31 }, 0, 1); } } else //文件发送完毕后的信息 { msg += comn.ReadExisting(); //读取串口缓冲区数据 } YmodeResponseGot?.Invoke(msg); } else { byte[] temp = new byte[128]; int count = comn.Read(temp, 0, temp.Length); if (count > 0) { recData.EnqueueRange(temp, 0, count); } } } catch (Exception Err) { YmodeStateChanged?.Invoke(11, "串口通信错误"); } }
private byte ReadNextByte() { if (recData.Count > 0) { byte c = recData.Dequeue(); System.Diagnostics.Debug.WriteLine(c); YmodeResponseGot?.Invoke((char)c + " "); return(c); } else { return(0xFF); // error } }
/** * @brief Transmit a file using the ymodem protocol * @param * @retval */ private byte Ymodem_Transmit() { byte i; bool CRC16_F = true; byte c; ackReceived = false; //默认 c = ReadNextByte(); //先判断是否结束传输或改变状态 switch (transmitState) { case YmodeSendState.WAIT_START: if (c == CRC16) { ackReceived = true; YmodeResponseGot?.Invoke("\n\r The file is being sent ...\n\r"); YmodeStateChanged?.Invoke(13, "发送文件信息"); lastState = transmitState; transmitState = YmodeSendState.SEND_FILENAME; //开始发送文件名及其大小 } break; case YmodeSendState.SEND_FILENAME: if (c == ACK) { YmodeStateChanged?.Invoke(13, "文件信息确认"); lastState = transmitState; } else { if (c == CRC16) { if (lastState == YmodeSendState.SEND_FILENAME && lastRec == ACK) { ackReceived = true; YmodeStateChanged?.Invoke(13, "开始发送文件"); transmitState = YmodeSendState.SEND_DATA; //开始发送文件内容 } else { errors++; if (errors > 10) { ackReceived = true; } } } } break; case YmodeSendState.SEND_DATA: if (c == ACK) { ackReceived = true; YmodeProgressUpdated?.Invoke(fileIndex); if (fsFWSent) { transmitState = YmodeSendState.SEND_EOT; //当前文件内容发送完毕 } } break; case YmodeSendState.SEND_EOT: if (c == ACK) { lastState = transmitState; transmitState = YmodeSendState.SEND_LASTPACK; } break; case YmodeSendState.SEND_LASTPACK: if (c == CRC16 && lastState == YmodeSendState.SEND_EOT && lastRec == ACK) { ackReceived = true; } else if (c == ACK) { start = false; transmittingYmodem = false; //结束Ymodem发送 //通知“固件升级”子窗口固件升级成功 //rMainform.ReportFwUpdateResult("Succeed"); YmodeProgressFinished?.Invoke("Succeed"); YmodeStateChanged?.Invoke(14, "文件发送成功"); return(1); //直接返回,然后可以发送APP代码的CRC16值 } break; case YmodeSendState.SEND_CA: if (c == ACK) { ackReceived = true; transmittingYmodem = false; //结束Ymodem发送 return(0); } break; default: break; } lastRec = c; if (c == CA) { if (ReadNextByte() == CA) //连续两次读到CA { transmittingYmodem = false; YmodeStateChanged?.Invoke(11, "发送失败,请重试..."); return(0xFF); /* error */ } } //根据新状态来判断是否要准备新数据包 switch (transmitState) { case YmodeSendState.SEND_FILENAME: if (ackReceived) //下位机等待数据包下位机接收成功 { errors = 0; //清零出错计数 // Here 128 bytes package is used pktSize = PACKET_SIZE; // Prepare first block,对应数据包序号为0 Ymodem_PrepareIntialPacket(ref packet_data, fileName, (uint)fileBytes.Length); fsFWSent = false; resSize = (uint)fileBytes.Length; fileIndex = 0; blkNumber = 1; //接下来发送第1个数据包 } else { errors++; } break; case YmodeSendState.SEND_DATA: if (ackReceived) //上次数据包下位机接收成功 { errors = 0; //清零出错计数 // Prepare next packet Ymodem_PreparePacket(ref packet_data, blkNumber, resSize); /* * //修改第一个数据包,加入CRC值和文件长度 * if (blkNumber == 1) * { * UInt16 crc = CalcFileCRC16(ref fiFW); * } */ if (resSize >= PACKET_1K_SIZE) //剩余字节数大于等于1024 { // Here 1024 bytes package is used to send the packets pktSize = PACKET_1K_SIZE; } else if (resSize > PACKET_SIZE) //剩余字节数大于128且小于1024 { pktSize = PACKET_1K_SIZE; } else //剩余字节数小于等于128,且大于0 { pktSize = PACKET_SIZE; } if (resSize > PACKET_1K_SIZE) //判断是否还有数据包需要发送 { resSize -= PACKET_1K_SIZE; if (blkNumber > (fileBytes.Length / 1024)) //发送的数据包数量不能超出数据包总数量 { transmittingYmodem = false; return(0xFF); // error } else { blkNumber++; } } else { blkNumber++; resSize = 0; fsFWSent = true; //文件数据发送完毕,准备进入下一状态 } } else { errors++; } break; case YmodeSendState.SEND_LASTPACK: //发送序号为0的空数据包,结束文件传输 if (ackReceived) //上次数据包发送成功 { errors = 0; // Last packet preparation packet_data[0] = SOH; packet_data[1] = 0; packet_data[2] = 0xFF; for (i = PACKET_HEADER; i < (PACKET_SIZE + PACKET_HEADER); i++) { packet_data[i] = 0x00; } pktSize = PACKET_SIZE; } break; case YmodeSendState.SEND_EOT: case YmodeSendState.SEND_CA: if (ackReceived) //上次数据包发送成功 { errors = 0; } else { errors++; } break; default: break; } if (errors >= 0xFF) { transmittingYmodem = false; //通知“固件升级”子窗口固件升级失败 //rMainform.ReportFwUpdateResult("Fail"); YmodeProgressFinished?.Invoke("Fail"); YmodeStateChanged?.Invoke(11, "发送失败..."); return(errors); } else //发送上次的数据包或新数据包 { if ((transmitState == YmodeSendState.SEND_FILENAME) || (transmitState == YmodeSendState.SEND_DATA) || (transmitState == YmodeSendState.SEND_LASTPACK)) { bool send = false; if (transmitState == YmodeSendState.SEND_FILENAME && ackReceived) { send = true; System.Diagnostics.Debug.WriteLine("发送文件名大小"); } else if (transmitState == YmodeSendState.SEND_DATA && ackReceived) { send = true; System.Diagnostics.Debug.WriteLine("发送文件内容:" + (blkNumber - 1)); } else if (transmitState == YmodeSendState.SEND_LASTPACK && ackReceived) { send = true; System.Diagnostics.Debug.WriteLine("发送最后空数据"); } if (send) //新数据包待发送,重新计算校验值 { // Send CRC or CheckSum based on CRC16_F if (CRC16_F) { packCRC = Cal_CRC16(ref packet_data, 3, pktSize); //前3个数据不包含在CRC计算范围内 } else { packCheckSum = CalChecksum(ref packet_data, 3, pktSize); //前3个数据不包含在CRC计算范围内 } //send packet try { System.Diagnostics.Debug.WriteLine("CRC16:" + packCRC); int len = pktSize + PACKET_HEADER; // Send CRC or CheckSum based on CRC16_F if (CRC16_F) { packet_data[len] = (byte)(packCRC >> 8); packet_data[len + 1] = (byte)(packCRC & 0xFF); len += 2; } else { packet_data[len] = packCheckSum; len += 1; } comn.Write(packet_data, 0, len); ackReceived = false; //在接收事件处理函数中判断是否发送成功 } catch (Exception e) { transmittingYmodem = false; DataSendFailed?.Invoke(); YmodeStateChanged?.Invoke(11, "串口通信错误"); return(0xFF); /* error */ } } } else if (transmitState == YmodeSendState.SEND_EOT) //send EOT { try { if (ackReceived) { comn.Write(new[] { EOT }, 0, 1); ackReceived = false; //在接收事件处理函数中判断是否发送成功 System.Diagnostics.Debug.WriteLine("发送EOT"); } } catch (Exception e) { transmittingYmodem = false; YmodeStateChanged?.Invoke(11, "串口通信错误"); return(0xFF); // error } } } return(0); /* packet trasmitted successfully */ }