1. 读取AS5048角度数据

任务目标

通过SPI接口读取AS5048磁编码器的14位原始角度值(0~16383),将其转换为0~360.0°的浮点角度,并在终端打印结果以验证数据正确性。本案例使用STM32 HAL库实现主机端SPI通信,AS5048作为从设备。

硬件连接与依赖

  • MCU:STM32F407(或其他支持HAL库的STM32系列)
  • 传感器:AS5048B(14位磁角编码器,SPI接口)
  • 连接:SCK→PA5,MISO→PA6,MOSI→PA7,CS→PA4(软件控制片选)
  • 库依赖:STM32CubeMX生成的HAL库,SPI1已配置为模式0(CPOL=0,CPHA=1),时钟分频≤4MHz

关键实现说明

AS5048的SPI帧为16位:前2位为命令/状态位(读取命令为0x3FFF),后14位为数据。主机发送16位命令后,从机在下一个16位时钟周期返回数据。因此每次读取需要连续两次SPI传输:第一次发送读命令并丢弃返回,第二次发送任意值(如0x0000)并接收有效角度数据。片选在每次16位传输之间必须拉高再拉低,以触发从机更新输出寄存器。

完整代码

// main.c 中用户代码区(SPI1已初始化,CS引脚PA4配置为输出)
#include <stdio.h>
#include <math.h>

#define AS5048_CS_LOW()   HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET)
#define AS5048_CS_HIGH()  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)

// 读取AS5048原始角度值(14位)
uint16_t AS5048_ReadAngleRaw(void) {
    uint16_t cmd = 0x3FFF;  // 读角度寄存器命令
    uint16_t rx1 = 0, rx2 = 0;

    AS5048_CS_LOW();
    HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)&cmd, (uint8_t*)&rx1, 1, 100);
    AS5048_CS_HIGH();

    // 第二次传输获取实际数据
    uint16_t dummy = 0x0000;
    AS5048_CS_LOW();
    HAL_SPI_TransmitReceive(&hspi1, (uint8_t*)&dummy, (uint8_t*)&rx2, 1, 100);
    AS5048_CS_HIGH();

    return rx2 & 0x3FFF;  // 屏蔽高2位,保留14位数据
}

// 将原始值转换为角度(0~360°)
float AS5048_RawToDegrees(uint16_t raw) {
    return (float)raw * 360.0f / 16384.0f;
}

// 主循环中调用示例
int main(void) {
    // ... HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_SPI1_Init(); 等初始化代码 ...

    while (1) {
        uint16_t raw = AS5048_ReadAngleRaw();
        float deg = AS5048_RawToDegrees(raw);
        printf("Raw: %5u, Angle: %.2f°\n", raw, deg);
        HAL_Delay(500);  // 每500ms读取一次
    }
}

运行与验证

  1. 使用STM32CubeMX生成工程,配置SPI1为全双工主机,CPOL=Low、CPHA=2Edge(即模式0),预分频使SCK≤4MHz;PA4设为GPIO输出。
  2. 将代码复制到main.c对应位置,串口重定向至USART1(波特率115200)。
  3. 编译烧录后,打开串口终端,观察输出。

通过条件:缓慢旋转磁铁(或编码器转轴),串口打印的Raw值在0~16383之间连续变化,Angle值在0.00°~360.00°之间对应变化,且无跳变或卡死。若用手固定磁铁在某位置,多次读取的Raw值波动不超过±3 LSB(对应约±0.07°),则SPI通信与数据转换正确。

常见问题

  • 数据始终为0或0x3FFF:检查CS时序是否满足两次传输间拉高;确认SPI模式为CPOL=0/CPHA=1(部分库标注为Mode 1)。
  • 角度跳变剧烈:检查SCK频率是否超过4MHz上限,或电源纹波过大(建议在VDD3V3与GND间加100nF去耦电容)。
  • 串口无输出:确认printf重定向已实现(使用HAL_UART_Transmit或syscall重写)。