Перейти к содержанию
    

Analog Watchdog в STM32F103

Есть у кого-нибудь пример? В интернете обыскался, не нашел, а ручками что-то не получается...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, нашел.

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

Отключал прерывания и смотрел как работает АЦП - измерения правильные, шумов нет.

Вот инициализация АЦП

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);

 

 

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

 

Что я делаю не так?

Изменено пользователем zheka

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Описание работы 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 !

Изменено пользователем SSerge

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Очередное подтверждение того, что лучше написать по мануалу, чем ковыряться, как жук-навозник, в библиотеке.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как сделать наоборот? Чтобы прерывание срабатывало тогда, когда напряжение входит в определенную зону?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А как сделать наоборот? Чтобы прерывание срабатывало тогда, когда напряжение входит в определенную зону?
Если эта зона одним концом упирается в землю или питание - настроить собаку на оставшуюся часть диапазона. В противном случае - никак:

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.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Хм.. а как бы сделать так, чтобы прерывание генерировалось один раз при выходе за пределы? Я хочу ловить фронт и спад сигнала невысокой частоты (не более 200 Гц). По некоторым причинам всякие таймеры и режимы захвата не подходят.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В обработчике прерывания перенастраивать пределы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А у меня проблема на 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 процесс не попадает...

Можно конечно в другом прерывании читать значение из АЦП и сравнивать. Но это печально.

Изменено пользователем Ruslan.B

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

факт в том что в обработчик прерывания adc1_2_isr процесс не попадает...

АЦП еще настроить надо и запустить. Как обычно, начиная с тактов.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

АЦП еще настроить надо и запустить. Как обычно, начиная с тактов.

 

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

 

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);
}

 

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я, обычно, в отладчике смотрю на флаги. И думаю, почему они не такие, как хочу. В Кейле хорошо видно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я, обычно, в отладчике смотрю на флаги. И думаю, почему они не такие, как хочу. В Кейле хорошо видно.

Не забывайте сразу предупреждать про read sensitives флаги ;)

А то вроде бы очевидные вещи, почему-то для многих не очевидны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...