Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DMA(UART+ADC) ARM
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
4th
Вечер добрый. Чисто в учебных целях было решено оцифровывать сигнал с ADC1, сохранять его в uint16_t переменной и в прерывании от DMA(ADC1) копировать результат в массив uint8_t mass[2] и запускать отправку по UART через тот же DMA. А в прерывании DMA(UART) запускать преобразование АЦП заново. И так по кругу...
В режиме отладки при включенных бряках на DMA1_Channel1_IRQHandler (АЦП) и DMA1_Channel1_IRQHandler (UART) этот результат достигается. Но при роботе в реальном времени (ну или без брейкпоинтов) происходит следующее:
  • из main запускается HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_buffer, sizeof(adc_buffer));
  • при завершении преобразования уходит в прерывание DMA1_Channel1_IRQHandler;
  • копирует данные из adc_buffer в uart_buffer[]; запускает посылку по UART: HAL_UART_Transmit_DMA(&huart2, uart_buffer, sizeof(uart_buffer));
  • и останавливает АЦП: HAL_ADC_Stop_DMA(&hadc1);
  • после этого он должен попасть в обработчик завершения передачи DMA1_Channel7_IRQHandler, но этого не происходит (но происходит только при пошаговой отладке)

В общем не могу понять что мешает ему работать как задумано.
Ниже куски кода, которые наверняка захотят увидеть:
Код
int main(void)
{

  HAL_Init();

  SystemClock_Config();
  
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_USART2_UART_Init();

  HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_buffer, sizeof(adc_buffer));

  while (1) {  }

}

void DMA1_Channel1_IRQHandler(void)
{
   HAL_DMA_IRQHandler(&hdma_adc1);

  uart_buffer[0]=adc_buffer>>8;
  uart_buffer[1]=adc_buffer;
  HAL_UART_Transmit_DMA(&huart2, uart_buffer, sizeof(uart_buffer));
  HAL_ADC_Stop_DMA(&hadc1);

}

void DMA1_Channel7_IRQHandler(void)
{
  
  HAL_DMA_IRQHandler(&hdma_usart2_tx);

HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_buffer, sizeof(adc_buffer));        //заходит сюда только в пошаговом режиме

}


Immortal_Buka
в RM написано, что есть "peripheral-to-peripheral transfers"
4th
Цитата(Immortal_Buka @ Jul 1 2016, 18:29) *
в RM написано, что есть "peripheral-to-peripheral transfers"

Предлагаете сразу через DMA копировать данные. Понимаю. Но это не совсем подходящее решение. Предполагается, что перед копированием в буфер UARTa, может выполнять работа с данными. Поэтому делал изначально в прерывании.
Это не решает задачу полностью, но все-равно спасибо.
4th
Найдено решение:
В обработчике прерывания DMA(UART) было добавлено:
  • проверку условия срабатывания прерывания: if( HAL_DMA_GetState(&hdma_usart2_tx)==HAL_DMA_STATE_READY) {...}
  • принудительную остановку передачи в DMA по UART - HAL_UART_DMAStop(&huart2);
  • запуск АЦП - HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_buffer, sizeof(adc_buffer));


Следует отметить что без принудительной остановки HAL_UART_DMAStop(&huart2) - отказывается работать.
Также следует отметить что условий срабатывания прерывания DMA(UART) уйма, точнее сказать на любое состояние DMA:
Код
typedef enum
{
  HAL_DMA_STATE_RESET             = 0x00,  /*!< DMA not yet initialized or disabled */
  HAL_DMA_STATE_READY             = 0x01,  /*!< DMA initialized and ready for use   */
  HAL_DMA_STATE_READY_HALF        = 0x11,  /*!< DMA Half process success            */
  HAL_DMA_STATE_BUSY              = 0x02,  /*!< DMA process is ongoing              */
  HAL_DMA_STATE_TIMEOUT           = 0x03,  /*!< DMA timeout state                   */
  HAL_DMA_STATE_ERROR             = 0x04,  /*!< DMA error state                     */
}HAL_DMA_StateTypeDef;


Поэтому в прерывании DMA(UART) следует выполнять проверку на причину возникновения прерывания.

Листинг основных кусков кода ниже:
Код
int main(void)
{

  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_USART2_UART_Init();

  HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_buffer, sizeof(adc_buffer));

   while (1)  {}

}

void DMA1_Channel1_IRQHandler(void)
{

  HAL_DMA_IRQHandler(&hdma_adc1);

  uart_buffer[0]=adc_buffer>>8;
  uart_buffer[1]=adc_buffer;
  HAL_UART_Transmit_DMA(&huart2, uart_buffer, sizeof(uart_buffer));
  HAL_ADC_Stop_DMA(&hadc1);

}

void DMA1_Channel7_IRQHandler(void)
{
  
  HAL_DMA_IRQHandler(&hdma_usart2_tx);
  if( HAL_DMA_GetState(&hdma_usart2_tx)==HAL_DMA_STATE_READY){
      HAL_UART_DMAStop(&huart2);
      HAL_ADC_Start_DMA(&hadc1, (uint32_t *) &adc_buffer, sizeof(adc_buffer));        
  }
}


Думаю такое решение будет кому-то полезным tongue.gif
Lost_Viking
у тебя, скорее всего, просто не успевали отправиться данные. ацп, наверняка, шпарил на всю катушку, быстрее, чем пересылка usart
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.