项目介绍
ADMT4000 是一款高性能磁编码器芯片,其独特之处在于能够在完全掉电状态下保持圈数记录,最大可记录46圈。这一特性使其在需要断电位置保持的应用场景中具有重要价值,如工业自动化、机器人关节定位、医疗设备等。
本项目的主要目标是验证 ADMT4000 的掉电圈数记录能力,并构建一个完整的测试验证系统。系统采用 FT4232 USB 转多协议接口芯片作为通信桥梁,配合电子墨水屏实现实时数据显示,全部软件使用 Rust 语言开发,确保在 Windows、macOS 和 Linux 系统上的跨平台兼容性。
硬件设计
系统架构
- 传感模块:ADMT4000 磁编码器芯片及其外围电路
- 接口模块:FT4232 USB 转 SPI 接口板
- 显示模块:1.54 英寸电子墨水屏
ADMT4000 电路设计
参考数据手册中的 Typical System Configuration 第一种电路方案:
- 电源设计:采用 3.3V 供电,使用 100nF 和 1μF 电容进行电源去耦
- 复位电路:复位信号(RSTB)通过 100kΩ 上拉电阻连接到 VDD,未对外引出
- SPI 接口:仅引出四根信号线(SCLK、MOSI、MISO、CSB)
- 磁铁安装:建议使用径向磁铁,距离需要根据芯片手册工作磁场强度调整。


引脚连接表
ADMT4000 引脚 | FT4232 接口 | 功能说明 |
|---|---|---|
VDD (3.3V) | 3.3V 输出 | 电源正极 |
GND | GND | 电源地 |
SCLK | AD0 (SCK) | SPI 时钟 |
MOSI | AD1 (MOSI) | 主出从入 |
MISO | AD2 (MISO) | 主入从出 |
CSB | AD3 (CS) | 片选信号 |
墨水屏引脚 | FT4232 接口 | 功能说明 |
|---|---|---|
VDD (3.3V) | 3.3V 输出 | 电源正极 |
GND | GND | 电源地 |
SCL | BD0 (SCK) | SPI时钟 |
SDA | BD1 (MOSI) | SPI数据 |
RES | BD2 | 复位 |
DC | BD3 | 数据/命令 |
CS | BD4 | 片选信号 |
BUSY | BD5 | 忙信号 |
FT4232 配置
FT4232 芯片内置两个 MPSSE 引擎,本项目中将两个引擎均配置为 SPI 主模式:
- Engine A:连接ADMT4000,速率配置为10MHz(不高于芯片最大 10MHz 以确保稳定性)
- Engine B:连接墨水屏,速率配置为30MHz
- GPIO 扩展:利用
Engine B剩余引脚控制墨水屏的复位、忙信号检测等
软件实现
流程图

ft4232
FT4232该芯片内置两个mpsse引擎,可以作为spi/jtag/iic/gpio等接口。mpsse从fifo读取指令,执行并将数据写回到fifo中。因此只需要按照官方mpsse手册,使用usb库往fifo中写入指令并及时回读即可。借用我之前使用rust重写的驱动可以轻松实现本项目需要的usb转spi。
本项目中两个mpsse都作为SPI使用,并提供相应的gpio。在初始化spi后在循环里重复读取寄存器并更新显示内容即可。
ADMT4000
let mpsse_1 =
FtdiMpsse::open(&device[0].usb_device, Interface::A).expect("Failed to open MPSSE 1");
mpsse_1.set_frequency(10_000_000).unwrap();
let spi_device = FtdiSpiDevice::new(Arc::new(Mutex::new(mpsse_1))).unwrap();
let mut admt4000 = Admt4000::new(spi_device);
获取mpsse并构造spi设备,并使用此spi构造Admt4000实例。
fn calc_crc(input: u32) -> u8 {
let mut shft = [1u8, 1, 1, 1, 1];
for i in (5..=30).rev() {
let data_bit = ((input >> i) & 1) as u8;
let xor_0 = data_bit ^ shft[4];
shft[4] = shft[3];
shft[3] = shft[2];
shft[2] = shft[1] ^ xor_0;
shft[1] = shft[0];
shft[0] = xor_0;
}
let mut crc5 = 0u8;
for i in 0..5 {
crc5 |= shft[i] << i;
}
crc5
}
根据手册说明,读写寄存器需要crc校验,虽然任务中单纯读取可以忽略校验位,但依旧建议完整实现。使用crc校验可以确保SPI通信的物理链路没有问题,在最开始我的spi设置为30Mhz,crc一直校验不过,最后才发现是spi速率过高。
读取角度主要有两个寄存器,0x03绝对角度寄存器和0x05角度寄存器。绝对角度寄存器中高六位是圈数值,注意该六位值会映射到[-9,53],剩余10位则是映射到[0°,360°),而0x05寄存器是16位映射到[0°,360°)。
墨水屏

let mpsse_2 =
FtdiMpsse::open(&device[0].usb_device, Interface::B).expect("Failed to open MPSSE 2");
let mtx = Arc::new(Mutex::new(mpsse_2));
let mut buffer = Ssd1680Buffer::<152, 152, 2888>::new();
let spi = FtdiSpiTx::new(mtx.clone()).unwrap();
let mut rst = FtdiOutputPin::new(mtx.clone(), Pin::Lower(2))?;
let dc = FtdiOutputPin::new(mtx.clone(), Pin::Lower(3))?;
let cs = FtdiOutputPin::new(mtx.clone(), Pin::Lower(4))?;
let mut busy = FtdiInputPin::new(mtx.clone(), Pin::Lower(5))?;
let mut ssd1680 = Ssd1680::new(ExclusiveDevice::new_no_delay(spi, cs)?, dc);
同样是先获取mpsse,再由mpsse构造spi以及其他所需要的io。
rst.set_low().unwrap();
rst.set_high().unwrap();
unsafe {
ssd1680.assert_hard_reset();
}
wait_not_busy(&mut ssd1680, &mut busy);
ssd1680.soft_reset().unwrap();
wait_not_busy(&mut ssd1680, &mut busy);
ssd1680.init_fast_seq1().unwrap();
wait_not_busy(&mut ssd1680, &mut busy);
ssd1680.init_fast_seq2().unwrap();
wait_not_busy(&mut ssd1680, &mut busy);
墨水屏初始化流程:硬复位、软复位、发送初始化序列、[写显存+发送刷新指令],每两步之间等待busy信号变低再进行下一步。
ssd1680.fast_update(&buffer.0).unwrap();
wait_not_busy(&mut ssd1680, &mut busy);
在不切换刷新模式的情况下,在执行完一次初始化流程后,后续更新显示内容只需要将buffer通过spi传输,然后启动刷新即可,不需要重新初始化。
遇到的问题与解决方案
1. SPI 通信不稳定问题
问题描述:crc始终无法校验通过。
根本原因:ADMT4000 的最大 SPI 速率为 10MHz,总线上数据不可靠。
解决方案:将SPI速率降至10MHz。
2. 掉电圈数无法记录
问题描述:上电状态圈数正常,重新上电后圈数回到46。
根本原因:磁铁安装距离过近,导致内部硬件圈数记录并未工作。
解决方案:参考手册重新安装。
项目总结
本项目成功验证了 ADMT4000 磁编码器的掉电圈数记录功能,证明了其在断电情况下能够可靠保持最多 46 圈的记录。通过构建基于 FT4232 和墨水屏的测试系统,在 [ 掉电-转动-上电读取 ] 循环测试中,ADMT4000 的圈数记录并未出现丢失情况,使用 Rust 语言开发的测试软件具有良好的跨平台兼容性,代码结构清晰,易于维护和扩展。
相关链接
- ADMT4000 数据手册:https://www.analog.com/media/en/technical-documentation/data-sheets/admt4000.pdf
- FT4232H 数据手册:https://ftdichip.cn/Support/Documents/DataSheets/ICs/DS_FT4232H.pdf
- MPSSE 编程指南:https://ftdichip.cn/Support/Documents/AppNotes/AN_135_MPSSE_Basics.pdf
- Rust 嵌入式开发指南:https://docs.rust-embedded.org/book
- ftx232驱动库:https://github.com/fan2nd/ftdi-tools-rs