Transmit and read 16 bit values from magnetic encoder on STM32 with SPI

680 Views Asked by At

I am trying to read values from an AMS AS5050A magnetic encoder via SPI on an STM32 NUCLEO F446RE, but I cannot get it to work. When I use the HAL library, the output is always 0. My setup for the peripheral is this:

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();
}

This is my code so far:

    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);

The AMS_AS5050A_create_command function adds a read/write bit to the short and adds a parity bit, when used with the command 0x3FFF it gives 0xFFFF, which is correct. It looks like this:

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;
}

When I look at the output in PuTTy, the output is always 0. The functions do not give any error codes but the output from the SPI read command is always 0, even when I hold a magnet in front of it:

[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

Does anybody have an idea of what I'm doing wrong?

1

There are 1 best solutions below

2
On

while there are variations, the usual sequence is:

  1. enable the device
  2. write a command to the device requesting it's status
  3. read the status
  4. if busy, loop back to step 2
  5. write a command requesting the latest data
  6. write a command to read the status
  7. if status indicates data available
  8. then write a command to read the data
  9. read the data
  10. disable the device

however, this specific device has its' own details, which your code has not taken into account.

a few comments:

rather than requesting the status of the data conversion, you could (should) be using the interrupt signal from the device to trigger the reading of the data.

figure 10 of the data sheet says: "shows how the AS5050A can be connected to a microcontroller. The SPI interface is a slave inter face for accessing the on-chip registers. The INT/ output is an active-low interrupt for informing the host microcontroller when a new result is available." Your posted code is not taking that signal into account

Please read the paragraph: "reading the angle" for details on how to start a conversion, how to recognize when the conversion is complete, etc