【问题标题】:What is the correct way to format data to send by HAL SPI in STM32?在STM32中格式化数据以通过HAL SPI发送的正确方法是什么?
【发布时间】:2017-06-05 04:13:42
【问题描述】:

我正在尝试从 ST EEPROM M95640-W 读取/写入数据

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

首先是 8 位指令“从内存阵列读取”: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 发布了库,写入和读取数据功能齐全。欢迎帮助查看代码并添加一些新功能。

【问题讨论】:

    标签: stm32 spi eeprom


    【解决方案1】:

    您的代码似乎不是为使用 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;
    }
    

    【讨论】:

    • 是的!我已经做了同样的事情,这解决了这个问题。我会尽快用图像更新问题。谢谢!
    • 啊。 DMA 正在工作,但现在我把它关掉了,因为它更难控制 CS 线 - 它必须在中断中打开和关闭。我稍后会测试它。
    猜你喜欢
    • 2018-02-01
    • 2021-08-27
    • 2022-01-20
    • 1970-01-01
    • 2018-01-09
    • 2022-10-29
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多