跳到主要内容

DC 同步

从站级 DC(分布式时钟)配置。通过 slave.dc() 获取 SlaveDC 实例访问。

推荐使用主站级方法

大多数场景建议使用 master.configure_dc_all() 一次性配置所有 DC 从站。 从站级方法适用于需要对个别从站设置不同参数的场景。

只读属性

类别方法返回类型说明
DC 状态has_dc()boolESC 硬件是否支持 DC
has_esi_dc_sync()boolESI 是否声明此从站使用 DC 同步 (OpMode/AssignActivate 非零)
dc_active()u16DC 激活状态(0=禁用, 非0=已激活)
DC 时间dc_cycle0()i32当前 SYNC0 周期(纳秒)
dc_cycle1()i32当前 SYNC1 周期(纳秒)
dc_shift()i32当前相位偏移(纳秒)
propagation_delay()i32帧从主站到达此从站的传播延迟(纳秒)
DC 拓扑dc_next() / dc_previous()u16DC 链中下一个/上一个从站索引
dc_parent_port()i32DC 父端口号
dc_receive_time_a/b/c/d()i32各端口接收时间(纳秒)
has_dc vs has_esi_dc_sync

has_dc() 仅反映 ESC 硬件 bit, 不代表应用层一定使用 DC. 部分从站 ESC 报 DC capable 但 ESI 未声明 DC OpMode, 此时应跑 FreeRun / SM-Sync, 强行启用 DC 会让从站拒绝进入 OP.

启用 DC 前的稳妥写法:

if slave.has_dc() && slave.has_esi_dc_sync() {
slave.dc().configure(1_000_000, 0, None)?;
}

配置方法

dc().configure()

pub fn configure(&self, sync0_ns: u32, sync1_ns: u32, shift_ns: Option<i32>) -> Result<()>

配置从站 DC 同步。所有参数单位:纳秒(ns)

参数:

  • sync0_ns (u32) — SYNC0 周期(纳秒),0 表示禁用
  • sync1_ns (u32) — SYNC1 增量时间(纳秒),0 表示仅 SYNC0
  • shift_ns (Option<i32>) — 相位偏移(纳秒):None=自动计算(默认),Some(0)=不设置偏移,其他值=手动偏移

示例:

slave.dc().configure(1_000_000, 0, None)?;              // SYNC0 = 1ms,自动偏移
slave.dc().configure(1_000_000, 0, Some(0))?; // SYNC0 = 1ms,不设置偏移

dc().configure_mode()

pub fn configure_mode(&self, mode: DcSyncMode, sync0_ns: u32, sync1_ns: u32, shift_ns: Option<i32>) -> Result<()>

根据同步模式配置 DC(ETG.1020)。

参数:

  • mode (DcSyncMode) — DC 同步模式
  • sync0_ns (u32) — SYNC0 周期(纳秒),仅 DcSynchron 模式使用
  • sync1_ns (u32) — SYNC1 周期(纳秒),仅 DcSynchron 模式使用
  • shift_ns (Option<i32>) — 相位偏移(纳秒),仅 DcSynchron 模式使用

相关结构:

#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum DcSyncMode {
FreeRun = 0, // 自由运行 - 不使用 DC 同步
SmSynchron = 1, // SM 同步 - 使用 SM 事件触发
DcSynchron = 2, // DC 同步 - 使用 SYNC0/SYNC1 信号
}

示例:

slave.dc().configure_mode(DcSyncMode::DcSynchron, 1_000_000, 0, None)?;  // DC SYNC0 = 1ms
slave.dc().configure_mode(DcSyncMode::SmSynchron, 0, 0, None)?; // SM 同步模式
slave.dc().configure_mode(DcSyncMode::FreeRun, 0, 0, None)?; // 自由运行

dc().current_dc_sync_mode()

pub fn current_dc_sync_mode(&self) -> DcSyncMode

获取当前 DC 同步模式。

示例:

let mode = slave.dc().current_dc_sync_mode();
println!("当前 DC 同步模式: {:?}", mode);

dc().disable()

pub fn disable(&self)

禁用此从站的 DC 同步。

同步窗口诊断

dc().sync_window_status()

pub fn sync_window_status(&self) -> Option<SyncWindowStatus>

获取从站 DC 同步窗口的详细状态。不支持 DC 或读取失败时返回 None

返回值:

  • Option<SyncWindowStatus> — 同步窗口状态

相关结构:

pub struct SyncWindowStatus {
pub diff_ns: i32, // 当前时间差(纳秒)
pub max_diff_ns: i32, // 最大时间差(纳秒)
pub min_diff_ns: i32, // 最小时间差(纳秒)
pub in_sync: bool, // 是否在同步窗口内
pub out_of_sync_count: u32, // 超出同步窗口次数
}
便捷属性

如果只需要 in_syncsync_time_difference,可通过 slave.diagnostics().dc() 访问,详见 从站诊断sync_window_status() 适合需要完整统计信息的场景。

dc().reset_sync_window_stats()

pub fn reset_sync_window_stats(&self)

重置此从站的同步窗口统计(最大/最小时间差、超出同步次数等)。

完整示例

let slave = master.slave(1);

if slave.has_dc() {
let dc = slave.dc();
dc.configure(1_000_000, 0, None)?; // SYNC0 = 1ms, 自动偏移

println!("DCActive={}, DCCycle0={}ns, DCShift={}ns",
slave.dc_active(), slave.dc_cycle0(), slave.dc_shift());

// 同步窗口详细状态
if let Some(status) = dc.sync_window_status() {
println!("同步差={}ns, 同步={}", status.diff_ns, status.in_sync);
}

dc.disable();
}