Данные SPI STM32 отправляются в обратном направлении

Я экспериментировал с записью во внешнюю EEPROM с использованием SPI, и у меня был смешанный успех. Данные смещаются, но в обратном порядке. ЭСППЗУ требуется стартовый бит, а затем код операции, который по сути является 2-битным кодом для чтения, записи и стирания. По сути, стартовый бит и код операции объединены в один байт. Я создаю 32-битное целое число без знака, а затем сдвигаю бит в нем значения. Когда я передаю их, я вижу, что сначала отображаются фактические данные, а затем код операции 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 */

3 ответа

Решение

Похоже, что ваш интерфейс 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.

Вы упаковываете свою информацию в 32-разрядное целое число, в строке 3 своего кода вы решаете, какие биты данных размещены в каком месте слова. Для изменения порядка вы можете заменить строку на:

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

Это смещение data 16 бит осталось в старших 16 битах слова, сдвигаясь mem_addr до 8 битов и / или его, а затем добавление ERASE в наименее значимых битах.

Ваша проблема - это Endianness.

По умолчанию STM32 использует маленький edian, поэтому младший байт uint32_t сохраняется на первом адресе.

Если я прав, это объявление, если вы используете функцию передачи:

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

Требуется указатель на uint8_t в качестве данных (а не на uint32_t), поэтому вы должны получить хотя бы предупреждение, если компилируете свой код.

Если вы хотите написать код, который не зависит от используемого порядка байтов, вы должны хранить ваши данные в массиве вместо одной "большой" переменной.

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);
Другие вопросы по тегам