DC 同步
从站级 DC(分布式时钟)配置。通过 slave.dc() 获取 SlaveDC 实例访问。
推荐使用主站级方法
大多数场景建议使用 master.configure_dc_all() 一次性配置所有 DC 从站。
从站级方法适用于需要对个别从站设置不同参数的场景。
只读属性
| 类别 | 方法 | 返回类型 | 说明 |
|---|---|---|---|
| DC 状态 | has_dc() | bool | ESC 硬件是否支持 DC |
| has_esi_dc_sync() | bool | ESI 是否声明此从站使用 DC 同步 (OpMode/AssignActivate 非零) | |
| dc_active() | u16 | DC 激活状态(0=禁用, 非0=已激活) | |
| DC 时间 | dc_cycle0() | i32 | 当前 SYNC0 周期(纳秒) |
| dc_cycle1() | i32 | 当前 SYNC1 周期(纳秒) | |
| dc_shift() | i32 | 当前相位偏移(纳秒) | |
| propagation_delay() | i32 | 帧从主站到达此从站的传播延迟(纳秒) | |
| DC 拓扑 | dc_next() / dc_previous() | u16 | DC 链中下一个/上一个从站索引 |
| dc_parent_port() | i32 | DC 父端口号 | |
| 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 表示仅 SYNC0shift_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_sync 或 sync_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();
}