Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Analog Watchdog в STM32F103
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
zheka
Есть у кого-нибудь пример? В интернете обыскался, не нашел, а ручками что-то не получается...
Integro
Наверное у вас гугл сломался, запрос, один из результатов
zheka
Спасибо, нашел.
Но есть проблема - прерывание генерируется постоянно, независимот от показаний АЦП.
Отключал прерывания и смотрел как работает АЦП - измерения правильные, шумов нет.
Вот инициализация АЦП
Код
void adc_Init()
{

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);// ʹÄÜ ADC1 ÖØÒª£¡£¡£¡

    
  
        
//////////////////////////////        
        
         /* ADC1 Configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;
  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 channel14 configuration */
  ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_13Cycles5);

  /* Configure high and low analog watchdog thresholds */
  ADC_AnalogWatchdogThresholdsConfig(ADC1, 1000, 3902);
  /* Configure channel14 as the single analog watchdog guarded channel */
  ADC_AnalogWatchdogSingleChannelConfig(ADC1, ADC_Channel_0);
  /* Enable analog watchdog on one regular channel */
  ADC_AnalogWatchdogCmd(ADC1, ADC_AnalogWatchdog_SingleRegEnable);

  /* Enable AWD interrupt */
  ADC_ITConfig(ADC1, ADC_IT_AWD, ENABLE);

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

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

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

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


Вот ножка и прерывание
Код
void ADC1_2_IRQHandler(void)
{

  
   if(ADC_GetITStatus(ADC1,ADC_IT_AWD))
   {

  }  
     ADC_ClearITPendingBit(ADC1,ADC_IT_AWD);          

}


/////////////////////////////////

/* Configure PA.0 (ADC Channel) as analog input -------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);



Еще раз повторюсь - показания АЦП правильные.

Что я делаю не так?
SSerge
Описание работы AWD занимает в реф. мануале меньше страницы.
Читаем, пишем:
Код
#define guarded_channel (0)
ADC1->CR1 |= ADC_CR1_AWDEN  // enable on regular channels
        | ADC_CR1_AWDSGL    //  Enable the watchdog on a single channel in scan mode
        | ADC_CR1_AWDIE     //  Analog watchdog interrupt enable
        | guarded_channel;  // #channel
ADC1->LTR = 1000;
ADC1->HTR = 3902;

У меня работает.

Добавлено:
Цитата
Но есть проблема - прерывание генерируется постоянно, независимот от показаний АЦП.

Вот оно что:
Цитата
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold)

Сначала HighThreshold, потом LowThreshold !
zheka
Цитата
HighThreshold, потом LowThreshold !

Именно!
Заработало, спасибо!
ViKo
Очередное подтверждение того, что лучше написать по мануалу, чем ковыряться, как жук-навозник, в библиотеке.
zheka
А как сделать наоборот? Чтобы прерывание срабатывало тогда, когда напряжение входит в определенную зону?
Сергей Борщ
Цитата(zheka @ Feb 18 2015, 05:48) *
А как сделать наоборот? Чтобы прерывание срабатывало тогда, когда напряжение входит в определенную зону?
Если эта зона одним концом упирается в землю или питание - настроить собаку на оставшуюся часть диапазона. В противном случае - никак:
Цитата
The AWD analog watchdog status bit is set if the analog voltage converted by the ADC is below a low threshold or above a high threshold.


zheka
Хм.. а как бы сделать так, чтобы прерывание генерировалось один раз при выходе за пределы? Я хочу ловить фронт и спад сигнала невысокой частоты (не более 200 Гц). По некоторым причинам всякие таймеры и режимы захвата не подходят.
Сергей Борщ
В обработчике прерывания перенастраивать пределы.
Ruslan.B
А у меня проблема на f100RBT6, может чего-то упустил или вообще не знал?
Вкратце, что и в каком порядке...

Код
gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO1);

nvic_set_priority(NVIC_ADC1_2_IRQ, 0);
    nvic_enable_irq(NVIC_ADC1_2_IRQ);

adc_enable_analog_watchdog_regular(ADC1);
    adc_enable_analog_watchdog_on_selected_channel(ADC1,1);
    adc_enable_awd_interrupt(ADC1);
    adc_set_watchdog_high_threshold(ADC1,4000);
    adc_set_watchdog_low_threshold(ADC1,2000);


факт в том что в обработчик прерывания adc1_2_isr процесс не попадает...
Можно конечно в другом прерывании читать значение из АЦП и сравнивать. Но это печально.
ViKo
Цитата(Ruslan.B @ Feb 28 2017, 12:15) *
факт в том что в обработчик прерывания adc1_2_isr процесс не попадает...

АЦП еще настроить надо и запустить. Как обычно, начиная с тактов.
Ruslan.B
Цитата(ViKo @ Feb 28 2017, 15:27) *
АЦП еще настроить надо и запустить. Как обычно, начиная с тактов.


Извиняюсь. Это присутствует...

Код
rcc_periph_clock_enable(RCC_ADC1);
rcc_periph_clock_enable(RCC_GPIOA);


И вообще до этого взял из примера функцию:

Код
static void adc_setup(void)
{
    gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0);
    gpio_set_mode(GPIOA, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO1);

    /* Make sure the ADC doesn't run during config. */
    adc_off(ADC1);

    /* We configure everything for one single conversion. */
    adc_disable_scan_mode(ADC1);
    adc_set_single_conversion_mode(ADC1);
    adc_disable_external_trigger_regular(ADC1);
    adc_set_right_aligned(ADC1);
    adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC);

    adc_power_on(ADC1);

    /* Wait for ADC starting up. */
    int i;
    for (i = 0; i < 800000; i++) /* Wait a bit. */
        __asm__("nop");

    adc_reset_calibration(ADC1);
    adc_calibration(ADC1);
}


И оно всё работало...

ViKo
Я, обычно, в отладчике смотрю на флаги. И думаю, почему они не такие, как хочу. В Кейле хорошо видно.
jcxz
Цитата(ViKo @ Feb 28 2017, 11:54) *
Я, обычно, в отладчике смотрю на флаги. И думаю, почему они не такие, как хочу. В Кейле хорошо видно.

Не забывайте сразу предупреждать про read sensitives флаги wink.gif
А то вроде бы очевидные вещи, почему-то для многих не очевидны.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.