在 STM32 中格式化数据以通过 HAL SPI 发送的正确方法是什么?

What is the correct way to format data to send by HAL SPI in STM32?

我正在尝试 read/write 来自 ST EEPROM M95640-W 的数据

根据数据表,读取操作数据命令的格式必须如下:

首先是8位指令"Read from Memory Array":0x03 (B00000011)

第二个是16位地址。

但是当我发送命令和数据时,我得到了这个:

地址 0x0001 (B00000001):

并且只是用镜像位检查数据位置

地址 0x0081 (B10000001):


所以我在我的代码中找不到错误,为什么它以不正确的方式发送数据。它发送 0x20 命令,除了 0x03。它发送 0x48 地址,除了 0x010x80 除了 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 说的那样做了数据包并且它有效:

UPD2 我在 Github 发布了库,写入和读取数据功能齐全。欢迎帮助查看代码并添加一些新功能。

您的代码似乎不是为使用 DMA 而编写的,所以不要使用它。尝试使用 HAL_SPI_ReceiveHAL_SPI_Transmit 而不是 HAL_SPI_Receive_DMAHAL_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;
}