HardwareTimer прерывание
- Войдите на сайт для отправки комментариев
Пт, 13/03/2020 - 12:21
Добрый день.
Подскажите, почему не работает HardwareTimer на Nucleo f401. Пробовал и официальный пример :
и примеры с обучения:
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));
}
и в чем выражается не работает?
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.
Переменные, используемые в прерываниях, должны быть обьявлены как volatile
volatile int n=0; // не помогло. запускается 1 раз
ну тогда значит напутали с прерыванием. Когда вызываете attachInterrupt. надо указывать при каком именно событии возникает прерывание - оно может быть по сравнению, по переполнению, по захвату...
Не знаю, с каким аддоном вы пишете, у меня вот так - работает
update -исправил опечатку
Вот Эта сборка:
https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package...
не работает.... может инициализация какая нужна?
пробовал перед void setup() указывать :
HardwareTimer *Timer5=new HardwareTimer(TIM5);
Пишет ошибку: request for member 'setPeriod' in 'Timer5', which is of pointer type 'HardwareTimer*' (maybe you meant to use '->' ?)
я не знаю этот аддон и какой в нем синтаксис
Но если вы создаете указатель методом
то обращаться к его методам надо через стрелку:
И имена для своих переменных лучше брать такие, чтоб не пересекались с системными. то есть Timer5 или TIM5 я бы не брал.
t5->setPeriod(100000);
я так и подключаю. Ардуино не видит эти функции.
а у вас какой аддон? может проще мне на ваш перейти.
http://arduino.ru/forum/obshchii/arduino-ide-addon-ot-stm32
как раз этот аддон поставил все в точности с указанием по установке
А откуда пример с таймером? Он к этому аддону не относится. Открываете любой пример HAL. Или прямо на CMSIS. Мне больше LL драйвера нравятся. Они ближе к CMSIS. Инициализация из STM32CubeMX работает в ардуиновском коде без проблем.
https://github.com/stm32duino/STM32Examples/blob/master/examples/Peripherals/HardwareTimer/Timebase_callback/Timebase_callback.ino
Работает не понятно как с частотой 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 варианта... теперь в замешательстве.
А зачем стоки закомментированы?
пробовал по-разному... Закомментированные строки никак не влияют на таймер, если их раскомментировать - так и идет частота 648
Пробовать то зачем? Прочитайте про регистры таймера.
В частности.
TIM2->PSC=84-1; Предделитель. Этой командой тактируем таймер 1 МГц. Можно сделать любой в диапазоне uint16_t. 84 - системная частота, если конечно она оказалась такой после инициализации платы.
TIM2->ARR=1000-1; Собственно до куда считаем. В данном случае каждую миллисекунду будет переполнение и если событие update поставить в качестве источника прерывания в регистре TIM2->DIER=1<<0; тo период вызова прерывания определяется однозначно.
пробовал по-разному... Закомментированные строки никак не влияют на таймер, если их раскомментировать - так и идет частота 648
что-то вы уже совсем код исковеркали...
Посмотрел ваш аддон - в нем же есть простые примеры.
Начните с чистого листа - возьмите готовый пример из Вики, не забудьте свой счетчик сделать volatile и не путайте выходы, на которм мигаете диодом.
Пробовать то зачем? Прочитайте про регистры таймера.
ИМХО, не нужны ему регистры...
У него в аддоне есть функция setOverflow(), которая умеет подбирать параметры для нужного периода - разом устанавливает и прескалер и регистр сравнения.
Беда ТС в том, что, как кажется. он не очень понимает, что такое таймер и как работает - и постоянно мечется по инету в поисках готового примера, смешивая прямую работу с регистрами и функции разных аддонов... поэтому в скетче получается невообразимая каша.
пробовал по-разному...
А на пальцах такты посчитать? Чудес не бывает.
В Итоге нашел на форуме 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(){}В Итоге нашел на форуме stm32duino:
Все дело в версиях... новая версия еще не задокументирована! MyTim->setMode(2, TIMER_OUTPUT_COMPARE);
А это разве не документация? С примерами и описанием https://github.com/stm32duino/wiki/wiki/HardwareTimer-library
А это разве не документация? С примерами и описанием https://github.com/stm32duino/wiki/wiki/HardwareTimer-library
Пример из Examples не работает в версии 1.8.0.