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

Данные с порта в память(DMA)

День добрый
Есть внешний параллельный АЦП, который я тактирую шимом одного из таймеров(STM32F4), вручную забирая данные с порта к которому подключен АЦП.
Возникло желание использовать для этих целей DMA.

ШИМ настроен на:  TIM4 - Channel 4 - PWM Generation CH4


Добавил DMA
Событие: TIM4_UP
Направление передачи: Периферия - Память
Инкрементируется адрес памяти

 

Собственно инициализация в кубе:

__HAL_RCC_GPIOB_CLK_ENABLE();
/**TIM4 GPIO Configuration    
PB9     ------> TIM4_CH4 
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF2_TIM4;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
    
__HAL_RCC_TIM4_CLK_ENABLE();
/* TIM4 DMA Init */
/* TIM4_UP Init */
hdma_tim4_up.Instance = DMA1_Stream6;
hdma_tim4_up.Init.Channel = DMA_CHANNEL_2;
hdma_tim4_up.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_tim4_up.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_tim4_up.Init.MemInc = DMA_MINC_ENABLE;
hdma_tim4_up.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_tim4_up.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_tim4_up.Init.Mode = DMA_NORMAL;
hdma_tim4_up.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_tim4_up.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_tim4_up) != HAL_OK)
{
  Error_Handler();
}

__HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_UPDATE],hdma_tim4_up);

Запускаю ШИМ, запускаю DMA:

HAL_TIM_PWM_Start(&htim4, TIM_CHANNEL_4);
HAL_DMA_Start(&hdma_tim4_up, (uint32_t)&PORT_ADC->IDR, &TestDMA[0], 100);

На выходе имею пустой массив

Опирался на AN4666, но что то делаю не так

Укажите пожалуйста на ошибку

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


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

А не заменить-ли Вам DMA1 на DMA2 ?  По-моему, GPIO находятся на шине AHB1, которая соединена с DMA2.

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


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

Да вы правы, мне уже подсказали это. И я заменил DMA1 на DMA2, но это не помогло.

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


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

В 09.09.2019 в 12:27, Nosaer сказал:

На выходе имею пустой массив

Опирался на AN4666, но что то делаю не так

Укажите пожалуйста на ошибку

Ошибки у вас нет, но есть недодел -   нет тактирования и разрешения прерываний для DMA.

Тактирование для вашего DMA1_Stream6 добавляется так:

  __HAL_RCC_DMA1_CLK_ENABLE();

иначе он на месте стоит и ничего не делает.

Разрешить ему прерывания:

  HAL_NVIC_SetPriority(DMA1_Stream6_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream6_IRQn);

И хандлер для их приема сделать:

void DMA1_Stream6_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_tim4_up);
}

Вот вроде бы и всё.

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


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

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

Ошибки у вас нет, но есть недодел -   нет тактирования и разрешения прерываний для DMA.

Если это делалось в кубе и стоят галочки, то он включает это всё в MX_DMA_Init()

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

И хандлер для их приема сделать:

void DMA1_Stream6_IRQHandler(void)
{
  HAL_DMA_IRQHandler(&hdma_tim4_up);
}

По идеологии куба  хэндлер HAL_DMA_IRQHandler() обычно уже есть(если галки стоят) и он вызывает колбэки, которые надо описать в main :

XferCpltCallback( struct __DMA_HandleTypeDef * hdma)

XferHalfCpltCallback( struct __DMA_HandleTypeDef * hdma)

XferM1CpltCallback( struct __DMA_HandleTypeDef * hdma)

XferM1HalfCpltCallbac)( struct __DMA_HandleTypeDef * hdma)

XferErrorCallback( struct __DMA_HandleTypeDef * hdma)

XferAbortCallback( struct __DMA_HandleTypeDef * hdma)

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


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

Xenia, тактирование и запуск прерываний прописан в MX_DMA_INIT, как и написал HardEgor.

static void MX_DMA_Init(void)
{
  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA2_Stream5_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
}

Хандлер для их приема тоже автоматически сгенерирован кубом.

П.С. Как я уже писал выше, заменил DMA1 на DMA2.

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


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

3 часа назад, Nosaer сказал:

П.С. Как я уже писал выше, заменил DMA1 на DMA2.

А DMA вручную менялся или как положено в кубе?

И вообще, что за контроллер?

GPIO_PIN_9 точно выдает импульсы?

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


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

DMA менял в кубе.

Контроллер STM32F407

С шимом проблем нет, в этом плане все работает.

Пробовал считывать все порты, во всех случаях вижу только 0xFF.

У меня больше подозрений на запуск:

HAL_DMA_Start(&hdma_tim4_up, (uint32_t)&PORT_ADC->IDR, &TestDMA[0], 100);

Возможно не так запускаю или не то использую. Пробовал так же 

HAL_DMA_Start_IT(&hdma_tim4_up, (uint32_t)&PORT_ADC->IDR, &TestDMA[0], 100);

Результата тоже не дало

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


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

Я в кубе не волоку и может глупость скажу, а не может быть быть так, что ПДП запускается и отрабатывает всю пересылку сразу, не дожидаясь сигнала запуска пересылки, пока ваше АЦП еще не успело выставить данные?

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


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

Я пока не использую АЦП. А просто пытаюсь считать любой порт, где заведомо подал сигналы на некоторые выводы.

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


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

Тогда смотрите внутрь __HAL_LINKDMA() и HAL_DMA_Start_IT(), те ли параметры передаются  - в одну hdma_tim4_up,  а в другую указатель.

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


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

В 13.09.2019 в 07:39, HardEgor сказал:

Тогда смотрите внутрь __HAL_LINKDMA() и HAL_DMA_Start_IT(), те ли параметры передаются  - в одну hdma_tim4_up,  а в другую указатель.

Действительно, со вторым параметром __HAL_LINKDMA что-то явно неладно:

__HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_UPDATE],hdma_tim4_up);

А за HAL_DMA_Start_IT() можно не волноваться, т.к. это - функция, и сама способна проверять типы своих параметров, тогда как __HAL_LINKDMA - макрос.

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


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

А у таймера есть разрешение генерировать события для DMA?

Бит UDE в регистре DIER таймера должен быть установлен в единицу.

Переключать DMA на DMA2 не нужно. Событие TIM4_UP привязано к Stream6 Cnannel 2 DMA1. На DMA2 оно просто работать не будет.

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

DMA2. Например TIM1 или TIM8.

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


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

Всем большое спасибо. Проблема была в том, что при инициализации не выставлялся бит UDE в DIER.

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


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

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

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

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

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

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

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

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

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

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