MT6835是一款基于AMR(各向异性磁阻)技术的高精度角度传感器芯片,广泛应用于工业伺服、机器人关节和自动化控制领域。这颗芯片的核心优势在于其非接触式测量特性和21位绝对角度输出分辨率,相当于能将360°圆周划分为2,097,152个细分位置。
芯片内部采用两对正交布置的AMR惠斯通电桥作为传感核心。当外部磁场方向变化时,电桥会产生两路相位差90°的正余弦模拟信号(Vsin和Vcos)。这两路信号经过以下处理链路:
关键提示:MT6835的AMR传感器对磁场方向敏感而非强度,建议使用径向充磁的磁铁,磁场强度范围建议在20-100mT之间。
芯片提供多种输出接口,本方案采用的SPI接口具有以下通信特性:
| 参数 | 规格说明 |
|---|---|
| 时钟频率 | 最大10MHz(3.3V供电) |
| 数据格式 | 摩托罗拉模式,MSB优先 |
| 传输模式 | 全双工,CPOL=1, CPHA=1 |
| 数据帧格式 | 命令字+地址+数据(详见图1) |

MT6835的内部寄存器采用16位地址寻址,角度数据存储在特定地址区域:
| 地址 | 数据内容 | 位宽 | 说明 |
|---|---|---|---|
| 0x0003 | ANGLE[7:0] | 8位 | 角度值低字节 |
| 0x0004 | ANGLE[15:8] | 8位 | 角度值中字节 |
| 0x0005 | ANGLE[20:16] + STATUS | 8位 | 高5位角度+3位状态 |
| 0x0006 | CRC8 | 8位 | 数据校验码 |
角度值计算示例:
c复制// 将3个字节数据组合成21位角度值
uint32_t angle = ((buf[2] & 0x1F) << 16) | (buf[1] << 8) | buf[0];
float degree = angle * 360.0f / 2097152.0f; // 转换为角度值

实际测试发现,连续读取4个字节(角度+状态+CRC)的耗时比单字节模式减少约60%
APM32F425的SPI3接口配置要点:
c复制void MX_SPI3_Init(void) {
GPIO_Config_T GPIO_InitStructure = {0};
SPI_Config_T SPI_InitStructure = {0};
// 时钟使能
RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_SPI3);
RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOB);
// PB3(SCK), PB4(MISO), PB5(MOSI)复用配置
GPIO_InitStructure.pin = GPIO_PIN_3 | GPIO_PIN_4 | GPIO_PIN_5;
GPIO_InitStructure.mode = GPIO_MODE_AF;
GPIO_InitStructure.af = GPIO_AF_SPI3;
GPIO_InitStructure.speed = GPIO_SPEED_100MHz;
GPIO_InitStructure.otype = GPIO_OTYPE_PP;
GPIO_InitStructure.pupd = GPIO_PUPD_NOPULL;
GPIO_Config(GPIOB, &GPIO_InitStructure);
// 片选引脚PA15配置(软件控制)
GPIO_InitStructure.pin = GPIO_PIN_15;
GPIO_InitStructure.mode = GPIO_MODE_OUT;
GPIO_Config(GPIOA, &GPIO_InitStructure);
GPIO_SetBit(GPIOA, GPIO_PIN_15); // 初始高电平
// SPI参数配置
SPI_InitStructure.direction = SPI_DIRECTION_2LINES_FULLDUPLEX;
SPI_InitStructure.mode = SPI_MODE_MASTER;
SPI_InitStructure.dataSize = SPI_DATA_LENGTH_8B;
SPI_InitStructure.clockPolarity = SPI_CLKPOL_HIGH; // CPOL=1
SPI_InitStructure.clockPhase = SPI_CLKPHA_2EDGE; // CPHA=1
SPI_InitStructure.baudratePrescaler = SPI_BAUDRATE_DIV_16; // 120MHz/16=7.5MHz
SPI_InitStructure.firstBit = SPI_FIRSTBIT_MSB;
SPI_Config(SPI3, &SPI_InitStructure);
SPI_Enable(SPI3);
}
关键参数选择依据:
DMA配置采用双流模式(发送流7和接收流0):
c复制void MX_DMA1_Init(void) {
DMA_Config_T DMA_ConfigStruct = {0};
RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_DMA1);
// 接收流配置(DMA1_Stream0)
DMA_ConfigStruct.channel = DMA_CHANNEL_0;
DMA_ConfigStruct.direction = DMA_DIR_PERIPHERALTOMEMORY;
DMA_ConfigStruct.memoryDataSize = DMA_MEMORY_DATA_SIZE_BYTE;
DMA_ConfigStruct.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_BYTE;
DMA_Config(DMA1_Stream0, &DMA_ConfigStruct);
// 发送流配置(DMA1_Stream7)
DMA_ConfigStruct.direction = DMA_DIR_MEMORYTOPERIPHERAL;
DMA_Config(DMA1_Stream7, &DMA_ConfigStruct);
}
DMA通道选择参考APM32F425的DMA请求映射表:
| 外设 | 请求类型 | 流编号 | 通道 |
|---|---|---|---|
| SPI3_TX | DMA1 | 7 | 通道0 |
| SPI3_RX | DMA1 | 0 | 通道0 |
完整的数据采集函数实现:
c复制uint8_t spi3_send_buf[6] = {0x0B, 0x00, 0x03, 0x00, 0x04, 0x00}; // 连续读取命令
uint8_t spi3_rec_buf[6] = {0};
void magnetic0_requestdata() {
// 1. 准备DMA传输
DMA_Disable(DMA1_Stream0);
DMA_ConfigDataNumber(DMA1_Stream0, 6); // 接收6字节
DMA_ConfigMemoryAddress(DMA1_Stream0, (uint32_t)spi3_rec_buf);
DMA_Disable(DMA1_Stream7);
DMA_ConfigDataNumber(DMA1_Stream7, 6); // 发送6字节
DMA_ConfigMemoryAddress(DMA1_Stream7, (uint32_t)spi3_send_buf);
// 2. 启动传输
GPIO_ResetBit(GPIOA, GPIO_PIN_15); // 拉低片选
SPI_I2S_EnableDMA(SPI3, SPI_I2S_DMA_REQ_TX | SPI_I2S_DMA_REQ_RX);
DMA_Enable(DMA1_Stream7);
DMA_Enable(DMA1_Stream0);
// 3. 等待传输完成(实际应用建议用中断)
while(!DMA_GetFlagStatus(DMA1_STREAM0, DMA_FLAG_TCIF0));
// 4. 结束传输
GPIO_SetBit(GPIOA, GPIO_PIN_15); // 拉高片选
DMA_Disable(DMA1_Stream7);
DMA_Disable(DMA1_Stream0);
SPI_I2S_DisableDMA(SPI3, SPI_I2S_DMA_REQ_TX | SPI_I2S_DMA_REQ_RX);
// 5. 清除标志位
DMA_ClearFlag(DMA1_STREAM0, DMA_FLAG_TCIF0);
DMA_ClearFlag(DMA1_STREAM7, DMA_FLAG_TCIF7);
}
MT6835采用CRC-8算法(多项式0x07),查表法比实时计算效率提升约8倍:
c复制// 预计算的CRC表(多项式0x07)
const uint8_t Crc8_Tab[256] = {
0x00,0x07,0x0E,0x09,0x1C,0x1B,0x12,0x15,0x38,0x3F,0x36,0x31,0x24,0x23,0x2A,0x2D,
// ...(完整表格见前文)
};
uint8_t calculate_crc(uint32_t data) {
uint8_t crc = 0;
uint8_t *p = (uint8_t*)&data;
crc = Crc8_Tab[crc ^ p[2]]; // 高字节
crc = Crc8_Tab[crc ^ p[1]]; // 中字节
crc = Crc8_Tab[crc ^ p[0]]; // 低字节
return crc;
}
校验流程示例:
c复制uint32_t raw_data = ((spi3_rec_buf[2] & 0x1F) << 16) |
(spi3_rec_buf[1] << 8) |
spi3_rec_buf[0];
uint8_t calc_crc = calculate_crc(raw_data);
if(calc_crc != spi3_rec_buf[5]) {
// CRC校验失败处理
}
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 通信无响应 | 1. 接线错误 | 检查SCK/MOSI/MISO连接 |
| 2. 片选信号异常 | 示波器观察NSS信号时序 | |
| 角度数据跳变 | 1. 磁场干扰 | 使用屏蔽线,远离干扰源 |
| 2. CRC校验失败 | 检查CRC算法实现 | |
| DMA传输不完整 | 1. 缓冲区未对齐 | 确保内存地址4字节对齐 |
| 2. 流控制器配置错误 | 检查DMA_CNDTR寄存器值 |
时序优化:
DMA优化技巧:
c复制// 启用DMA双缓冲模式(需APM32F4xx支持)
DMA_DoubleBufferModeConfig(DMA1_Stream0, (uint32_t)buf1, (uint32_t)buf2, DMA_MEMORY_0);
DMA_DoubleBufferModeEnable(DMA1_Stream0);
抗干扰设计:
我在实际项目中发现,当SPI时钟超过10MHz时,信号完整性会明显下降。建议通过眼图测试确定最高可靠通信速率,一般保守选择芯片标称最大速率的70%作为工作频率。