Nosaer 0 Posted September 9, 2019 · Report post День добрый Есть внешний параллельный АЦП, который я тактирую шимом одного из таймеров(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, но что то делаю не так Укажите пожалуйста на ошибку Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Aleksandr Baranov 0 Posted September 10, 2019 · Report post А не заменить-ли Вам DMA1 на DMA2 ? По-моему, GPIO находятся на шине AHB1, которая соединена с DMA2. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Nosaer 0 Posted September 11, 2019 · Report post Да вы правы, мне уже подсказали это. И я заменил DMA1 на DMA2, но это не помогло. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Xenia 0 Posted September 11, 2019 · Report post В 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); } Вот вроде бы и всё. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
HardEgor 0 Posted September 11, 2019 · Report post 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) Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Nosaer 0 Posted September 11, 2019 · Report post 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. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
HardEgor 0 Posted September 11, 2019 · Report post 3 часа назад, Nosaer сказал: П.С. Как я уже писал выше, заменил DMA1 на DMA2. А DMA вручную менялся или как положено в кубе? И вообще, что за контроллер? GPIO_PIN_9 точно выдает импульсы? Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Nosaer 0 Posted September 12, 2019 · Report post 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); Результата тоже не дало Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Сергей Борщ 1 Posted September 12, 2019 · Report post Я в кубе не волоку и может глупость скажу, а не может быть быть так, что ПДП запускается и отрабатывает всю пересылку сразу, не дожидаясь сигнала запуска пересылки, пока ваше АЦП еще не успело выставить данные? Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Nosaer 0 Posted September 13, 2019 · Report post Я пока не использую АЦП. А просто пытаюсь считать любой порт, где заведомо подал сигналы на некоторые выводы. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
HardEgor 0 Posted September 13, 2019 · Report post Тогда смотрите внутрь __HAL_LINKDMA() и HAL_DMA_Start_IT(), те ли параметры передаются - в одну hdma_tim4_up, а в другую указатель. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Xenia 0 Posted September 14, 2019 · Report post В 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 - макрос. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Wasserati 0 Posted September 15, 2019 · Report post А у таймера есть разрешение генерировать события для DMA? Бит UDE в регистре DIER таймера должен быть установлен в единицу. Переключать DMA на DMA2 не нужно. Событие TIM4_UP привязано к Stream6 Cnannel 2 DMA1. На DMA2 оно просто работать не будет. Если так нужно DMA2 то стоит взять другой таймер, который может генерировать события именно для DMA2. Например TIM1 или TIM8. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...
Nosaer 0 Posted September 26, 2019 · Report post Всем большое спасибо. Проблема была в том, что при инициализации не выставлялся бит UDE в DIER. Quote Ответить с цитированием Share this post Link to post Share on other sites More sharing options...