现场优化4

This commit is contained in:
2026-08-15 18:43:38 +08:00
parent 8d941d92f0
commit 92eab2f626
5 changed files with 249 additions and 31 deletions
+72 -4
View File
@@ -688,6 +688,7 @@ namespace ZLGUSBCANFD
/// <summary>
/// 发送自定义报文(原始字节,帧 ID 支持 string 兼容模式)。
/// 循环发送间隔毫秒 = 0 时只发送一次;>0 时按指定间隔循环发送,可调用 停止循环发送 停止。
/// </summary>
/// <param name="通道号">CAN/CANFD 通道索引</param>
/// <param name="帧IDStr">帧 ID(可以是 "26"、"0x1A"、"1A");扩展帧会自动置位 0x80000000</param>
@@ -696,6 +697,7 @@ namespace ZLGUSBCANFD
/// <param name="是否是扩展帧">是否为 29 位扩展帧</param>
/// <param name="是否是CANFD">true = CANFD;false = 经典 CAN</param>
/// <param name="开启波特率加速BRS">CANFD 是否开启波特率加速</param>
/// <param name="循环发送间隔毫秒">0 = 单次发送;>0 = 周期循环发送(毫秒)</param>
public virtual bool 发送自定义报文(
uint 通道号,
string 帧IDStr,
@@ -703,7 +705,8 @@ namespace ZLGUSBCANFD
byte dlcLength,
bool 是否是扩展帧 = false,
bool 是否是CANFD = true,
bool 开启波特率加速BRS = true)
bool 开启波特率加速BRS = true,
int 循环发送间隔毫秒 = 0)
{
if (!TryParseFrameId(帧IDStr, out uint 帧ID))
{
@@ -713,23 +716,88 @@ namespace ZLGUSBCANFD
if (通道号 >= _maxChannels || _channelHandles[通道号] == IntPtr.Zero) return false;
if (原始数据 == null) return false;
if (循环发送间隔毫秒 < 0) throw new ArgumentOutOfRangeException(nameof(循环发送间隔毫秒), "循环发送间隔必须大于或等于 0。");
// 扩展帧需要把最高位标志位置起来
uint canId = 帧ID & 0x7FFFFFFF;
if (是否是扩展帧) canId |= 0x80000000;
// 单次发送
if (循环发送间隔毫秒 == 0)
{
return 发送自定义报文单次(通道号, canId, 原始数据, dlcLength, 是否是扩展帧, 是否是CANFD, 开启波特率加速BRS);
}
// 循环发送:先停止同通道同帧 ID 的旧循环,再启动新循环
停止循环发送(通道号, 帧ID);
// 拷贝原始数据,避免外部修改影响循环发送
byte[] dataCopy = new byte[原始数据.Length];
Array.Copy(原始数据, dataCopy, 原始数据.Length);
var cts = new CancellationTokenSource();
var sendTask = Task.Run(async () =>
{
while (!cts.Token.IsCancellationRequested)
{
if (_isClosing) break;
try
{
lock (_channelLocks[通道号])
{
if (_channelHandles[通道号] == IntPtr.Zero || _isClosing) break;
发送自定义报文单次(通道号, canId, dataCopy, dlcLength, 是否是扩展帧, 是否是CANFD, 开启波特率加速BRS);
}
await Task.Delay(循环发送间隔毫秒, cts.Token);
}
catch (OperationCanceledException)
{
break;
}
catch (Exception ex)
{
Logger.LoggerHelper.Error($"[ZLGCANFD] 循环发送自定义报文失败: {ex.Message}");
break;
}
}
if (_cyclicSenders.TryGetValue((通道号, 帧ID), out var current) && ReferenceEquals(current.Cts, cts))
{
_cyclicSenders.TryRemove((通道号, 帧ID), out _);
}
cts.Dispose();
}, cts.Token);
_cyclicSenders[(通道号, 帧ID)] = (cts, sendTask);
return true;
}
/// <summary>
/// 发送自定义报文的单次执行(内部方法,无循环逻辑)。
/// </summary>
[Browsable(false)]
private bool 发送自定义报文单次(
uint 通道号,
uint canId,
byte[] 原始数据,
byte dlcLength,
bool 是否是扩展帧,
bool 是否是CANFD,
bool 开启波特率加速BRS)
{
lock (_channelLocks[通道号])
{
if (是否是CANFD)
{
// CANFD 有效 DLC 校验
byte validFdDlc = 校验CANFD的Dlc(dlcLength);
ZLGCAN.canfd_frame fdFrame = new ZLGCAN.canfd_frame
{
can_id = canId,
len = validFdDlc,
flags = (byte)((是否是扩展帧 ? 0x01 : 0x00) | (开启波特率加速BRS ? 0x02 : 0x00) | 0x20), // 0x20 本地回显
flags = (byte)((是否是扩展帧 ? 0x01 : 0x00) | (开启波特率加速BRS ? 0x02 : 0x00) | 0x20),
data = new byte[64]
};
Array.Copy(原始数据, 0, fdFrame.data, 0, Math.Min(原始数据.Length, 64));
@@ -749,7 +817,7 @@ namespace ZLGUSBCANFD
{
can_id = canId,
can_dlc = dlcLength > 8 ? (byte)8 : dlcLength,
__pad = 0x20, // 发送回显
__pad = 0x20,
data = new byte[8]
};
Array.Copy(原始数据, 0, standardFrame.data, 0, Math.Min(原始数据.Length, 8));