2. 读取电机编码器数据

任务目标

通过SPI接口读取AS5047P磁编码器的原始角度数据(14位,0~16383),并验证读取值与手动旋转电机时的物理角度变化一致。

环境与依赖

  • 硬件:STM32F405最小系统板 + AS5047P编码器模块(SPI模式,CS接PB12,SCK=PB13,MISO=PB14,MOSI=PB15)
  • 软件:STM32CubeIDE(HAL库),SPI1时钟分频后不超过10MHz(AS5047P最高支持10MHz)
  • 接线:编码器VCC=3.3V,GND共地,CS/SCK/MISO/MOSI按上述引脚连接

关键实现说明

AS5047P的SPI读取协议为16位帧:前8位为命令(最高位为读标志1,后7位为寄存器地址),后8位为数据。读取角度寄存器(地址0x3FFF)时,发送0xFFFF后,在下一个16位帧的MISO上返回角度值。本实现使用HAL库的HAL_SPI_TransmitReceive,通过片选拉低启动通信,连续收发两个16位帧完成一次角度读取。

完整代码

// main.c 中用户代码区(USER CODE BEGIN Includes / PV / 0 / 4 之间添加)
#include <stdio.h>
#include <string.h>

SPI_HandleTypeDef hspi1;
#define AS5047P_CS_LOW()   HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET)
#define AS5047P_CS_HIGH()  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET)

// 读取AS5047P寄存器值(16位命令/数据协议)
uint16_t AS5047P_ReadReg(uint16_t regAddr) {
    uint16_t cmd = 0x4000 | (regAddr & 0x3FFF);  // 读标志位bit14=1
    uint16_t txData[2] = {cmd, 0x0000};          // 第二帧发送0,用于获取数据
    uint16_t rxData[2] = {0, 0};

    AS5047P_CS_LOW();
    HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)txData, (uint8_t*)rxData, 2, HAL_MAX_DELAY);
    AS5047P_CS_HIGH();

    return rxData[1];  // 第二帧返回寄存器内容
}

// 读取14位角度值(0~16383)
uint16_t AS5047P_GetAngle(void) {
    return AS5047P_ReadReg(0x3FFF) & 0x3FFF;  // 角度寄存器地址0x3FFF
}

// main() 中 USER CODE BEGIN 2 之后添加初始化与主循环
// SPI1 已在 MX_SPI1_Init() 中配置为:MSB先行,CPOL=0,CPHA=1(SPI模式1),预分频32(此时钟约2.625MHz)
// GPIOB Pin12 已在 MX_GPIO_Init() 中配置为推挽输出,初始为高电平

uint16_t angle;
char msg[64];

while (1) {
    angle = AS5047P_GetAngle();
    sprintf(msg, "Angle: %u\r\n", angle);
    HAL_UART_Transmit(&huart2, (uint8_t*)msg, strlen(msg), 100);
    HAL_Delay(200);
}

运行与验证

  1. 编译烧录后,打开串口助手(波特率115200,对应USART2),观察输出。
  2. 静态验证:保持电机轴不动,串口输出的角度值应稳定在±2 LSB以内(AS5047P内部噪声极小)。
  3. 动态验证:手动缓慢旋转电机轴一整圈,观察输出值应从0~16383连续递增(或递减,取决于旋转方向),且无跳变、无重复段。
  4. 通过标准:旋转360°过程中,输出值覆盖整个0~16383范围且单调变化;停止旋转后数值稳定不漂移。

常见问题

  • 输出恒为0或0x3FFF:检查SPI模式是否为模式1(CPOL=0,CPHA=1),以及CS引脚是否在通信前后正确拉低/拉高。
  • 数值跳变剧烈:检查MISO/MOSI接线是否松动,或SPI时钟是否超过10MHz(降低分频系数)。
  • 角度非线性:确认编码器磁铁是否居中安装,偏心会导致角度读数呈正弦误差。