STM32 SPI数据反向发送方式

STM32 SPI data is sent the reverse way

我一直在尝试使用 SPI 向外部 EEPROM 写入数据,但结果喜忧参半。数据确实被移出,但以相反的方式移出。 EEPROM 需要一个起始位,然后是一个操作码,它本质上是一个用于读取、写入和擦除的 2 位代码。本质上,起始位和操作码合并为一个字节。我正在创建一个 32 位 unsigned int,然后将值移位到其中。当我传输这些时,我看到首先看到的是实际数据,然后是 SB+操作码,然后是内存地址。我如何反转它以首先查看操作码,然后是内存地址,然后是实际数据。如下图所示,数据为BCDE,SB+操作码为07,内存地址为3F。正确的顺序应该是 07、3F 然后是 BCDE(我想!)。

代码如下:

uint8_t mem_addr = 0x3F;
uint16_t data = 0xBCDE;
uint32_t write_package = (ERASE << 24 | mem_addr << 16 | data);

while (1)
{

/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
  HAL_SPI_Transmit(&hspi1, &write_package, 2, HAL_MAX_DELAY);
  HAL_Delay(10);

}
/* USER CODE END 3 */

您将信息打包成一个 32 位整数,在代码的第 3 行,您可以决定将哪些数据位放置在字中的位置。要更改顺序,您可以将行替换为:

uint32_t write_package = ((data << 16) | (mem_addr << 8) | (ERASE));

也就是将data左移16位到字的最高16位,将mem_addr上移8位进行或运算,然后加上ERASE 在最低有效位。

你的问题是 Endianness.

默认STM32使用little edian所以uint32_t的最低字节存储在第一个地址。

如果我是对的,这就是您使用的传输函数的声明:

HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)

它需要一个指向 uint8_t 的指针作为数据(而不是 uint32_t),因此如果您编译代码,您应该至少得到一个警告。

如果您想编写与使用的字节序无关的代码,您应该将数据存储到一个数组而不是一个 "big" 变量中。

uint8_t write_package[4];

write_package[0] = ERASE;
write_package[1] = mem_addr;
write_package[2] = (data >> 8) & 0xFF;
write_package[3] = (data & 0xFF);

您的 SPI 接口似乎设置为一次处理 16 位半字。因此,将要发送的数据也分解为 16 位半字是有意义的。这将负责排序。

uint8_t mem_addr = 0x3F;
uint16_t data = 0xBCDE;
uint16_t write_package[2] = {
    (ERASE << 8) | mem_addr,
    data
};

HAL_SPI_Transmit(&hspi1, (uint8_t *)write_package, 2, HAL_MAX_DELAY);

编辑

添加了显式转换。如评论中所述,如果没有显式转换,它不会编译为 C++ 代码,并会导致一些警告作为 C 代码。