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