HardwareTimer прерывание

sanstan
Offline
Зарегистрирован: 24.06.2019

Добрый день.

Подскажите, почему не работает HardwareTimer на Nucleo f401. Пробовал и официальный пример :

https://github.com/stm32duino/STM32Examples/blob/master/examples/Peripherals/HardwareTimer/Timebase_callback/Timebase_callback.ino

и примеры с обучения:

https://istarik.ru/blog/arduino/105.html   :

volatile bool LEDOn13 = 0;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT); // PC13
  Timer3.pause(); // останавливаем таймер перед настройкой
  Timer3.setPrescaleFactor(720); // устанавливаем делитель
  Timer3.setOverflow(16000); // переполнение
  Timer3.attachInterrupt(TIMER_UPDATE_INTERRUPT, func_tim_3); // активируем прерывание
  Timer3.refresh(); // обнулить таймер 
  Timer3.resume(); // запускаем таймер
}

void loop() 
{}

void func_tim_3() // обработчик прерывания
{
  digitalWrite(LED_BUILTIN, (LEDOn13 = !LEDOn13));
} 

 

b707
Онлайн
Зарегистрирован: 26.05.2017

и в чем выражается не работает?

sanstan
Offline
Зарегистрирован: 24.06.2019

HardwareTimer *Tim2=new HardwareTimer(TIM5);
int n=0;
void Tim2_IT_callback(HardwareTimer*){
  n++;
  Tim2->resume();    //можно и без этой строчки
}

void setup() {
  Serial.begin(115200); 
  
 // Tim2->setOverflow(100, HERTZ_FORMAT); // 10 kHz
  Tim2->setOverflow(100000, MICROSEC_FORMAT); // 100000 microseconds = 100 milliseconds
  Tim2->attachInterrupt(Tim2_IT_callback);  // активируем прерывание
  Tim2->refresh();   // обнулить таймер - без этой строчки нет даже одного вхождения
  Tim2->resume();    // запускаем таймер

}

void loop() {
  delay(500);                       // wait for a second
  t2++;     //это работает

  Serial.println(String(n));  //выводит "1"

}

Одно вхождение в таймер. менял таймеры 2,3,4.

b707
Онлайн
Зарегистрирован: 26.05.2017

Переменные, используемые в прерываниях, должны быть обьявлены как volatile

sanstan
Offline
Зарегистрирован: 24.06.2019

volatile int n=0; // не помогло. запускается 1 раз

b707
Онлайн
Зарегистрирован: 26.05.2017

ну тогда значит напутали с прерыванием. Когда вызываете attachInterrupt. надо указывать при каком именно событии возникает прерывание - оно может быть по сравнению, по переполнению, по захвату...

Не знаю, с каким аддоном вы пишете,  у меня вот так - работает

Timer5.setPeriod(100000); // 100000 microseconds = 100 milliseconds
Timer5.attachInterrupt(TIMER_UPDATE_INTERRUPT, im2_IT_callback);  // активируем прерывание
Timer5.refresh();   // обнулить таймер - 
Timer5.resume();    // запускаем таймер

update -исправил опечатку

sanstan
Offline
Зарегистрирован: 24.06.2019

Вот Эта сборка:

https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package...

Timer5.setPeriod(100000); // 100000 microseconds = 100 milliseconds
Timer5.attachInterrupt(TIMER_UPDATE_INTERRUPT, im2_IT_callback);  // активируем прерывание
Timer5.refresh();   // обнулить таймер - 
Timer5.resume();    // запускаем таймер

не работает.... может инициализация какая нужна?

пробовал перед void setup() указывать : 

HardwareTimer *Timer5=new HardwareTimer(TIM5); 

Пишет ошибку: request for member 'setPeriod' in 'Timer5', which is of pointer type 'HardwareTimer*' (maybe you meant to use '->' ?)

 
b707
Онлайн
Зарегистрирован: 26.05.2017

 я не знаю этот аддон и какой в нем синтаксис

Но если вы создаете указатель методом

HardwareTimer *t5=new HardwareTimer(TIM5); 

то обращаться к его методам надо через стрелку:

t5->setPeriod(100000);

И имена для своих переменных лучше брать такие, чтоб не пересекались с системными. то есть Timer5 или TIM5 я бы не брал.

sanstan
Offline
Зарегистрирован: 24.06.2019

t5->setPeriod(100000);

я так и подключаю. Ардуино не видит эти функции.

 

а у вас какой аддон? может проще мне на ваш перейти.

nik182
Offline
Зарегистрирован: 04.05.2015
sanstan
Offline
Зарегистрирован: 24.06.2019

как раз этот аддон поставил все в точности с указанием по установке

nik182
Offline
Зарегистрирован: 04.05.2015

А откуда пример с таймером? Он к этому аддону не относится. Открываете любой пример HAL. Или прямо на CMSIS. Мне больше LL драйвера нравятся. Они ближе к CMSIS. Инициализация из STM32CubeMX работает в ардуиновском коде без проблем. 

 

 

 

sanstan
Offline
Зарегистрирован: 24.06.2019
sanstan
Offline
Зарегистрирован: 24.06.2019

Работает не понятно как с частотой 648 Гц :

http://arduino.ru/forum/obshchii/arduino-ide-addon-ot-stm32:

 

void setup() {
  pinMode(PA5,OUTPUT);
  RCC->APB1ENR|=1<<0; //tim2 clock enable   //стр. 126/847

  TIM2->PSC=80000-1;//
 // TIM2->DIER=1<<0;// Update interrupt enable
//  TIM2->ARR=84000000;//1 sec
  TIM2->CR1=1;
//  NVIC_EnableIRQ(TIM2_IRQn);
  HardwareTimer *tim2 = new HardwareTimer(TIM2);
  tim2->attachInterrupt(led_blink);

}

int f=0;
void led_blink(HardwareTimer*){
  f++;
  if(f>1){
    digitalWrite(PA5,HIGH);
    f=0;
  }else{
    digitalWrite(PA5,LOW);
  }
}

Попробовал 3 варианта... теперь в замешательстве.

nik182
Offline
Зарегистрирован: 04.05.2015

А зачем стоки закомментированы? 

sanstan
Offline
Зарегистрирован: 24.06.2019

пробовал по-разному... Закомментированные строки никак не влияют на таймер, если их раскомментировать - так и идет частота 648

nik182
Offline
Зарегистрирован: 04.05.2015

Пробовать то зачем? Прочитайте про регистры таймера.

В частности.

TIM2->PSC=84-1; Предделитель. Этой командой тактируем таймер 1 МГц. Можно сделать любой в диапазоне uint16_t. 84 - системная частота, если конечно она оказалась такой после инициализации платы.  

TIM2->ARR=1000-1;  Собственно до куда считаем. В данном случае каждую миллисекунду будет переполнение и если событие update поставить в качестве источника прерывания в регистре TIM2->DIER=1<<0; тo период вызова прерывания определяется однозначно.

 

b707
Онлайн
Зарегистрирован: 26.05.2017

sanstan пишет:

пробовал по-разному... Закомментированные строки никак не влияют на таймер, если их раскомментировать - так и идет частота 648

что-то вы уже совсем код исковеркали...

Посмотрел ваш аддон - в нем же есть простые примеры.

Начните с чистого листа - возьмите готовый пример из Вики, не забудьте свой счетчик сделать volatile и не путайте выходы, на которм мигаете диодом.

b707
Онлайн
Зарегистрирован: 26.05.2017

nik182 пишет:

Пробовать то зачем? Прочитайте про регистры таймера.

ИМХО, не нужны ему регистры...

У него в аддоне есть функция setOverflow(), которая умеет подбирать параметры для нужного периода - разом устанавливает и прескалер и регистр сравнения.

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

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

sanstan пишет:

пробовал по-разному... 

А на пальцах такты посчитать? Чудес не бывает.

sanstan
Offline
Зарегистрирован: 24.06.2019

В Итоге нашел на форуме stm32duino:

Все дело в версиях... новая версия еще не задокументирована!   MyTim->setMode(2, TIMER_OUTPUT_COMPARE);

Попробуй сам догадайся.

Теперь все заработало нормально.


/*
  Timebase callback
  This example shows how to configure HardwareTimer to execute a callback at regular interval.
  Callback toggles pin.
  Once configured, there is only CPU load for callbacks executions.
*/

#if defined(LED_BUILTIN)
#define pin  PA5
#else
#define pin  PA5
#endif

void Update_IT_callback(HardwareTimer*)
{ // Toggle pin. 10hz toogle --> 5Hz PWM
  digitalWrite(pin, !digitalRead(pin));
}

void setup()
{
#if defined(TIM1)
  TIM_TypeDef *Instance = TIM1;
#else
  TIM_TypeDef *Instance = TIM2;
#endif

  // Instantiate HardwareTimer object. Thanks to 'new' instanciation, HardwareTimer is not destructed when setup() function is finished.
  HardwareTimer *MyTim = new HardwareTimer(Instance);

  // configure pin in output mode
  pinMode(pin, OUTPUT);

  MyTim->setMode(2, TIMER_OUTPUT_COMPARE);
  MyTim->setOverflow(15, HERTZ_FORMAT); // 10 Hz
  MyTim->attachInterrupt(Update_IT_callback);
  MyTim->resume();
}

void loop(){}

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

sanstan пишет:

В Итоге нашел на форуме stm32duino:

Все дело в версиях... новая версия еще не задокументирована!   MyTim->setMode(2, TIMER_OUTPUT_COMPARE);

А это разве не документация? С примерами и описанием https://github.com/stm32duino/wiki/wiki/HardwareTimer-library

sanstan
Offline
Зарегистрирован: 24.06.2019

dimax пишет:

А это разве не документация? С примерами и описанием https://github.com/stm32duino/wiki/wiki/HardwareTimer-library

Пример из Examples не работает в версии 1.8.0.