需求:前一段时间朋友想要上位机向板卡传输升级文件,做到自动升级板卡程序,上位机使用c#编写,下位机使用c语言编写,可执行程序采用Xmodem协议传输,在网上浏览了很久没有找到好的c#版本的Xmodem协议的demo,大家可以参考这个例子;
协议:在网上有很多Xmodem协议相关的东西,不多说......
文件流方式打开传输:
XModem xModem = new XModem();
xModem.init_xmodem(SP);//SerialPort
using (FileStream fs = File.Open(filePath, FileMode.Open))//文件路径
{
using (BinaryReader b_reader = new BinaryReader(fs))
{
xModem.xmodem_send(b_reader);
}
}
XModem帮助类发送:
public void xmodem_send(BinaryReader B_reader)//开始发送,有两种包长度,128和1024两种方式
{
int err = 0;
Sender_Packet_Number = 1;
this.wait_c();
Sender_Data = B_reader.ReadBytes(1024);
err = Send_Packet(Sender_Data, Sender_Packet_Number, 1024);//第一包数据
while(true)
{
if(err == 1)
{
Sender_Data = B_reader.ReadBytes(1024);
if(Sender_Data.Length == 0)//结束跳出循环
{
break;
}
else if(Sender_Data.Length != 1024)
{
byte[] full_stream = new byte[1024];
byte[] zero_ary = new byte[1024 - Sender_Data.Length];
Array.Clear(zero_ary, 0, zero_ary.Length);
Console.WriteLine(Sender_Data.Length);
Array.Copy(Sender_Data, 0, full_stream, 0, Sender_Data.Length);
Array.Copy(zero_ary, 0, full_stream, Sender_Data.Length, zero_ary.Length);
Sender_Data = full_stream;
}
Sender_Packet_Number++;
err = Send_Packet(Sender_Data, Sender_Packet_Number, 1024);
}
else
{
err = Send_Packet(Sender_Data, Sender_Packet_Number, err);
}
}
}
private int Send_Packet(byte[] data, byte SPN, int Length)//每一包数据
{
if(Length == 128)
{
Sender_Packet[0] = Constants.SOH;//包首字节
}
else if(Length == 1024)
{
Sender_Packet[0] = Constants.SOX;
}
Sender_Packet[1] = SPN;//包第二字节
//Sender_Packet[2] = BitConverter.GetBytes(255 - SPN)[0];
Sender_Packet[2] = (byte)(~SPN);//包第三字节
Console.WriteLine(BitConverter.ToString(Sender_Packet));
SPort.Write(Sender_Packet, 0, 3);//发送前三字节
Console.WriteLine(BitConverter.ToString(data));
SPort.Write(data, 0, Length);//发送有效载荷
//Sender_Crc = crc16.ComputeCrc(data);
//Sender_Crc = Crc_o.calcrc(data);
Sender_Crc_us = crc16.CRC16_ccitt(data, 0, Length);//crc_16两字节校验
Sender_Crc[0] = (byte)((Sender_Crc_us >> 8) & 0xFF);
Sender_Crc[1] = (byte)(Sender_Crc_us & 0xFF);
Console.WriteLine(BitConverter.ToString(Sender_Crc));//发送两字节校验
SPort.Write(Sender_Crc, 0, 2);
return Wait_ACK_NAK(Length);
}
private int Wait_ACK_NAK(int Length)
{
int SPort_read;
while(true)
{
Console.WriteLine("Wait_ACK_NAK");
SPort_read = SPort.ReadChar();//Console.Read();
if(SPort_read == Constants.NAK) //重复发送
{
Console.WriteLine("NAK");
return Length;
}
else if(SPort_read == Constants.ACK) //继续发送
{
Console.WriteLine("ACK");
return 1;
}
else
{
Console.WriteLine(SPort_read);
}
}
}
帮助类下载链接:地址 方便大家下载,学习......