使用 SPI 从 STM32 上的磁性编码器传输和读取 16 位值

Posted

技术标签:

【中文标题】使用 SPI 从 STM32 上的磁性编码器传输和读取 16 位值【英文标题】:Transmit and read 16 bit values from magnetic encoder on STM32 with SPI 【发布时间】:2022-01-08 02:24:28 【问题描述】:

我正在尝试通过 STM32 NUCLEO F446RE 上的 SPI 从 AMS AS5050A 磁编码器读取值,但我无法让它工作。当我使用 HAL 库时,输出始终为 0。我对外围设备的设置是这样的:

hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_16BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi3) != HAL_OK)

    Error_Handler();

这是我目前的代码:

    HAL_StatusTypeDef ret = 0;
    short address = AMS_AS5050A_create_command(AMS_AS5050A_SPI_READ, 0x3FFF);

    // pull slave select pin low
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
    //transmit data
    ret = HAL_SPI_Transmit(&hspi3, (uint8_t *) &address, 2, HAL_MAX_DELAY);
    // pull slave select pin high
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);

    sprintf(buf, "[MAIN] test transmit returned code: %d\r\n", ret);
    UART_send(buf);

    HAL_Delay(50);

    uint16_t temp_data = 0;

    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
    ret = HAL_SPI_Receive(&hspi3, (uint8_t*) &temp_data, 2,
    HAL_MAX_DELAY);
    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);

    sprintf(buf, "[MAIN] test receive returned code: %d\r\n", ret);
    UART_send(buf);

    sprintf(buf, "[MAIN] test transmit and receive angle is: %d\r\n",
            temp_data);
    UART_send(buf);
    HAL_Delay(50);

AMS_AS5050A_create_command 函数将读/写位添加到short 并添加奇偶校验位,当与命令0x3FFF 一起使用时,它给出0xFFFF,这是正确的。它看起来像这样:

short AMS_AS5050A_create_command(uint8_t read_write, short address)


    short data = read_write << 15;
    data |= (address << 1);
    short res = data | calculate_parity(data);

    return res;

当我在 PuTTy 中查看输出时,输出始终为 0。函数没有给出任何错误代码,但 SPI 读取命令的输出始终为 0,即使我在它前面拿着一块磁铁:

[MAIN] test transmit returned code: 0
[MAIN] test receive returned code: 0
[MAIN] test transmit and receive angle is: 0
[MAIN] test transmit returned code: 0
[MAIN] test receive returned code: 0
[MAIN] test transmit and receive angle is: 0
[MAIN] test transmit returned code: 0
[MAIN] test receive returned code: 0
[MAIN] test transmit and receive angle is: 0
[MAIN] test transmit returned code: 0
[MAIN] test receive returned code: 0
[MAIN] test transmit and receive angle is: 0

有人知道我做错了什么吗?

【问题讨论】:

【参考方案1】:

虽然有变化,但通常的顺序是:

    启用设备 向设备写入命令以请求其状态 读取状态 如果忙,则返回步骤 2 编写请求最新数据的命令 编写命令读取状态 如果状态表明数据可用 然后写一条命令来读取数据 读取数据 禁用设备

但是,此特定设备有其自己的详细信息,您的代码没有考虑到这些详细信息。

几个cmets:

您可以(应该)使用来自设备的中断信号来触发数据的读取,而不是请求数据转换的状态。

数据表的图 10 说:“显示了 AS5050A 如何连接到微控制器。SPI 接口是用于访问片上寄存器的从接口。INT/ 输出是低电平有效中断当有新结果可用时通知主机微控制器。”您发布的代码没有考虑该信号

请阅读段落:“阅读角度”,了解如何开始转换、如何识别何时完成转换等的详细信息

【讨论】:

我试过这个,但我也得到了同样的结果。已完成的发送和接收函数的回调被调用,但编码器中断引脚上的回调永远不会被调用。你知道可能出了什么问题吗? 参考文档列出了设备应如何连接的详细信息以及所有命令和状态信息。建议发布您的实际连接和您用于读取数据的代码

以上是关于使用 SPI 从 STM32 上的磁性编码器传输和读取 16 位值的主要内容,如果未能解决你的问题,请参考以下文章

SPI从机将数据读入stm32上的缓冲区?

梳理STM32F429之通信传输部分---NO.8 硬件SPI

请教STM32F103与DSP采用SPI通信的问题!

STM32和ADXL345之间的SPI通信

STM32:简单的 SPI 传输

STM32 SPI通讯