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

时间:2017-01-20 08:28:58

标签: stm32 spi eeprom

我正在尝试从ST EEPROM M95640-W

读取/写入数据

根据数据表,对于读操作,数据命令必须格式化为:

M95640-W Read operation

首先是8位指令“从存储器阵列读取”: 0x03(B00000011)

其次是16位地址。

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

地址0x0001(B00000001): M95640 Read from address 0x1

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

地址0x0081(B10000001): M95640 Read from address 0x81

所以我在代码中找不到错误,为什么它以错误的方式发送数据。除 0x03 外,它发送 0x20 命令。它发送 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 Read from address 0x81 Working way

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

1 个答案:

答案 0 :(得分:2)

您的代码似乎没有写入使用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;
}