Germanjet SSI 位移传感器主站实现:模块配置与单片机读帧

SSI 常被说成"最省协议"的接口:没有站地址、没有协议栈、不用组态。省的是协议,不是实现——时钟要你自己发,位要你自己拼,帧间隙要你自己留。用现成的 SSI 模块时这些都封在模块里,换成自制板子,这六件事就全回到手上。

主站读一帧 SSI 的六个步骤:锁存、等待、取位、拼接、单稳态、换算
六个动作:从拉低时钟到最后换算,一个都不能省

主站侧只有四个参数

不管主站是 PLC 模块还是一颗单片机,要配的就是四个数,而且这四个数的来源都是订货码和现场线长,不是"调一调试试"。

参数取值怎么来配错的表现
位数型号编码的数据长度位:1 = 25 位,2 = 24 位少一位读数减半,多一位读数翻倍
码制型号编码的代码类型位:B = 二进制,G = 格雷码读数呈锯齿状折返,不单调
时钟频率按电缆长度查表,3 m 以内可到 1000 kBd偶发跳大数、位错
帧间隙不小于 48 μs 的单稳态时间整帧偶发错误,读到上一帧残值

型号编码逐项怎么读见 SSI 帧结构,波形层面怎么判读见 SSI 调试。这篇只讲实现侧:模块里填什么,代码里怎么写。

PLC 侧:模块参数怎么填

  • 数据结构按 32 位选。25 位已经超过 16 位字长。模块或数据区如果按 16 位读,拿到的是截断值,在监视表里表现为"行程走到后半段数字不动了"。
  • 码制选项要跟订货一致。多数模块有 Gray / Binary 两个选项,选错不会报错,只会一直读错。区分方法就是看曲线:折返是码制错,整体偏移是零点错。
  • 时钟频率是可配的,不要默认拉满。线超过 50 米还按 1000 kBd 跑,就是偶发跳数的固定来源。
  • 扫描周期要容得下一帧。一次读取包含"时钟串 + 单稳态":25 位在 1000 kBd 下约 25 μs,再加 48 μs,一帧至少 73 μs。扫描周期比这还短,模块要么丢帧、要么报错。

单片机侧:位翻转读一帧

控制器没有 SSI 外设时,用普通 GPIO 就能读,关键是把采样点放对。数据在时钟下降沿之后更新,在上升沿之前已经稳定,所以在上升沿之后取这一位最稳。

uint32_t ssi_read_frame(int bits)      // bits 取 24 或 25,与订货一致
{
    uint32_t v = 0;
    clock_low();                       // 第一个下降沿:传感器锁存位置
    delay_ns(T_BIT / 2);
    for (int i = 0; i < bits; i++) {
        clock_high();                  // 上升沿:此时数据已稳定
        delay_ns(T_BIT / 2);
        v = (v << 1) | data_read();    // 高位先出,左移拼接
        clock_low();
        delay_ns(T_BIT / 2);
    }
    idle_delay_us(50);                 // 单稳态 ≥48 μs,接口复位后才能再读
    return v;
}

三个必须守住的地方:

  • 用 uint32_t 承接。25 位放不进 uint16_t,用 16 位变量会静默截掉高位,症状和"位数配少"一模一样,很容易查错方向。
  • 采样点放在上升沿之后。在下降沿采,取到的是这一位更新之前的值,整帧会错一位——表现为读数大致对、但总有固定偏差。
  • 帧间隙不能省。"循环里读得越快越好"是错的。48 μs 是接口复位时间,压掉它整帧会偶发错误。

时间预算:一帧多久,能读多快

  • 时钟串本身:位数 × 位宽。25 位在 1000 kBd(1 μs 一位)约 25 μs。
  • 单稳态:≥ 48 μs。
  • 合计:约 73 μs,理论最快约 13.7 kHz。

但真实上限通常不在这里。传感器的更新频率随行程变化,1000 mm 行程只有 2.3 kHz,约 430 μs 才更新一次。主站按 13 kHz 去读,读到的是同一帧的重复值,多做的是无用中断。读取周期应取"更新周期"与"73 μs"两个数里较大的那个,再留余量。更新频率随行程的变化见 SSI 帧结构。

多轴时,这笔时间预算要乘上去

一轴一帧 73 μs,八轴看起来就是 584 μs 一轮。SSI 每轴有自己的时钟线和数据线,理论上可以并行读,实际受两件事限制:

  • 主站侧的通道数。PLC 的 SSI 模块通常按通道卖,通道够就能并行;单片机上用 GPIO 位翻转,多轴要么分时轮询,要么用移位寄存器或 CPOL 型外设扩展通道。
  • CPU 占用。位翻转读一帧要占住 CPU 约 73 μs。八轴分时读,一秒里光拼帧就吃掉几十毫秒,控制周期紧的系统必须把这笔账算进去。

所以多轴场合的实际做法是:通道够就用模块并行读;用 GPIO 就把读取间隔放宽到控制真正需要的程度,比如 10 ms 一次,而不是按传感器的最快更新率去读。轴上去了而线束也跟着上去,这时候该回头比较总线方案,见 按控制器接口选总线。

与 CANopen 主站的区别

同样是自己写主站,SSI 和 CANopen 卡的地方完全不同:SSI 难在时序与位拼接,没有状态机、没有对象字典;CANopen 难在状态机、命令字与字节序,见 Germanjet CANopen 主站实现。SSI 每一轴独占一路时钟与数据,轴数一多线束成本就超过总线,这笔账在选型阶段就该算,见 八种输出接口对照。

一句话

SSI 主站只做三件事:把时钟发对、把位拼对、把间隙留够。三件事省掉任何一件,读出来的都是"看起来对"的数。

常见问题

Q:单片机没有 SSI 外设,能读 SSI 传感器吗

能。用两个普通 GPIO,一个输出时钟、一个输入数据,按时序位翻转即可。要注意三点:上升沿之后采样、变量用 uint32_t、每帧之间留 48 μs 以上。位翻转读法在中断密集的系统里会占 CPU,多轴场合建议用带 SSI 外设或移位寄存器的方案。

Q:25 位数据用 16 位变量存会怎样

高位被静默截掉,读数值失真,而且症状和「主站位数配少」完全一样——都是读数只有一半或卡在某个数上。排查时先确认变量类型,再怀疑配置,能省不少时间。

Q:PLC 模块读到行程后半段数字就不动了

几乎可以肯定是数据结构按 16 位选的。25 位数据超过 16 位字长,读到高位之后就没法继续增大。把模块的输入数据区改成 32 位整数即可,不需要动传感器。

Q:一帧要多久,最快能读多快

25 位在 1000 kBd 下时钟串约 25 μs,加上 48 μs 单稳态,一帧至少 73 μs,理论约 13.7 kHz。但传感器自身更新率更低(1000 mm 行程约 2.3 kHz),按理论值去读只会读到重复值,实际应按更新周期设扫描周期。

这篇讲的问题,说到底都绕不开磁致伸缩位移传感器本身。磁致伸缩位移传感器产品中心按行程、安装方式与输出接口把全部系列排开,选型从这里进最省事。

← 返回行业动态