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

STM32F4+таймеры+захват

Всем привет!

Изучаю таймеры.

Перешел к изучению режима захвата.

В программе дрыгаю светодиодами с задержкой 5 сек.

попутно таймером TIM3 первый канал которого находится на PA6 пытаюсь захватить сигнал со светодиода, что живет на PD12. Просто замыкаю эти две ноги.

#include "stm32f4xx.h"				  // Device header

void init_gpio(void);
void init_timer(void);
void led_blinking(void);


static volatile uint32_t TimeTick;
volatile int capture1;
volatile int capture2;

void SysTick_Handler() { 
  if(TimeTick) 
  {
  TimeTick--;
  }
}

void TIM3_IRQHandler(){
  if(TIM3->SR&2){
  }
}


int main(){
  SysTick_Config(SystemCoreClock/1000);
  init_gpio();
  init_timer();
  while(1){
  led_blinking();
  }

}

void init_gpio(){
  /*Configure pins 12, 13, 14, 15 on port D*/
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
  GPIOD->MODER = 0x55000000;

  /*Cofigure TIM3, Channel 1 (PA6)*/
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  GPIOA->MODER = GPIO_MODER_MODER6_0;
  GPIOA->AFR[0] = 0x02000000;
}

void init_timer(){
  RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
  TIM3->CCMR1 |= TIM_CCMR1_CC1S_0;						   // CH1 to PA6
 TIM3->CCMR1 |= (TIM_CCMR1_IC1F_0 | TIM_CCMR1_IC1F_1);			//
 TIM3->CCER &= ~TIM_CCER_CC1P;
 TIM3->CCER &= ~TIM_CCER_CC1NP;
 TIM3->CCMR1 &= ~TIM_CCMR1_IC1PSC;						   // 
 TIM3->CCER |= TIM_CCER_CC1E;							  // 
 TIM3->DIER |= TIM_DIER_CC1IE;							  // 
 TIM3->CR1 |= TIM_CR1_CEN;								 // 
 NVIC_EnableIRQ(TIM3_IRQn);   
}


void DelaymS(uint32_t time){
  TimeTick = time;
while(TimeTick); 
}

void led_blinking(){
  GPIOD->BSRRH = GPIO_BSRR_BS_12 | GPIO_BSRR_BS_13 | GPIO_BSRR_BS_14 | GPIO_BSRR_BS_15; //LEDs On
  DelaymS(5000);//Delay using SysTick
  GPIOD->BSRRL = GPIO_BSRR_BS_12 | GPIO_BSRR_BS_13 | GPIO_BSRR_BS_14 | GPIO_BSRR_BS_15; //LEDs Off
  DelaymS(5000);
}

Настроил порт Д и диоды.

Настроил порт А и для шестой ноги определил альтернативную функцию.

Настроил таймер в режиме захвата, захват по фронту.

Но почему-то не заходит в прерывание. Период изменения сигнала для светодиодов 5 сек.

Где я мог ошибиться?

Изменено пользователем IgorKossak
[codebox] для длинного кода, [code] - для короткого!

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


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

Как минимум, ошибка здесь:

 

ARR[15:0]: Prescaler value

ARR is the value to be loaded in the actual auto-reload register.

The counter is blocked while the auto-reload value is null

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


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

 

 

Прерывания разрешили?

Остановите в отладчике и посмотрите содержимое регистра разрешения -- флаг разрешения и флаг прерывания. Если нет хотя бы одного, то прерывания не будет. То какого нет даст информацию, что не сделано.

Изменено пользователем IgorKossak
бездумное цитирование

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


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

Чтобы не плодить темы...

Вот думаю, как АТОМАРНО считать значение таймера и обнулить его? Потеря счетных импульсов недопустима!

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


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

Вот думаю, как АТОМАРНО считать значение таймера и обнулить его? Потеря счетных импульсов недопустима!

Такие сферические вопросы в вакууме плохо помогают приблизиться к решению задачи. Что сделать-то надо?

А вообще вот вам сферический ответ в вакууме: сконфигурируйте таймер так, чтобы сигнал на одном из его входов вызывал и захват, и сброс. И надейтесь, что захват произойдёт раньше сброса :laughing:

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


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

Чтобы не плодить темы...

Вот думаю, как АТОМАРНО считать значение таймера и обнулить его? Потеря счетных импульсов недопустима!

 

Если вам надо измерять временные интервалы, то input capture это все что надо.

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


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

Чтобы не плодить темы...

Вот думаю, как АТОМАРНО считать значение таймера и обнулить его? Потеря счетных импульсов недопустима!

Вот я думал-думал и так и не придумал зачем может такая вещь понадобиться? Это получается, что "все равно, что считываю из Таймера - лишь бы как только считал значение, то сразу обнулился бы этот Таймер!". Так получается. Т.е. тут будут какие-то программные задержки на обращение/считывание значения из Таймера и Вам на них плевать, а обнулить все равно хочется точно в момент считывания. Если Вам нужно организовать подсчет длины внешнего импульса и по возникшему прерыванию считываете значение Таймера (сразу его обнулив при этом), то лучше напрямую захват сделать! А если Вы какие-то длительности внутренних процессов подсчитываете, то все равно так не делают ка Вы хотите.

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


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

Таймер в режиме счетчика. Нужен подсчет внешних импульсов. В произвольный момент берется значение и отсылается далее, далее счет начинается заново.

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

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


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

Таймер в режиме счетчика. Нужен подсчет внешних импульсов. В произвольный момент берется значение и отсылается далее, далее счет начинается заново.

Не нужно для этого сбрасывать счётчик. Запоминаем последнее считанное значение, в следующий раз вычитаем его. Учитываем переполнения, естественно. Сброс-то зачем?

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


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

Вредная привычка экономить память и процессорные такты...

Да, видимо, буду запоминать.

Есть, правда, мысля еще попробовать запретить работу таймера, считать-сбросить, разрешить работу. При разрешении, таймер, возможно, отработает смену входного уровня, если она произойдет.

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


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

Вредная привычка экономить память и процессорные такты...

До добра не доведёт. Бросайте это гиблое дело. Какие такие такты? Их сейчас раздают по 100 млн шт. в секунду. Не говоря уже о том, что копеечку выиграешь, а рубль потеряешь. Впрочем, мне-то что? Думайте сами :laughing:

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


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

Проблема была в том, что я неверно настроил пин на альтернативную функцию.

GPIOA->MODER = GPIO_MODER_MODER6_1;

должно быть

А вот насчет установки предделителя PSC и значения ARR не уверен, что обязательно устанавливать. У меня и так и так работает. То есть мк уходит в прерывание. Может кто объяснить надо ли для захвата их настраивать?

 

Далее решил разобраться а как же определить период сигнала.

По идее в обработчике прерывания необходимо (сбросить флаг само собой) записать в переменную значение TIM3->CCR1, а затем вычислить разницу между предыдущим и следующим значениями.

capture1 = capture2 = 0;
    capture2 = TIM3->CCR1;
    t = capture2 - capture1;

Верно?

Но почему-то t какая-то фигня пишется. HEX в DEC не забываю перевести.

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

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


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

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

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

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

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

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

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

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

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

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