реклама на сайте
подробности

 
 
> Опять таймер, ADC и DMA на STM32F4 (Discovery), Заезженная уже, наверное, тема.
hd44780
сообщение Feb 12 2013, 07:53
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 202
Регистрация: 26-08-05
Из: Донецк, ДНР
Пользователь №: 7 980



Привет всем.
Надо запускать ADC1 по таймеру, забирать результаты через DMA с получением какого-нибудь прерывания по заполнению буфера.

По мотивам доки и форумов написал:
CODE

volatile uint16_t adcBuffer[4096]; // <- the results are here

........................................

// ADC1 CH0 - PA0
void adcInit ( void )
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
DMA_InitTypeDef DMA_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;

// Enable ADC3, DMA2 and GPIO clocks
RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA, ENABLE );
RCC_APB2PeriphClockCmd ( RCC_APB2Periph_ADC1, ENABLE );

// DMA2 Stream0 channel0 configuration
DMA_DeInit(DMA2_Stream0);
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(ADC1->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&adcBuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 4096;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
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_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init ( DMA2_Stream0, &DMA_InitStructure );
DMA_Cmd ( DMA2_Stream0, ENABLE );

// Enable the DMA Stream IRQ Channel
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init ( &NVIC_InitStructure );

DMA_ITConfig ( DMA2_Stream0, DMA_IT_HT | DMA_IT_TC, ENABLE );

// Configure ADC1 Channel1 (PA0) pin as analog input
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init ( GPIOA, &GPIO_InitStructure );

// ADC Common Init
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit ( &ADC_CommonInitStructure );

// ADC1 Init
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T8_TRGO;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 0;
ADC_Init ( ADC1, &ADC_InitStructure );

// ADC1 regular channel1 configuration
ADC_RegularChannelConfig ( ADC1, ADC_Channel_0, 1, ADC_SampleTime_3Cycles );

// Enable DMA request after last transfer (Single-ADC mode)
ADC_DMARequestAfterLastTransferCmd ( ADC1, ENABLE );

// Enable ADC1 DMA
ADC_DMACmd ( ADC1, ENABLE );

// Enable ADC1
ADC_Cmd ( ADC1, ENABLE );

// Инициализация TIM8, запускающего АЦП
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

RCC_APB2PeriphClockCmd ( RCC_APB2Periph_TIM8, ENABLE );

TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
// делитель 33600 - частота прерываний = 84MHz/33600= 2500 = 2.5 kHz
TIM_TimeBaseStructure.TIM_Prescaler = 33600-1;

// Период загружается в ARR - значение перезагрузки. Счётчик считает 0..ARR
TIM_TimeBaseStructure.TIM_Period = 2; //период 2 импульсов - частота 1250 гц

TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit ( TIM8, &TIM_TimeBaseStructure );
TIM_SelectOutputTrigger ( TIM8, TIM_TRGOSource_Update );
} // adcInit

// Старт
void adcStart ( void )
{
TIM_Cmd ( TIM8, ENABLE );
} // adcStart


Из main-а вызываю adcInit, adcStart (т.е. запускаю таймер).
Результат - зависание на последней команде adcInit TIM_SelectOutputTrigger ( TIM8, TIM_TRGOSource_Update );
До запуска и всего прочего дело не доходит ....
Наверное в инициализации накосячил. Но не пойму где.

Пробовал ручной запуск, типа как здесь - http://electronix.ru/forum/index.php?showtopic=104701 и в примерах от ST, т.е. вместо таймера команда
ADC_SoftwareStartConv(ADC1); // start ADC conversions
Не виснет, но в буфере нули ... В той теме пошли разговоры на религиозные темы - "регистры против библиотек и функций" sm.gif .

Да и нужен мне не ручной запуск, а по таймеру, с определённой частотой. Сам таймер работает, если убрать триггер и повесить прерывание, то оно исправно тикает с указанной частотой.
Я также пытался ставить ADC_SoftwareStartConv(ADC1); в прерывание таймера (метод а-ля AVR), получил пустой буфер с нулями.
На ноге PA0 (канал 0) висит потенциометр для отладки. От его положения соответственно ничего не зависит.

Также интересует, как установить прерывание DMA по заполнению буфера. Примеров не нашёл. В примере ADC3_DMA от ST (архив STM32F4xx_DSP_StdPeriph_Lib_V1.0.1) тупо выводит на дисплей 2-байтовую переменную, которую заполняет DMA. Но это ж некошерно ...

Помогите, кто может.

Спасибо.

PS. Плата STM32F4Discovery, проц STM32F4VGT6. Дисплей графический, ILI9320, работает по FSMC. С этим всё в норме.


--------------------
Чтобы возить такого пассажира, необходим лимузин другого класса.
(с) Мария Эдуарда
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 23:07
Рейтинг@Mail.ru


Страница сгенерированна за 0.01362 секунд с 7
ELECTRONIX ©2004-2016