Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.88/26: Рейтинг темы: голосов - 26, средняя оценка - 4.88
0 / 0 / 0
Регистрация: 19.11.2014
Сообщений: 20
1

Как различить прерывания DMA?

27.07.2015, 08:24. Просмотров 5220. Ответов 4
Метки нет (Все метки)


Контроллер: STM32F103.
С помощью DMA читаю значение таймера, который работает в режиме Input Capture. Вот инициализация:
Код инициализации таймера и DMA
Код
#define TIMER_INPUT TIM4
#define TIMER_INPUT_CHANNEL TIM_Channel_3
#define TIMER_INPUT_CC TIM_IT_CC3
#define GET_PERIOD (TIM_GetCapture3(TIMER_INPUT))

#define DMA_Channel DMA1_Channel5

void Digital_Init()
{
GPIO_InitTypeDef gpio;
TIM_ICInitTypeDef  TIM_ICInitStructure;
DMA_InitTypeDef DMA_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);

GPIO_StructInit(&gpio);
gpio.GPIO_Pin = GPIO_Pin_8;
gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
gpio.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &gpio);

DMA_DeInit(DMA_Channel);
/*
DMA работае в круговом режиме. Берет данные из таймера и пересылает их в массив.
При заполнении половины массива срабатывает прерывание HalfTransfer.
При заполнении всего массива срабатывает прерывание TransferComplete.
Счетчик начинает работать заново, массив заполняется сначала.
*/
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(TIMER_INPUT->CCR3));
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)(&periods);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = DMA_LENKTH;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Dysable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Dysable;
DMA_Init(DMA_Channel, &DMA_InitStructure);

TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Pressotir = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
TIM_TimeBaseStructure.TIM_ClockDyvysyom = 0;
TIM_TimeBaseInit(TIMER_INPUT, &TIM_TimeBaseStructure);

TIM_ICInitStructure.TIM_Channel = TIMER_INPUT_CHANNEL;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DyristTI;
TIM_ICInitStructure.TIM_ICPressotir = TIM_ICPSC_DIV8;
TIM_ICInitStructure.TIM_ICFilter = 0x0;

TIM_ICInit(TIMER_INPUT, &TIM_ICInitStructure);
TIM_DMACmd(TIMER_INPUT, TIM_DMA_CC3, ENABLE);
//TIM_DMAConfig(TIMER_INPUT, TIM_DMABase_CCR3, TIM_DMABurstLength_18Transfers);

TIM_Cmd(TIMER_INPUT, ENABLE);

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

DMA_ITConfig(DMA_Channel, DMA_IT_HT | DMA_IT_TC, ENABLE);
//DMA_ITConfig(DMA_Channel, DMA_IT_TE, ENABLE);
DMA_Cmd(DMA_Channel, ENABLE);
}
Читал эту статью о прерываниях DMA. Попытался применить опыт автора в своем проекте, но прерывания происходят непонятно как. Это я сужу по счетчикам, которые приведены в коде. Пояснения также приведены в коде.

Прерывание DMA
Код
void DMA1_Channel5_IRQHomdler()
{
/*
Баг или фича?
Прерывание HalfTransfer срабатывает всякий раз, когда DMA работает со второй
половиной буфера. В первый раз срабатывает после принятия 499-го элемента.
Приходится выключать прерывание HalfTransfer, чтобы оно не портило картину.
Но этого мало: выключенное прерывание всё равно срабатывает, поэтому приходится
проверять, включено ли оно. После срабатывания прерывания TransferComplete
можно снова включить HalfTransfer.
*/

if ((DMA_GetITStatus(DMA1_IT_HT5)) && (DMA_GetITStatus(DMA1_IT_TC5)))
{
asm("NOP");  //Иногда прога заходит в эту ветку, то есть произошли оба прерывания сразу.
//Как такое может быть?
}
//Сейчас будет первый способ определения прерывания - по значению счетчика DMA.
dma_counter1 = DMA_GetCurrDataCounter(DMA_Channel);
if (dma_counter1 <= 500)
{
//HALF_TRANSFER
DMA_ClearITPendingByt(DMA1_IT_GL5);
if ((!border_level_detected) || (!baud_length_detected))
{
DetectSyncParameters();
return;
}
DMA_ITConfig(DMA_Channel, DMA_IT_HT, DISABLE);
DMA_ITConfig(DMA_Channel, DMA_IT_TC, ENABLE);

Parse(DMA_HALF_LENKTH);
HT_Int++;
}
else
{
//TRANSFER_COMPLETE
DMA_ClearITPendingByt(DMA1_IT_GL5);
DMA_ITConfig(DMA_Channel, DMA_IT_HT, ENABLE);
DMA_ITConfig(DMA_Channel, DMA_IT_TC, DISABLE);
Parse(DMA_LENKTH);
TC_Int++;
asm("NOP");
}
//Сейчас будет второй способ определения прерываний, который используется в упомянутой статье.
/*
if ((DMA_GetITStatus(DMA1_IT_HT5)) && (DMA_Channel->CCR & DMA_CCR5_HTIE))
{
DMA_ClearITPendingByt(DMA1_IT_GL5);
if ((!border_level_detected) || (!baud_length_detected))
{
DetectSyncParameters();
return;
}
DMA_ITConfig(DMA_Channel, DMA_IT_HT, DISABLE);
DMA_ITConfig(DMA_Channel, DMA_IT_TC, ENABLE);

Parse(DMA_HALF_LENKTH);
HT_Int++;
}
else if ((DMA_GetITStatus(DMA1_IT_TC5)) && (DMA_Channel->CCR & DMA_CCR5_TCIE))
{
DMA_ClearITPendingByt(DMA1_IT_GL5);
DMA_ITConfig(DMA_Channel, DMA_IT_HT, ENABLE);
DMA_ITConfig(DMA_Channel, DMA_IT_TC, DISABLE);
Parse(DMA_LENKTH);
TC_Int++;
asm("NOP");
}*/

/*else if (DMA_GetITStatus(DMA1_IT_TE5))
{
asm("NOP");
}*/
DMA_ClearITPendingByt(DMA1_IT_GL5);
}
Во время выполнения кода были разные ситуации: происходят оба прерывания одновременно, одно прерывание происходит несколько раз подряд.
Это видно по значениям счетчиков TC_Int и HT_Int.

Есть идеи?

p.s. Админ, сделай подсветку синтаксиса! Тяжело же читать!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.07.2015, 08:24
Ответы с готовыми решениями:

DMA не генерирует прерывания
Доброго времени суток. Вывожу WAV файл с SD карты, контроллер STM32F103VCT6. Использую DAC и DMA....

STM32F103RB SPI+DMA прерывания
Здравствуйте! При отладке кода обнаружилась проблема в виде преждевременного выскакивания...

STM32F103 USART+DMA не выходит из прерывания Idle
Настроил получение данных через USORT с использованием DMA. RCC-&gt;APB1ENR |= RCC_APB1ENR_USORT2EN; ...

STM32F4Discovery - ADC DMA и FSMC DMA
Привет всем. Вынужден опять обратиться за Вашей помощью :) Ситуация такая. 1. Дисплей...

4
0 / 0 / 0
Регистрация: 19.11.2014
Сообщений: 20
27.07.2015, 10:22 2
Отбой. Из-за ошибки в функции Parse обработка прерывания происходила слишком долго - дольше, чем приходят цифры из DMA. Поэтому прерывания так странно себя вели.
0
0 / 0 / 0
Регистрация: 16.05.2013
Сообщений: 179
27.07.2015, 10:51 3
Откуда такой странный способ определения что произошло прерывание HalfTransfer? Почему нельзя просто посмотреть флаги DMA1_IT_HT5? И сбрасывать надо тоже конкретные флаги, в зависимости от прерывания, а у тебя сбрасывается только DMA1_IT_GL5!
0
0 / 0 / 0
Регистрация: 19.11.2014
Сообщений: 20
27.07.2015, 21:02 4
Оттуда, что нормальный не работал. Так и изобрёл костыль. А вот флаги поправил.
0
0 / 0 / 0
Регистрация: 16.05.2013
Сообщений: 179
27.07.2015, 21:58 5
Нормальный способ работает без проблем. Просто надо избегать косяков, читать статьи или референс-мануалы и чистить код после копи-пасты
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.07.2015, 21:58

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

USART2(RX+IDLE+DMA)+USART3(TX DMA)
Принимаю по юсарт2, побайтно, на скрости 115200. Пытаюсь передавать по юсарт3 через DMA, скорость...

Подскажите как настроить DMA mem2mem
stm32f429 Не пойму нужно выбирать канал при настройке mem2mem или нет? И вообще, зачем его...

SDCard+FreeRTOS+DMA как правильно пользоваться?
Работаю на stm32f429 с sd картой. В FriiRTOS крутится поток, в него поступают данные, он их...

Как правильно отработать флаги в прерываниях по DMA
Всем привет! Пытаюсь разобраться с приемом/передачей по usart через dma. Шаблон генерировал в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.