C#上位机通过CAN总线发送bin文件
让gpt生成一段代码用来把bin文件通过can总线发出去
c#代码还是比较强大的,各种功能基本都是一两行代码就实现了,这里记录一下对这个代码的理解和解读
主要代码如下,传入bin文件的地址即可将其从指定的can通道发送出去:
public void SendBINFile(string binFilePath)
{
if (!File.Exists(binFilePath))
{
Console.WriteLine("BIN file not found: " + binFilePath);
return;
}
try
{
// 读取 BIN 文件
byte[] binData = File.ReadAllBytes(binFilePath);
int chunkSize = 8; // 每帧发送 8 字节
int totalFrames = (binData.Length + chunkSize - 1) / chunkSize;
Console.WriteLine($"Sending BIN file: {binFilePath}");
Console.WriteLine($"Total data size: {binData.Length} bytes, Frames: {totalFrames}");
for (int i = 0; i < totalFrames; i++)
{
// 准备 CAN 消息
byte[] frameData = new byte[chunkSize];
int currentFrameSize = Math.Min(chunkSize, binData.Length - i * chunkSize);
Array.Copy(binData, i * chunkSize, frameData, 0, currentFrameSize);
TPCANMsg canMessage = new TPCANMsg
{
ID = 0x123, // 自定义消息 ID
LEN = (byte)currentFrameSize,
MSGTYPE = TPCANMessageType.PCAN_MESSAGE_STANDARD,
DATA = frameData
};
// 发送 CAN 消息
LastStatus = PCANBasic.Write(Pcan_Handle, ref canMessage);
Thread.Sleep(1);
if (LastStatus != TPCANStatus.PCAN_ERROR_OK)
{
Console.WriteLine($"Error sending frame {i + 1}: {GetErrorText(LastStatus)}");
}
else
{
Console.WriteLine($"Frame {i + 1} sent: {BitConverter.ToString(frameData, 0, currentFrameSize)}");
}
}
}
catch (Exception ex)
{
Console.WriteLine("Error sending BIN file: " + ex.Message);
}
}
其他都比较简单易懂,其中最核心的就是for循环的这部分:
for (int i = 0; i < totalFrames; i++)
{
// 准备 CAN 消息
byte[] frameData = new byte[chunkSize];
int currentFrameSize = Math.Min(chunkSize, binData.Length - i * chunkSize);
Array.Copy(binData, i * chunkSize, frameData, 0, currentFrameSize);
TPCANMsg canMessage = new TPCANMsg
{
ID = 0x123, // 自定义消息 ID
LEN = (byte)currentFrameSize,
MSGTYPE = TPCANMessageType.PCAN_MESSAGE_STANDARD,
DATA = frameData
};
// 发送 CAN 消息
LastStatus = PCANBasic.Write(Pcan_Handle, ref canMessage);
Thread.Sleep(1);
其中framedata用来储存当前要发送的数据,最大8字节,每一个for循环都要进行一次发送。currentFrameSize是当前这轮发送时framedata的尺寸,除了最后一帧外全都是8。
Array.Copy(binData, i * chunkSize, frameData, 0, currentFrameSize)是将“bindata”这个bin文件的指定位置(i * chunkSize)指定大小(currentFrameSize)的数据复制到framedata中用于发送。
其次,Thread.Sleep(1)也是很重要的,250k波特率下每秒can总线发送报文的极限是2000条左右,为了均衡效率和稳定性,我们设置每次发送后延时1ms再继续发送,以避免总线过载或者可能发生的错误。