0

I am working with a STM32F3DISCOVERY board and I'm trying to dive a bit deeper into the abstractions of the HAL. I made a simple version of a function that transmits data over SPI, sadly it does not work (at least the DAC I'm sending it to does not change state) and I'm not sure what I am missing there. Maybe there's also something in the initialization code that doesn't work with my simple version. I'd be happy for any guidance or references I could check. Thank you!

#include <stm32f3xx_hal.h>

#define PINS_SPI GPIO_PIN_5 | GPIO_PIN_7
#define GPIO_PORT GPIOA

/* This is the simplest function I could come up with to do the transfer but I'm clearly missing something here */
uint8_t SPI_SendReceive(SPI_HandleTypeDef *hspi, uint8_t data) {
  /* Loop while DR register in not empty */
  while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET) {
  }

  /* Send data through the SPI1 peripheral */
  hspi->Instance->DR = data;

  /* Wait to receive data */
  while ((hspi->Instance->SR & SPI_FLAG_RXNE) == RESET) {
  }

  return hspi->Instance->DR;
}

int main() {
  HAL_Init();


  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_SPI1_CLK_ENABLE();

  static SPI_HandleTypeDef spi = {.Instance = SPI1};
  spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
  spi.Init.Direction = SPI_DIRECTION_2LINES;
  spi.Init.CLKPhase = SPI_PHASE_1EDGE;
  spi.Init.CLKPolarity = SPI_POLARITY_LOW;
  spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  spi.Init.DataSize = SPI_DATASIZE_8BIT;
  spi.Init.FirstBit = SPI_FIRSTBIT_MSB;
  spi.Init.NSS = SPI_NSS_HARD_OUTPUT;
  spi.Init.TIMode = SPI_TIMODE_DISABLE;
  spi.Init.Mode = SPI_MODE_MASTER;

  HAL_SPI_Init(&spi);
  __HAL_SPI_ENABLE(&spi);

  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.Pin = PINS_SPI;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  /* TI 8564 DAC Settings */
  uint8_t cmd1 = 0b00010000;
  /* DAC output value (16-bit) */
  uint16_t cmd23 = 0;
  uint8_t cmd2 = cmd23 >> 8;
  uint8_t cmd3 = cmd23 & 0xff;

  uint8_t command[3] = {cmd1, cmd2, cmd3};

  while (true) {
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);

    /* This does not work :( */
    SPI_SendReceive(&spi, command[0]);
    SPI_SendReceive(&spi, command[1]);
    SPI_SendReceive(&spi, command[2]);
    
    /* This works! When commenting in the lines above and commenting this out */
    /* HAL_SPI_Transmit(&spi, command, 3, HAL_MAX_DELAY); */

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);

    HAL_Delay(1000);
  }
}
chmanie
  • 5,016
  • 3
  • 21
  • 28
  • 1
    If ```HAL_SPI_Transmit``` is working, the peripheral is initialised properly, I would check what ```HAL_SPI_Transmit``` is doing and the differences with ```SPI_SendReceive``` – Jose Aug 15 '20 at 18:38
  • 1
    You don't say what exactly is not working... Also you transmit data on SPI. But to what ? Another board ? A peripheral ? – Guillaume Petitjean Aug 17 '20 at 07:39
  • Thank you both for your comments! I am trying to talk to a [TI 8564 DAC](https://www.ti.com/product/DAC8564). Sorry for not clarifying that. Right now the only thing that I can assess is a voltage change in the DAC. I will however try to get access to a logic analyzer and then provide more information! Thank you so far! @Jose I checked the `HAL_SPI_Transmit` function and it does an awful lot of things that might or might not be mandatory. I messed around with it a bit trying to comment out things that I thought might not be needed in my case but eventually gave up :( – chmanie Aug 17 '20 at 12:39
  • 1
    Yes, the HAL is pretty complex because it tries to support every possible configuration and use case. However in this "awful lot of things" there are some that are mandatory... In particular you have to set the number of bytes to be send / received and start / stop the SPI at every transfer. The reference manual of STM32 describes what you need to do. – Guillaume Petitjean Aug 17 '20 at 13:40
  • Thank you, @GuillaumePetitjean, I will check the reference manual and poke around as soon as I have better means for debugging rather than just an on/off feedback! – chmanie Aug 17 '20 at 14:06

1 Answers1

0

Check the contents of HAL_SPI_Init. Most likely this function calls another function which is supposed to do the low-level initialization, and you're responsible to provide this function yourself. To make it more complex, this alleged second function already has a "dummy" weak alias defined, so the toolchain doesn't return any error but just builds a code unable to do anything.

A.R.f.
  • 11
  • 2