STM32: простая передача SPI

Я работаю с платой STM32F3DISCOVERY и пытаюсь немного глубже погрузиться в абстракции HAL. Я сделал простую версию функции, которая передает данные через SPI, к сожалению, она не работает (по крайней мере, DAC, на который я ее отправляю, не меняет состояния), и я не уверен, что мне там не хватает. Возможно, в коде инициализации есть что-то, что не работает с моей простой версией. Буду рад любым советам или ссылкам, которые я смогу проверить. Спасибо!

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

person chmanie    schedule 15.08.2020    source источник
comment
Если HAL_SPI_Transmit работает, периферийное устройство инициализировано правильно, я бы проверил, что делает HAL_SPI_Transmit и различия с SPI_SendReceive   -  person Jose    schedule 15.08.2020
comment
Вы не говорите, что именно не работает ... Также вы передаете данные по SPI. Но к чему? Еще одна доска? Периферийное?   -  person Guillaume Petitjean    schedule 17.08.2020
comment
Спасибо вам обоим за ваши комментарии! Я пытаюсь поговорить с TI 8564 DAC. Извините за то, что не прояснил это. Сейчас единственное, что я могу оценить, - это изменение напряжения на ЦАП. Однако я попытаюсь получить доступ к логическому анализатору, а затем предоставлю дополнительную информацию! Спасибо вам до сих пор! @Jose Я проверил функцию HAL_SPI_Transmit, и она делает очень много вещей, которые могут быть, а могут и не быть обязательными. Я немного повозился с этим, пытаясь прокомментировать вещи, которые, как я думал, могут быть не нужны в моем случае, но в конце концов сдался :(   -  person chmanie    schedule 17.08.2020
comment
Да, HAL довольно сложен, потому что он пытается поддерживать все возможные конфигурации и варианты использования. Однако в этом ужасном множестве вещей есть некоторые, которые являются обязательными ... В частности, вы должны установить количество байтов, которые должны быть отправлены / получены, и запускать / останавливать SPI при каждой передаче. Справочное руководство STM32 описывает, что вам нужно сделать.   -  person Guillaume Petitjean    schedule 17.08.2020
comment
Спасибо, @GuillaumePetitjean, я проверю справочное руководство и покопаюсь, как только у меня появятся лучшие средства для отладки, а не просто включение / выключение обратной связи!   -  person chmanie    schedule 17.08.2020


Ответы (1)


Проверьте содержимое HAL_SPI_Init. Скорее всего, эта функция вызывает другую функцию, которая должна выполнять низкоуровневую инициализацию, и вы несете ответственность за предоставление этой функции самостоятельно. Чтобы сделать его более сложным, эта предполагаемая вторая функция уже имеет фиктивный слабый псевдоним, поэтому инструментальная цепочка не возвращает никаких ошибок, а просто создает код, который ничего не может сделать.

person A.R.f.    schedule 25.08.2020