Задача мониторить ток и напряжения.
Камень самый простой 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] - для короткого!!!