现场优化4
This commit is contained in:
+72
-4
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user