Как правильно форматировать данные для отправки по HAL SPI в STM32?

Я пытаюсь прочитать / записать данные из ST EEPROM M95640-W

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

M95640-W Операция чтения

Сначала 8-битная инструкция «Чтение из массива памяти»: 0x03 (B00000011)

Второй - 16-битный адрес.

Но когда я отправляю команду и данные, я получаю следующее:

Адрес 0x0001 (B00000001):  M95640 Прочитать с адреса 0x1

И просто проверить положение данных с помощью зеркальных битов

Адрес 0x0081 (B10000001):  M95640 Прочитать с адреса 0x81


Поэтому я не могу найти ошибку в своем коде, почему он отправляет данные таким неправильным способом. Он отправляет команду 0x20, кроме 0x03. Он отправляет адрес 0x48, кроме 0x01 и 0x80, кроме 0x81. Похоже, у меня неправильная трансляция данных между типами uint16_t -> uint8_t *.

Итак, вот код:

#define EEPROM_SPI   hspi1
#define EEPROM_READ  0x03  // Read from Memory Array

 /**
  * @brief  Reads a block of data from the EEPROM.
  * @param  pBuffer: pointer to the buffer that receives the data read from the EEPROM.
  * @param  ReadAddr: EEPROM's internal address to read from.
  * @param  NumByteToRead: number of bytes to read from the EEPROM.
  * @retval None
  */
uint8_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead) {
    /*!< Select the EEPROM: Chip Select low */
    EEPROM_LED_ON();
    EEPROM_CS_LOW();

    /*!< Send "Read from Memory" instruction and MSB of WriteAddr  */
    EEPROM_SendInstruction((uint8_t*)EEPROM_READ, 1);

    /*!< Send WriteAddr address byte to read from */
    EEPROM_SendInstruction((uint8_t*)ReadAddr, 2);

    if (HAL_SPI_Receive_DMA(&EEPROM_SPI, (uint8_t*)pBuffer, NumByteToRead) != HAL_OK) {
        Error_Handler();
    }

    /*!< Deselect the EEPROM: Chip Select high */
    EEPROM_CS_HIGH();
    EEPROM_LED_OFF();

    return 0;
}

void EEPROM_SendInstruction(uint8_t *instruction, uint8_t size) {
    while (EEPROM_SPI.State == HAL_SPI_STATE_RESET) {
        osDelay(1);
    }

    if (HAL_SPI_Transmit_DMA(&EEPROM_SPI, (uint8_t*)instruction, (uint16_t)size) != HAL_OK) {
        Error_Handler();
    }
}

Инициализация SPI:

static void MX_SPI1_Init(void) {
    hspi1.Instance = SPI1;
    hspi1.Init.Mode = SPI_MODE_MASTER;
    hspi1.Init.Direction = SPI_DIRECTION_2LINES;
    hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
    hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
    hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
    hspi1.Init.NSS = SPI_NSS_SOFT;
    hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
    hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
    hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
    hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
    hspi1.Init.CRCPolynomial = 7;

    if (HAL_SPI_Init(&hspi1) != HAL_OK) {
        Error_Handler();
    }
}

UPD1: Я сделал пакет, как сказал @Guillaume Michel, и он сработал: M95640 Чтение с адреса 0x81 Рабочий способ

UPD2 Я опубликовал библиотеку на Github, писал и читал данные полностью функциональны. Помощь приветствуется, чтобы просмотреть код и добавить некоторые новые функции.


person Bulkin    schedule 20.01.2017    source источник


Ответы (1)


Кажется, ваш код написан не для использования DMA, поэтому не используйте его. Попробуйте использовать HAL_SPI_Receive и HAL_SPI_Transmit, а не HAL_SPI_Receive_DMA и HAL_SPI_Transmit_DMA.

Полярность и фаза кажутся нормальными, но проверьте еще раз.

Я не уверен, что вы называете EEPROM_SendInstruction правильным. Попробуйте вместо этого:

uint8_t sEE_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t NumByteToRead) {

  uint8_t tmpBuf[2];

  /*!< Select the EEPROM: Chip Select low */
  EEPROM_LED_ON();
  EEPROM_CS_LOW();

  /*!< Send "Read from Memory" instruction and MSB of WriteAddr  */
  tmpBuf[0] = EEPROM_READ;
  EEPROM_SendInstruction(tmpBuf, 1);

  /*!< Send WriteAddr address byte to read from */
  tmpBuf[0] = (uint8_t)(ReadAddr<<8);
  tmpBuf[1] = (uint8_t)ReadAddr;
  EEPROM_SendInstruction(tmpBuf, 2);

  if (HAL_SPI_Receive_DMA(&EEPROM_SPI, (uint8_t*)pBuffer, NumByteToRead) != HAL_OK) {
      Error_Handler();
  }

  /*!< Deselect the EEPROM: Chip Select high */
  EEPROM_CS_HIGH();
  EEPROM_LED_OFF();

  return 0;
}
person Guillaume Michel    schedule 20.01.2017
comment
Да! Я уже сделал то же самое, и это решило проблему. Я скоро обновлю вопрос с изображением. Спасибо! - person Bulkin; 20.01.2017
comment
Ах. DMA работает, но пока я его отключил, так как там сложнее управлять линией CS - ее надо включать и выключать в прерываниях. Позже протестирую. - person Bulkin; 20.01.2017