Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Постоянное считывание 3 каналов АЦП без прерываний
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Halfback
Задача проста: имеются три переменные u16 a,b,c и есть 3 канала ацп ADC1, ADC2 и ADC3. Как сделать так, чтобы эти три канала постонно сканировались и значения записывались в 3 переменные без использования прерываний и ресурсов ядра. Т.е. чтобы фактически система жила своей жизнью... Тут понятно, нужно DMA но вот как обойтись без переинициализаций - ведь на каждый АЦП своя переменная для хранения результата. Есть у кого идеи как это сделать?
one_man_show
В постановке задачи непонятно, почему нужно исключить прерывания? Используется ли ОС? Какова периодичность опроса?
AHTOXA
Что за Cortex-то? Ежели STM32, то без проблем вроде (и без DMA).
Halfback
Спасибо что откликнулись! smile.gif

AHTOXA Да, Cortex STM32F103RE

Если без проблем то как? Читал про ADC но пока не догнал. Пока сделал циклический постоянный опрос Датчика температуры и запись значения в переменную, но я использую DMA с автоматической переинициализацией.


Цитата
В постановке задачи непонятно, почему нужно исключить прерывания? Используется ли ОС? Какова периодичность опроса?

ОС не используется, периодичность определяется аппаратными функциями АЦП (т.е. без тамеров и т.п.) ну и вообще каких-то жестких критериев нет - если будет мерить хотя бы 10 раз в секунду и то вполне устроит. Сейчас вообще стоит максимальное время семплирования канала.
Прерывания хочу исключить т.к. есть прерывания, которые надо сразу обрабатывать без всяких очередей. Заморачиваться в приоритетах пока нет желания.
AHTOXA
Цитата(Halfback @ Feb 21 2010, 00:06) *
Если без проблем то как?

Посмотрите примеры от их FWLib. В частности, examples\ADC\3ADCs_DMA.
Насчёт того, что легко без DMA я похоже погорячилсяsmile.gif - либо поллинг, либо DMA.
Halfback
AHTOXA
Пример давно еще изучен и не катит - там ДВА РАЗНЫХ АЦП1 и АЦП3 и на них работает свой канал DMA. Третий АЦП2 висит на NVIC где в обработчике считывается значение из регистра в переменную. ТАк что не канает.
Halfback
Проблема решена. Как всегда самим.

Вот так:
в переменную u16 ADC_ConvertedValue[3] = {0,0,0}; надо складывать преобразования 0,1 и 16 каналов АЦП и чтобы всё на автомате и без прерываний.

Инициализация ADC:
Код
void ADC_Configuration(void) {

    ADC_InitTypeDef ADC_InitStructure;     

    ADC_TempSensorVrefintCmd(ENABLE);    
    
      /* ADC1 configuration ------------------------------------------------------*/
      ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
      ADC_InitStructure.ADC_ScanConvMode = ENABLE;
      ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
      ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
      ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
      ADC_InitStructure.ADC_NbrOfChannel = 3;
      ADC_Init(ADC1, &ADC_InitStructure);    
      
    ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_16, 3, ADC_SampleTime_239Cycles5);

    ADC_DMACmd(ADC1, ENABLE);  /* Enable ADC1 DMA */
      ADC_Cmd(ADC1, ENABLE);     /* Enable ADC1 */                                          
      ADC_ResetCalibration(ADC1);      /* Enable ADC1 reset calibaration register */       
      while(ADC_GetResetCalibrationStatus(ADC1));     /* Check the end of ADC1 reset calibration register */      
      ADC_StartCalibration(ADC1);     /* Start ADC1 calibaration */          
      while(ADC_GetCalibrationStatus(ADC1)); /* Check the end of ADC1 calibration */      
      ADC_SoftwareStartConvCmd(ADC1, ENABLE);    /* Start ADC1 Software Conversion */  
    }


Инициализация DMA:
Код
    // Настраиваем канал 1 DMA_1 на передачу из АЦП значения датчика температуры
    /* DMA1 channel1 configuration ----------------------------------------------*/
      DMA_DeInit(DMA1_Channel1);
      DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;  //(u32)0x4001244C;
      DMA_InitStructure.DMA_MemoryBaseAddr = (u32) ADC_ConvertedValue;
      DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
      DMA_InitStructure.DMA_BufferSize = 3;
      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_M2M = DMA_M2M_Disable;
      DMA_Init(DMA1_Channel1, &DMA_InitStructure);


Проверено - работает. Из примера вроде всё понятно что к чему и почему.
AHTOXA
Цитата(Halfback @ Feb 24 2010, 01:22) *
Проблема решена. Как всегда самим.


Ага, я же говорил что элементарно!
Шутка, шуткаsmile.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.