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

stm32 перевод команд HAL на cmsis или на LL

Для интерфейсов как SPI, отправка байтов по DMA происходит не по таймеру, а по запросу от самого модуля SPI, по событию TXE, и все байты в пакете идут без разрывов:

 

Снимок экрана 2024-07-10 195515.jpg

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


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

On 7/10/2024 at 4:56 PM, EdgeAligned said:

отправка байтов по DMA происходит не по таймеру

А отправка пакетов по DMA может по таймеру происходить ?

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


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

Косвенно. То есть, методом программного запуска канала. Но в таком случае прерывание TCIF от DMA всё-таки лучше использовать, потому что в случае дисплея время передачи всего пакета может быть значительным

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


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

В 10.07.2024 в 15:38, Andrey190 сказал:
  SPI1->CR2 &= ~SPI_CR2_TXDMAEN;
  DMA2_Stream3->CR &= ~DMA_SxCR_EN;
  DMA2->LIFCR = DMA_LIFCR_CTCIF3 | DMA_LIFCR_CHTIF3 | DMA_LIFCR_CTEIF3 | DMA_LIFCR_CDMEIF3;
  DMA2_Stream3->NDTR = 48;
  DMA2_Stream3->M0AR = (uint32_t) &buf[(uint8_t)i][0];
  DMA2_Stream3->PAR  = (uint32_t)(&SPI1->DR);
  DMA2_Stream3->CR |= DMA_SxCR_EN;
  SPI1->CR2 |= SPI_CR2_TXDMAEN;

прерывания от DMA не использую. отправка по таймеру

Это какой контроллер? А каким образом таймер может участвовать в отправке.SPI_DMA?

У меня есть библиотека Хал для ST7735  DMA запускаю полный 0 .На регистрах запускаю -наложение картинок происходит.

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


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

11 часов назад, dimir сказал:

Это какой контроллер? А каким образом таймер может участвовать в отправке.SPI_DMA?

У меня есть библиотека Хал для ST7735  DMA запускаю полный 0 .На регистрах запускаю -наложение картинок происходит.

STM32F401. отправка данных начинается в прерывании от таймера, запуская указанный выше код (не аппаратный запуск).

в моем случае, весь буфер гарантированно будет выдан раньше, чем сработает таймер - поэтому прерывания от DMA не нужны.

сначала идет настройка DMA и SPI - сгенерировано в кубе, с кодом даже не разбирался, просто настроил по своей схеме.

 
static void MX_DMA_Init(void)
{
  /* Init with LL driver */
  /* DMA controller clock enable */
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);
...............
static void MX_SPI1_Init(void)
{
  LL_SPI_InitTypeDef SPI_InitStruct = {0};
.....................

 

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


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

Для случая с отправкой графических данных в дисплей, такой как ST7735, длительность передачи может достигать десятков миллисекунд, что отрицательно скажется на производительности в показанном примере. Соппсна, нет никаких проблем в том, чтобы использовать прерывание по завершению передачи DMA, TCIF. Да, конечно нужно иметь некоторые знания, приложить усилия написать несколько дополнительных строчек. Ну а как вы хотели то?

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


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

В 11.07.2024 в 08:47, Andrey190 сказал:

STM32F401. отправка данных начинается в прерывании от таймера, запуская указанный выше код (не аппаратный запуск).

в моем случае, весь буфер гарантированно будет выдан раньше, чем сработает таймер - поэтому прерывания от DMA не нужны.

сначала идет настройка DMA и SPI - сгенерировано в кубе, с кодом даже не разбирался, просто настроил по своей схеме.

 
static void MX_DMA_Init(void)
{
  /* Init with LL driver */
  /* DMA controller clock enable */
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);
...............
static void MX_SPI1_Init(void)
{
  LL_SPI_InitTypeDef SPI_InitStruct = {0};
.....................

 

Запустил я в прерывании по ДМА.Я понимаю как Запустить прерывание по ДМА используя флаг и внешнее прерывание и прерывание по таймеру.Таким же образом можно сделать  аппаратно-программную задержку для дисплея .

Да и проблема по ДМА -не было флага 

LL_DMA_ClearFlag_TC2(DMA2)

в обработчике прерывания.

И по моему вы ни чего не показали.А вот мой вариант реальнее.Я на avr правда сделал 4 канальную герлянду ШИМ эфффектами с аппаратно- программной задержкой.

Да и вы мне не обязаны показывать.Но мой вариант лучше.И сын ошибок трудных и гений парадоксов друг-учёба всю жизнь ежеминутно и ежесекундно.

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


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

18 минут назад, dimir сказал:

Но мой вариант лучше.

Ничего лучше я сегодня на форумах уже не прочту :)))

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


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

23 минуты назад, dimir сказал:

И по моему вы ни чего не показали.

я же написал - там нагенерил куб. под мой проект. что нагенерил - я не разбирался даже. но если поможет, пожалуйста.

Спойлер
/**
  * @brief SPI1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI1_Init(void)
{

  /* USER CODE BEGIN SPI1_Init 0 */

  /* USER CODE END SPI1_Init 0 */

  LL_SPI_InitTypeDef SPI_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);

  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_GPIOA);
  /**SPI1 GPIO Configuration
  PA5   ------> SPI1_SCK
  PA7   ------> SPI1_MOSI
  */
  GPIO_InitStruct.Pin = LL_GPIO_PIN_5|LL_GPIO_PIN_7;
  GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
  GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
  GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
  GPIO_InitStruct.Alternate = LL_GPIO_AF_5;
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* SPI1 DMA Init */

  /* SPI1_TX Init */
  LL_DMA_SetChannelSelection(DMA2, LL_DMA_STREAM_3, LL_DMA_CHANNEL_3);

  LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_3, LL_DMA_DIRECTION_MEMORY_TO_PERIPH);

  LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_3, LL_DMA_PRIORITY_MEDIUM);

  LL_DMA_SetMode(DMA2, LL_DMA_STREAM_3, LL_DMA_MODE_NORMAL);

  LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_3, LL_DMA_PERIPH_NOINCREMENT);

  LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_3, LL_DMA_MEMORY_INCREMENT);

  LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_3, LL_DMA_PDATAALIGN_HALFWORD);

  LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_3, LL_DMA_MDATAALIGN_HALFWORD);

  LL_DMA_DisableFifoMode(DMA2, LL_DMA_STREAM_3);

  /* USER CODE BEGIN SPI1_Init 1 */

  /* USER CODE END SPI1_Init 1 */
  /* SPI1 parameter configuration*/
  SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
  SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
  SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_16BIT;
  SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
  SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
  SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
  SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV8;
  SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
  SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
  SPI_InitStruct.CRCPoly = 10;
  LL_SPI_Init(SPI1, &SPI_InitStruct);
  LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
  /* USER CODE BEGIN SPI1_Init 2 */

  /* USER CODE END SPI1_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* Init with LL driver */
  /* DMA controller clock enable */
  LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA2);

  /* Configure DMA request MEMTOMEM_DMA2_Stream0 */

  /* Select channel */
  LL_DMA_SetChannelSelection(DMA2, LL_DMA_STREAM_0, LL_DMA_CHANNEL_0);

  /* Set transfer direction */
  LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_0, LL_DMA_DIRECTION_MEMORY_TO_MEMORY);

  /* Set priority level */
  LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_0, LL_DMA_PRIORITY_LOW);

  /* Set DMA mode */
  LL_DMA_SetMode(DMA2, LL_DMA_STREAM_0, LL_DMA_MODE_NORMAL);

  /* Set peripheral increment mode */
  LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_0, LL_DMA_PERIPH_INCREMENT);

  /* Set memory increment mode */
  LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_0, LL_DMA_MEMORY_INCREMENT);

  /* Set peripheral data width */
  LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_0, LL_DMA_PDATAALIGN_HALFWORD);

  /* Set memory data width */
  LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_0, LL_DMA_MDATAALIGN_HALFWORD);

  /* Enable FIFO mode */
  LL_DMA_EnableFifoMode(DMA2, LL_DMA_STREAM_0);

  /* Set FIFO threshold */
  LL_DMA_SetFIFOThreshold(DMA2, LL_DMA_STREAM_0, LL_DMA_FIFOTHRESHOLD_FULL);

  /* Set memory burst size */
  LL_DMA_SetMemoryBurstxfer(DMA2, LL_DMA_STREAM_0, LL_DMA_MBURST_INC4);

  /* Set peripheral burst size */
  LL_DMA_SetPeriphBurstxfer(DMA2, LL_DMA_STREAM_0, LL_DMA_PBURST_INC4);

  /* Configure DMA request MEMTOMEM_DMA2_Stream1 */

  /* Select channel */
  LL_DMA_SetChannelSelection(DMA2, LL_DMA_STREAM_1, LL_DMA_CHANNEL_0);

  /* Set transfer direction */
  LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_1, LL_DMA_DIRECTION_MEMORY_TO_MEMORY);

  /* Set priority level */
  LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_1, LL_DMA_PRIORITY_LOW);

  /* Set DMA mode */
  LL_DMA_SetMode(DMA2, LL_DMA_STREAM_1, LL_DMA_MODE_NORMAL);

  /* Set peripheral increment mode */
  LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_1, LL_DMA_PERIPH_INCREMENT);

  /* Set memory increment mode */
  LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_1, LL_DMA_MEMORY_INCREMENT);

  /* Set peripheral data width */
  LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_1, LL_DMA_PDATAALIGN_HALFWORD);

  /* Set memory data width */
  LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_1, LL_DMA_MDATAALIGN_HALFWORD);

  /* Enable FIFO mode */
  LL_DMA_EnableFifoMode(DMA2, LL_DMA_STREAM_1);

  /* Set FIFO threshold */
  LL_DMA_SetFIFOThreshold(DMA2, LL_DMA_STREAM_1, LL_DMA_FIFOTHRESHOLD_FULL);

  /* Set memory burst size */
  LL_DMA_SetMemoryBurstxfer(DMA2, LL_DMA_STREAM_1, LL_DMA_MBURST_INC4);

  /* Set peripheral burst size */
  LL_DMA_SetPeriphBurstxfer(DMA2, LL_DMA_STREAM_1, LL_DMA_PBURST_INC4);

  /* Configure DMA request MEMTOMEM_DMA2_Stream2 */

  /* Select channel */
  LL_DMA_SetChannelSelection(DMA2, LL_DMA_STREAM_2, LL_DMA_CHANNEL_0);

  /* Set transfer direction */
  LL_DMA_SetDataTransferDirection(DMA2, LL_DMA_STREAM_2, LL_DMA_DIRECTION_MEMORY_TO_MEMORY);

  /* Set priority level */
  LL_DMA_SetStreamPriorityLevel(DMA2, LL_DMA_STREAM_2, LL_DMA_PRIORITY_LOW);

  /* Set DMA mode */
  LL_DMA_SetMode(DMA2, LL_DMA_STREAM_2, LL_DMA_MODE_NORMAL);

  /* Set peripheral increment mode */
  LL_DMA_SetPeriphIncMode(DMA2, LL_DMA_STREAM_2, LL_DMA_PERIPH_INCREMENT);

  /* Set memory increment mode */
  LL_DMA_SetMemoryIncMode(DMA2, LL_DMA_STREAM_2, LL_DMA_MEMORY_INCREMENT);

  /* Set peripheral data width */
  LL_DMA_SetPeriphSize(DMA2, LL_DMA_STREAM_2, LL_DMA_PDATAALIGN_HALFWORD);

  /* Set memory data width */
  LL_DMA_SetMemorySize(DMA2, LL_DMA_STREAM_2, LL_DMA_MDATAALIGN_HALFWORD);

  /* Enable FIFO mode */
  LL_DMA_EnableFifoMode(DMA2, LL_DMA_STREAM_2);

  /* Set FIFO threshold */
  LL_DMA_SetFIFOThreshold(DMA2, LL_DMA_STREAM_2, LL_DMA_FIFOTHRESHOLD_FULL);

  /* Set memory burst size */
  LL_DMA_SetMemoryBurstxfer(DMA2, LL_DMA_STREAM_2, LL_DMA_MBURST_INC4);

  /* Set peripheral burst size */
  LL_DMA_SetPeriphBurstxfer(DMA2, LL_DMA_STREAM_2, LL_DMA_PBURST_INC4);

  /* DMA interrupt init */
  /* DMA2_Stream3_IRQn interrupt configuration */
  NVIC_SetPriority(DMA2_Stream3_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),0, 0));
  NVIC_EnableIRQ(DMA2_Stream3_IRQn);

}

 

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


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

5 часов назад, Andrey190 сказал:

я не разбирался даже

Эх, хотел бы я тоже так - не разбираться ни в чем 🙂 Но вот ведь беда - разбираюсь же. Как теперь научиться не разбираться? Научите?

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


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

1 час назад, EdgeAligned сказал:

Эх, хотел бы я тоже так - не разбираться ни в чем 🙂 Но вот ведь беда - разбираюсь же. Как теперь научиться не разбираться? Научите?

легко. проект - часы себе на стол. хобби так сказать. зависли - питание выкл/вкл (несколько месяцев после разработки пока не пришлось перезапускать). p.s. халокуб только для начальной инициализации... 

коммерческий проект - через чтение мануалов, без халокубов и прочих генераторов кодов.

20240712_150358.jpg

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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