Данные 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);