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

 
 
> Проблема с АЦП STM32F100, Проблема при измерении инжектированного и регулярного канала
drum1987
сообщение Feb 27 2013, 18:36
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 255
Регистрация: 3-02-09
Из: Омск
Пользователь №: 44 323



Задача мониторить ток и напряжения.
Камень самый простой f100c4. Соответственно АЦП только 1. Использую 2 канала (0 и 8). 0 канал мерит напряжения (их 8 подаются с мультиплексора). Сигнал на вход АЦП подается с ОУ, поэтому сопротивление источника мало + RC фильтр 100 Ом + 10нФ.

Схема измерения напряжения такая: Дергаю ножкой(подключая этим источник ко входу ОУ), запускаю 2(4, 8, 16) раза регулярное преобразование в прерывании по окончанию (флаг EOC) считываю результат преобразования, вычисляю среднее и ногу опускаю назад. Повторяю для всех ног. Пачка измерений раз в секунду.
Схема измерения тока: Источник подключен всегда, инжектированный канал связан с таймером необходимо 100 измерений в секунду (хочу считать А*ч).

Вроде все ясно и понятно, но есть проблема: когда инжектированный канал прерывается инжектированным, то преобразование регулярного канала не возобновляется при завершении преобразования в инжектированном канале. Изза этого образубтся "провалы" при измерениях.



Как видно из рисунка, значение измеренное при вытеснении инжектированным каналом близко к 0,4 В. (4+0,4)/2=2,2 В. То, что с напряжением на ноге все в порядке говорит осциллограмма:



Тут желтая эпюра - напряжение на входе АЦП, синяя - "отладочный светодиод" зажигаемый в момент начала преобразования и тушащийся в момент срабатывания прерывания по событию EOC.
Хорошо виден момент когда срабатывает инжектированный канал (импульс малой длительности по сравнению с остальными) прерванное преобразование не возобновляется.

Прилагаю код:
Настройка АЦП:
CODE
/* Enable ADC1 and RCC clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div2);

/* 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 = 1;
ADC_Init(ADC1, &ADC_InitStructure);


/* ADC1 regular channel0 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);

/* Set injected sequencer length */
ADC_InjectedSequencerLengthConfig(ADC1, 1);

/* ADC1 injected channel Configuration */
ADC_InjectedChannelConfig(ADC1, ADC_Channel_8, 1, ADC_SampleTime_239Cycles5);

/* ADC1 injected external trigger configuration */
ADC_ExternalTrigInjectedConvConfig(ADC1, ADC_ExternalTrigInjecConv_T2_TRGO);

/* Enable JEOC interrupt on ADC1 */
ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE);

/* Enable ADC1 EOC interupt */
ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);

NVIC_SetPriority (ADC1_IRQn, 1);

/* Enable ADC1 */
ADC_Cmd(ADC1, ENABLE);

/* Enable ADC1 reset calibaration register */
ADC_ResetCalibration(ADC1);

/* Check the end of ADC1 reset calibration register */
while(ADC_GetResetCalibrationStatus(ADC1));

/* Start ADC1 calibaration */
ADC_StartCalibration(ADC1);

/* Check the end of ADC1 calibration */
while(ADC_GetCalibrationStatus(ADC1));


/* Start ADC1 Software Conversion */
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE);



Прерывания по АЦП:
Код
void ADC1_IRQHandler(void)
{
  if (ADC_GetFlagStatus(ADC1, ADC_FLAG_JEOC))
  {
        // Get injected channel8 converted value
        int curr = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_2);
        curr = curr * VCC/0xfff;
    
ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC);
  }

  else if (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC))
  {
ADC1ConvertedValue = ADC_GetConversionValue(ADC1);
/* Clear ADC1 EOC pending interrupt bit */
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
converted = 1;
  LED_OFF;
    }
}


Вызов преобразования:
Код
long cell_mesure(unsigned int cell_num)
{

    GPIO_HIGH(Mes[cell_num - 1]->port, Mes[cell_num - 1]->pin); // включение измерителя
    converted = 0;    
    LED_ON;
    ADC1->SQR3 = 0;                //загрузить номер канала
              ADC1->CR2 |= ADC_CR2_SWSTART;     //запустить преобразование в регулярном канале  
    while(!converted);
    long voltage = ADC1ConvertedValue;  // измерение №1

    return (voltage);
}


Куда копать?

Сообщение отредактировал IgorKossak - Mar 1 2013, 08:31
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post



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

 


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


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