Перейти к содержанию
    

STM32: Свое тактирование SPI

Подскажите пож-та, пытаюсь тактировать SPI по своему алгоритму:

1. настроил на таймере Output Compare на 1 секунду и режимом Toggle on match, на выходе получаю секундный меандр

2. соединил выход таймера с пином тактирования SPI, по идее теперь SPI должен сдвигать свой регистр с частотой в 1 секунду

3. пытаюсь передать 1 бит 01010100 в SPI и жду на выходе мигание светодиодом 3 раза с задержкой 1 секунда

----- проблема -------

1. диод мигает не с секундной задержкой, о несколько дольше.

2. передача повторяется циклично, т.е. передачей одного байта дело не заканчивается, он снова и снова передается, или просто зависает на MISO

 

Иллюстрация настроек и работы

spi.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

----- проблема -------

1. диод мигает не с секундной задержкой, о несколько дольше.

Светодиод будет (должен) мигать с периодом 4 секунды, 2 секунды светится, 2 секунды нет, так 3 раза. Затем пауза будет дольше, так как нулей в младших битах больше.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Светодиод будет (должен) мигать с периодом 4 секунды, 2 секунды светится, 2 секунды нет, так 3 раза. Затем пауза будет дольше, так как нулей в младших битах больше.

Спасибо! Понял, принял, согласен.

Скажите, HAL_SPI_Transmit после успешной передачи должен очищает SPI->DR? у меня сейчас передаваемое значение зависает в SPI.

На другом форуме ребята говорили, что на некоторых камнях HAL_SPI_Transmit работает не корректно, рекомендовали пользоваться HAL_SPI_TransmitReceive.

Что нужно чтобы передать по SPI значение один раз?

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Скажите, HAL_SPI_Transmit после успешной передачи должен очищает SPI->DR? у меня сейчас передаваемое значение зависает в SPI.

Смотря что понимать под "очисткой" ...

Это не участок памяти, а функциональный регистр периферии, поэтому его поведение отличается от обычной памяти.

То, что вы в него записываете - прыгает в сдвиговый регистр и начинает передаваться на линию MOSI, при этом одновременно, такт за тактом, другим сдвиговым регистром, считывается значение с линии MISO. После того, как этот цикл завершен - считанное значение можно считать в том же самом регистре SPI->DR.

Перед записью в SPI->DR нужно убедиться, что он пуст, но НЕ в том смысле, что там ноль, а в том смысле, что предыдущая запись ушла в сдвиговый регистр. Для этого служит регистр статуса SPI->SR (бит TXE, Tx Empty).

Точно также - перед чтением нужно убедиться, что там что-то есть, то есть тактовый цикл на шине (8 или 16 тактов, как настроите) завершен. Для этого смотрим в тот же SPI->SR (бит RXNE, RX Not Empty).

Что нужно чтобы передать по SPI значение один раз?

Убедиться, что передающий буфер пуст и записать в него один раз значение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, не факт, что там тот же самый регистр. Их может быть два - в один можно только записывать, из другого - только читать. А адрес - да, тот же самый

 

считанное значение можно считать в том же самом регистре SPI->DR.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Парни, вижу что вы на форуме с опытом, просветите по созвучной с SPI темой (чтобы не плодить тем) - DMA в Periph и HAL, а именно не нашел в HAL аналога атрибуту DMA_InitStructure.DMA_Memory0BaseAddr, т.е. собственно DMA_Memory0BaseAddr задает ссылку на memory переменную и после разрешения DMA и SPI осуществляется передача (в примере ниже цикличная) данных из переменной в SPI->DR.

В HAL такой конкретной линковки с переменной нет, я правильно понимаю, что функцию линковки можно считать HAL_SPI_Transmit_DMA(&hspiX, (uint8_t *)&buffer, sizeof(buffer))?

Или дайте наводку на аналог DMA_PeripheralBaseAddr в HAL.

Спасибо.

 

в Periph:

DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.с = (uint_t)&buffer;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
...
пуск передачи
DMA_Cmd(DMA2_StreamX,ENABLE);
SPI_Cmd(SPIX, ENABLE);

 

в HAL:

...
hdma_spiX_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spiX_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spiX_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spiX_tx.Init.Mode = DMA_CIRCULAR;
...
HAL_DMA_Init(&hdma_spi1_tx);
// линк
__HAL_LINKDMA(hspi,hdmatx,hdma_spiX_tx);
...
пуск передачи
__HAL_DMA_ENABLE(&hdma_spiX_tx);
__HAL_SPI_ENABLE(&hspiX);

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

На счет первого поста автора, как мне думается дело не в DR регистре SPI, а все таки в том что тактирование продолжается, попробуйте в таймер отключить после передачи 8 бит. И еще, впервые встречаю такую реализацию SPI, что в дальнейшем вы с ним хотите делать?

Изменено пользователем RuSTA

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...