一、项目描述
本项目基于ADI公司的ADMT4000高精度磁性角度与转数传感器,设计并实现了一套用于检测电机旋转圈数及相对角度的嵌入式系统。ADMT4000集成了GMR(巨磁阻)转数计数器和AMR(各向异性磁阻)角度传感器,能够在无需外部电池的情况下实现断电位置记忆,通电后通过SPI接口即可读取绝对位置信息,包括完整旋转圈数和0°~360°范围内的高分辨率角度值。系统以MCU作为主控,完成传感器初始化、数据采集与解析,并将实时结果输出至彩色LCD显示屏。
二、硬件介绍
1.硬件描述
(1)ADMT4000
本项目核心传感单元为ADI公司出品的ADMT4000磁性匝数传感器。它是一款非接触式、高精度的位置与转数检测芯片,特别适用于需要断电后仍能保持位置记忆的应用场景。
该芯片内部集成三个独立磁传感器:
- 一个巨磁阻(GMR)匝数计数器,用于记录系统旋转圈数;
- 一个GMR象限检测传感器,配合AMR角度传感器共同确定绝对角度;
- 一个各向异性磁阻(AMR)角度传感器,可提供0°~360°范围内的高分辨率角度值。
三者协同工作,使得ADMT4000在通电后可通过SPI接口直接读取系统的绝对位置——包括完整旋转圈数和当前角度,最大支持顺时针方向连续计数46圈,精度高达±0.25°,数字输出分辨率超过16k。
此外,芯片内置温度传感器,支持宽温工作(-40°C至+150°C),供电电压范围为1.7V~5V,典型工作电压3.3V,采用24引脚TSSOP封装,适合工业级应用。同时具备欠压与过压检测功能,增强系统稳定性。
由于其无需外部电源即可保存转数信息,特别适合无刷直流电机控制、执行器定位等对可靠性要求较高的场合。

(2)同时本项目使用一个spi通信的LCD彩屏,和N32H785为主控芯片的开发板。
2.PCB设计

本项目的PCB设计参考ADMT4000官方数据手册中的推荐电路布局与引脚定义。如上图所示,为简化系统结构并降低硬件复杂度,本项目仅使用芯片的串行外设接口(SPI)进行通信,未启用其GPIO功能。所有必要的电源与控制信号均从芯片引出,包括VDD(3.3V供电)、RESET(复位)、GND(接地),以及SPI通信所需的四个核心引脚:CS(片选)、SCLK(时钟)、SDI(数据输入)、SDO(数据输出)。
在布局方面,考虑到电机安装位置与传感器磁路对准的需求,我们将ADMT4000芯片放置于PCB中央区域,使其正对旋转轴心,确保磁场感应最稳定。同时,PCB尺寸也根据实际电机外壳做了适配,提升整体系统的可靠性与测量精度。

三、软介绍
整个软件流程如下

在软件设计方面,系统上电后首先完成所用到的GPIO的初始化,并通过接口配置并驱动彩色LCD屏幕,用于后续数据显示。随后进入主循环,在每次循环中,MCU通过SPI协议向ADMT4000发送读取命令,获取包含旋转圈数和角度值的原始寄存器数据。读取到的数据经过简单的解析与单位换算,得到当前前圈数信息,和角度信息。处理完成后,系统将实时结果显示在LCD屏幕上。
1.初始化所有用到的IO
void GPIO_Configuration(void)
{
GPIO_InitType GPIO_InitStructure;
GPIO_InitStruct(&GPIO_InitStructure);
GPIO_InitStructure.Pin = LED1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_NO_PULL;
GPIO_InitPeripheral( LED1_PORT, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|
GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15|GPIO_PIN_8;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStructure.GPIO_Pull = GPIO_PULL_DOWN;
GPIO_InitPeripheral( GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.Pin = GPIO_PIN_14;
GPIO_InitStructure.GPIO_Mode = GPIO_MODE_INPUT;
GPIO_InitPeripheral(GPIOB,&GPIO_InitStructure);
}
2.移植LCD代码,调用LCD初始化函数,并填充背景色
LCD_Init();
LCD_Fill(0,0,320,170,0XA651);
3.读取ADMT4000数据
函数通过位操作模拟SPI协议,向ADMT4000芯片发送8位地址(左移24位构成32位命令),随后读取32位返回数据,并按小端序拆分为4字节存入list数组
void admt4000_read(uint8_t addr,uint8_t* list)
{
uint32_t data = 0;
uint32_t buff = 0;
uint8_t i = 32;
data |=addr<<24;
ADMT_CLK(0);
ADMT_CS(1);
systick_delay_ms(800);
ADMT_CS(0);
while(i--){
if(data&0x80000000)ADMT_SDO(1);
else ADMT_SDO(0);
data<<=1;
systick_delay_us(1);
ADMT_CLK(1);
buff<<=1;
buff|=ADMT_SDI;
systick_delay_us(1);
ADMT_CLK(0);
systick_delay_us(1);
}
ADMT_CS(1);
list[0] = (uint8_t)(buff&0xff);
buff>>=8;
list[1] = (uint8_t)(buff&0xff);
buff>>=8;
list[2] = (uint8_t)(buff&0xff);
buff>>=8;
list[3] = (uint8_t)(buff&0xff);
return ;
}
4.处理数据并显示
分别读取admt4000的0x03和0x05寄存器,分别是绝对角度寄存器和角度寄存器。将读取数据存入数组list中,然后存入字符数组,并在彩色LCD中显示。
admt4000_read(0x03,list);
admt4000_read(0x05,list+4);
temp = list[2];
temp2 = list[6]<<8|list[5];
turns = temp/4.0;
angle = (float)((temp2>>4)*0.08789);
sprintf(NUM_string,"%5.2f",turns);
LCD_ShowString(60,70,NUM_string,WHITE,BLACK,32,0);
sprintf(NUM_string,"%6.2f",angle);
LCD_ShowString(200,70,NUM_string,WHITE,BLACK,32,0);
四、结果展示

LCD左侧显示的是圈数,右侧显示的是角度,将电机旋转大约半圈,可见读取数据同步改变。
五、心得与体会
通过这次基于ADMT4000的电机角度与圈数检测项目,我不仅加深了对高精度磁性传感器工作原理的理解,也更熟悉了SPI通信在实际嵌入式系统中的应用。从硬件布局到软件调试,每一步都让我体会到细节的重要性——比如芯片位置对磁场感应的影响,或是数据解析时位序和格式的匹配。虽然过程中遇到过读数跳变、屏幕显示错乱等问题,但逐一排查后最终看到稳定输出的那一刻,真的很有成就感。更重要的是,这个小项目让我感受到:哪怕是一个人慢慢做,只要坚持下去,也能做出完整、可靠的东西。