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

STM32F4, Input capture

допустим на вход PA0 подается пульс шириной 1.5мс, и повторяется каждые 15мс.

но ширина пульса конечно может менятся, и ее я хочу измерять.

 

 

я сконфигурировал порт PA0 как входной захват, а на него подаю пульс который генерируется пином PB4, с PB4 поступает пульс описанный выше, это я проверил.

 

но на входе па0 почемуто не могу захватить сигнал, т.е. не считает счетчик.

полярность входного сигнала высокая стоит, как и по умолчанию, по идее настроив его на вход, проставив значение фильтра, и включив он уже должен работать, и я должен суметь считать значение счетчика равное времени входного пульса с TIM2_CCR1, но почемуто читается только 0.

 

вот код настройки:

// configure TIM2_CH1 for input capture //////////////////////////////////


TIM2->CCMR1 |=
        TIM_CCMR1_CC1S_0 | // set TIM2_CH1 for input mode
        TIM_CCMR1_IC1F_1; // set the input filter to 4 samples


// select edge of the active transition


//enable input capture
TIM2->CCER |= TIM_CCER_CC1E;


while (1)
{
    //cnt = TIM3->CNT;
    capture = TIM2->CCR1;

}

 

что еще я мог упустить?

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


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

с TIM2_CCR1, но почемуто читается только 0.

Дык таймер-то никто не запустил.

Вообще в STM32F очень навороченные таймеры: легко делается анти-ШИМ (на двух каналах, которые подключаются к одному пину) - в одном из каналов будет период, а в другом - длительность импульса.

Суть такова:

- по фронту импульса таймер сбрасывается и генерится прерывание, но предварительно сохраняется текущее значение таймера в первый (не путать с CCR1) регистр захвата;

- по спаду импульса копируется текущее значение таймера во второй регистр захвата;

- в прерывании имеем период и длительность импульса;

- можно настроить прерывание по переполнению и иметь информацию об отсутствии импульсов.

 

Например, так:

//-------------------------------------------------------------
// init_TIMER2(void)
//-------------------------------------------------------------
// Инициализация таймера 2 захват параметров ШИМ-сигнала на
// линии 2
//-------------------------------------------------------------
void __inline init_TIMER2(void)
{
    TIM2->CR1=0;                // счетчик выключен
    TIM2->PSC=720;            // максимальное разрешение

    TIM2->CCMR1=
        (2<<TIM_CCMR1_CC1S)
        |(1<<TIM_CCMR1_CC2S);

    TIM2->CCER=
        (1<<TIM_CCER_CC1E)
        |(1<<TIM_CCER_CC1P)
        |(1<<TIM_CCER_CC2E)
        |(0<<TIM_CCER_CC2P);

    TIM2->SMCR=
        (4<<TIM_SMCR_SMS)
        |(6<<TIM_SMCR_TS);

    TIM2->DIER=6;

    TIM2->CR1=1;

}
//-------------------------------------------------------------
// void TIM2_IRQHandler(void)
//-------------------------------------------------------------
// Прерывание от T2
//-------------------------------------------------------------
void TIM2_IRQHandler()
{
    if(TIM2->SR&2)
    {
        ir_pulse=TIM2->CCR1;

    }
    if(TIM2->SR&4)
    {
        ir_period=TIM2->CCR2;
        ir_get(ir_pulse,ir_period);
    }
    TIM2->SR=0;
}

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


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

для начала тогда решил сделать как Вашем примере, вот такой же код:

// enable TIM3 clock
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;

TIM2->CR1 = 0;
TIM2->PSC = 720;

TIM2->CCMR1 |= TIM_CCMR1_CC1S_1 |
        TIM_CCMR1_CC2S_0;


TIM2->CCER |= TIM_CCER_CC1E |
              TIM_CCER_CC1P |
              TIM_CCER_CC2E;


TIM2->SMCR |= TIM_SMCR_TS_2 |
              TIM_SMCR_TS_1 |
              TIM_SMCR_SMS_2;

TIM2->DIER |= TIM_DIER_CC1IE |
              TIM_DIER_CC2IE;


TIM2->CR1 |= TIM_CR1_CEN;


while (1)
{

}

 

вот функция прерывания:

void TIM2_IRQHandler()
{
    uint32_t ir_pulse = 0, ir_period = 0;

    if(TIM2->SR&2)  // breakpoint here *
    {
        ir_pulse=TIM2->CCR1;

    }
    if(TIM2->SR&4)
    {
        ir_period=TIM2->CCR2;
       // ir_get(ir_pulse,ir_period);
    }
    TIM2->SR=0;
}

 

а вот настройка порта:

//=============================================================================
// GPIOA configuration
//=============================================================================

// enable GPIOA clock
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;

// Alternate Function
GPIOA->MODER |=
(GPIO_MODER_MODER0_1 | // AF, TIM2_CH1
GPIO_MODER_MODER1_1   // AF, TIM2_CH2
);

// Output type
GPIOA->OTYPER |=  0; // push-pull if 0


// Speed type
GPIOA->OSPEEDR |=
(GPIO_OSPEEDER_OSPEEDR0_1 | // TIM2_CH1, 50MHz
GPIO_OSPEEDER_OSPEEDR1_1   // TIM2_CH2, 50MHz
);

// Push/Pull
GPIOA->PUPDR |=
(
GPIO_PUPDR_PUPDR0_0 |  // Pull-Up, TIM2_CH1,
GPIO_PUPDR_PUPDR1_0    // Pull-Up, TIM2_CH2,
);


// Alternate Function pins
GPIOA->AFR[0] |=
((1 << ((0 - 0) << 2)) |  // TIM2_CH1, AF1
(1 << ((1 - 0) << 2))   // TIM2_CH2, AF1
);

 

 

подключил к ножке PA1 пульс (1.5мс ширина, период 15мс), поставил брейкпоинт внутри функции прерывания, и оно не происходит.

 

 

что там еще может быть?

 

и еще вопрос, как именно понимать это максимальное разрешение? т.е. это количество клоков которое учавствует в сэмплингер входного сигнала? на Рис. 133, стр. 373 Мануала, устанавливая PSC=720 мы контролируем CK_INT который на входе мультиплексора? или как?

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


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

подключил к ножке PA1 пульс (1.5мс ширина, период 15мс), поставил брейкпоинт внутри функции прерывания, и оно не происходит.

что там еще может быть?

и еще вопрос, как именно понимать это максимальное разрешение? т.е. это количество клоков которое учавствует в сэмплингер входного сигнала? на Рис. 133, стр. 373 Мануала, устанавливая PSC=720 мы контролируем CK_INT который на входе мультиплексора? или как?

Не вижу настройки NVIC.

"Максимальное разрешение" - множитель задающий масштаб в регистрах захвата.

В примере при тактовой 72МГц, получается масштаб "единица на 10мкс".

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


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

да, NVIC не настроил. Но тем не менее, прежде чем активировать прерывания, я решил подправить немного код, и посмотреть работает ли захват вообще, подправил только PSC = 840, чтобы получить 1 счет в 10мкс. Затем тот код что в прерывании запихнул в непрерывный цикл, и вижу в дебаггере:

 

ширина пульса = 149

период = 1498

 

ну а т.к. шаг = 10мкс, то 149*10мкс ~ 1.5мс, и 1298*10мкс ~ 15мс, т.е. измерил правильно.

 

 

Ну а вот теперь убедившись что захват уже работает, решил проверить прерывание, вписываю одну строку только:

// enable TIM2 interrupt
NVIC->ISER[0] |= 1 << TIM2_IRQn;

 

и возобновляю предыдущий код в обработчике прерывания, в дебаггере вижу что прерывание действительно происходит, однако значения ширины пульса и периода абсолютно неверные, слишком большие, вот они:

ir_pulse = 4294967295

ir_period = 4294967295

 

 

не могу понять почему так? пробовал объявлять эти переменные в других местах кода итд, тоже самое почти что.

почему в обработчике прерывания не могу считать верные значения, как я это делал в беспрерывном цикле без прерываний?

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


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

не могу понять почему так? пробовал объявлять эти переменные в других местах кода итд, тоже самое почти что.

почему в обработчике прерывания не могу считать верные значения, как я это делал в беспрерывном цикле без прерываний?

Может, "volatile" добавить?

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


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

не помогает чтото, пробовал также с/без статика, тоже самое, неверные значения. вот мой код обработчика прерывания:

 

void TIM2_IRQHandler()
{
    volatile static uint32_t ir_pulse = 0, ir_period = 0;

    if(TIM2->SR&2)
    {
        ir_pulse=TIM2->CCR1;
    }
    if(TIM2->SR&4)
    {
        ir_period=TIM2->CCR2;
       // ir_get(ir_pulse,ir_period);
    }
    TIM2->SR=0;
}

 

 

пробовал эти переменные вообще глобально объявлять, изменять их в обработчике, а потом в основной функции из них читать в другие переменные, тоже самое, получаю нереальные испорченные значения. что еще может быть не так?

 

можно на ваш ir_get посмотреть?

хочу увидеть как вы сохраняете данные и где именно объявляете переменные?

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


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

пробовал эти переменные вообще глобально объявлять, изменять их в обработчике, а потом в основной функции из них читать в другие переменные, тоже самое, получаю нереальные испорченные значения. что еще может быть не так?

можно на ваш ir_get посмотреть?

хочу увидеть как вы сохраняете данные и где именно объявляете переменные?

переменные объявлены так:

volatile int        ir_pulse;
volatile int        ir_period;

 

В ir_get нет ничего специфичного.

Переменные у Вас равны 0xFFFFFFFF.

Правильно ли Вы смотрите их отладчиком?

Дошагиваете отладчиком до места присваивания из регистров?

В каждом ли прерывании переменные равны 0xFFFFFFFF (в первом, в последующих)?

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


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

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

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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