Stm32 прерывание по сравнению в таймере
- Войдите на сайт для отправки комментариев
Хочу освоить таймеры в STM32, с прерыванием по переполнению разобрался а вот с сравнением есть проблемы( Пытаюсь выжать с таймера все соки и сделать прерывание по переполнению и четыре прерывания по сравнению
В строчке 16 прописан параметр TIMER_UPDATE_INTERRUPT насколько я понимаю это флаг прерывания по переполнению как в ардуино нано или просто задекларированный в ардуино параметр, и я не могу разобраться как установить прерывание по сравнению с конкретным регистром сравнения, где можно найти перечень возможных параметров или пример работы таймера по нескольким сравнениям с помощью прямого доступа к регистрам а не через библиотеку???
Также не уверен правильно ли я включил режим сравнения (строчки 34-36) вроде по даташыту через переводчик оно правильно но хз)
Буду признателен за любую информацию!)
volatile bool LEDOn1 = 0;
volatile bool LEDOn2 = 0;
volatile bool LEDOn3 = 0;
volatile bool LEDOn4 = 0;
volatile bool LEDOn5 = 0;
void setup() {
pinMode(PA1, OUTPUT);
pinMode(PA2, OUTPUT);
pinMode(PA3, OUTPUT);
pinMode(PA4, OUTPUT);
pinMode(PA5, OUTPUT);
timer_attach_interrupt(TIMER2, TIMER_UPDATE_INTERRUPT, LED1); //прерывание по переполнению
timer_attach_interrupt(TIMER2, TIMER_UPDATE_INTERRUPT, LED2);
timer_attach_interrupt(TIMER2, TIMER_UPDATE_INTERRUPT, LED3);// как здесь сделать прерывание по сравнению???
timer_attach_interrupt(TIMER2, TIMER_UPDATE_INTERRUPT, LED4);
timer_attach_interrupt(TIMER2, TIMER_UPDATE_INTERRUPT, LED5);
RCC_BASE->APB1ENR|= (1<<0);//включить тактирование tim2
TIMER2_BASE->PSC = 7200-1; //значение пред делителя -1
TIMER2_BASE->ARR = 50000; //считать до установленого числа и обнулиться
TIMER2_BASE->CCR1 = 10000; //регистр сравнения 1
TIMER2_BASE->CCR2 = 20000; //регистр сравнения 2
TIMER2_BASE->CCR3 = 30000; //регистр сравнения 3
TIMER2_BASE->CCR4 = 40000; //регистр сравнения 4
TIMER2_BASE->DIER |= (1<<0); //разрешить прерывание по переполнению
TIMER2_BASE->DIER |= (1<<1); //разрешить прерывание по сравнению 1
TIMER2_BASE->DIER |= (1<<2); //разрешить прерывание по сравнению 2
TIMER2_BASE->DIER |= (1<<3); //разрешить прерывание по сравнению 3
TIMER2_BASE->DIER |= (1<<4); //разрешить прерывание по сравнению 4
TIMER2_BASE->CCMR1 &=~ (1<<0);
TIMER2_BASE->CCMR1 &=~ (1<<1); //включение режима сравнения // тут хз или правильно...
TIMER2_BASE->CCMR2 &=~ (1<<0);
TIMER2_BASE->CCMR2 &=~ (1<<1);
TIMER2_BASE->CR1 |=(1<<2); //разрешить принудительную перезагрузку счетного регистра // это здесь нужно??
TIMER2_BASE->CR1 |=(1<<0); //Включение тактирования таймера
}
void LED1(){ //обработчик прерывания
digitalWrite(PA1, (LEDOn1 = !LEDOn1));
TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания
}
void LED2(){
digitalWrite(PA2, (LEDOn2 = !LEDOn2));
TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания
}
void LED3(){
digitalWrite(PA3, (LEDOn3 = !LEDOn3));
TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания
}
void LED4(){
digitalWrite(PA4, (LEDOn4 = !LEDOn4));
TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания
}
void LED5(){
digitalWrite(PA5, (LEDOn5 = !LEDOn5));
TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания
}
void loop() {
}
Утро вечера мудренее) Все работает. Список задекларированных параметров нашел здесь- http://librambutan.readthedocs.io/en/latest/libmaple/api/timer.html
Рабочий вариант программы-
volatile bool LEDOn1 = 0; volatile bool LEDOn2 = 0; volatile bool LEDOn3 = 0; volatile bool LEDOn4 = 0; volatile bool LEDOn5 = 0; void setup() { pinMode(PA1, OUTPUT); pinMode(PA2, OUTPUT); pinMode(PA3, OUTPUT); pinMode(PA4, OUTPUT); pinMode(PA5, OUTPUT); timer_attach_interrupt(TIMER2, TIMER_UPDATE_INTERRUPT, LED5); //прерывание по переполнению timer_attach_interrupt(TIMER2, TIMER_CC1_INTERRUPT, LED1); timer_attach_interrupt(TIMER2, TIMER_CC2_INTERRUPT, LED2); // прерывания по сравнению timer_attach_interrupt(TIMER2, TIMER_CC3_INTERRUPT, LED3); timer_attach_interrupt(TIMER2, TIMER_CC4_INTERRUPT, LED4); TIMER2_BASE->CR1 &=~ (1<<0); //Выключение тактирования таймера RCC_BASE->APB1ENR|= (1<<0);//включить тактирование tim2 TIMER2_BASE->PSC = 7200-1; //значение пред делителя -1 (считаем от 0) TIMER2_BASE->ARR = 50000-1; //считать до установленого числа и обнулиться TIMER2_BASE->CCR1 = 10000-1; //регистр сравнения 1 TIMER2_BASE->CCR2 = 20000-1; //регистр сравнения 2 TIMER2_BASE->CCR3 = 30000-1; //регистр сравнения 3 TIMER2_BASE->CCR4 = 40000-1; //регистр сравнения 4 TIMER2_BASE->DIER |= (1<<0); //разрешить прерывание по переполнению TIMER2_BASE->DIER |= (1<<1); //разрешить прерывание по сравнению 1 TIMER2_BASE->DIER |= (1<<2); //разрешить прерывание по сравнению 2 TIMER2_BASE->DIER |= (1<<3); //разрешить прерывание по сравнению 3 TIMER2_BASE->DIER |= (1<<4); //разрешить прерывание по сравнению 4 TIMER2_BASE->CCMR1 &=~ (1<<0); TIMER2_BASE->CCMR1 &=~ (1<<1); //включение режима сравнения TIMER2_BASE->CCMR2 &=~ (1<<0); TIMER2_BASE->CCMR2 &=~ (1<<1); TIMER2_BASE->CR1 |=(1<<0); //Включение тактирования таймера //TIMER2_BASE->CR1 &=~ (1<<0); //Выключение тактирования таймера } void LED1(){ //обработчик прерывания по сравнению 1 digitalWrite(PA1, (LEDOn1 = !LEDOn1)); //меняем состояние порта на противоположное TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания } void LED2(){ //обработчик прерывания по сравнению 2 digitalWrite(PA2, (LEDOn2 = !LEDOn2)); //меняем состояние порта на противоположное TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания } void LED3(){ //обработчик прерывания по сравнению 3 digitalWrite(PA3, (LEDOn3 = !LEDOn3)); //меняем состояние порта на противоположное TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания } void LED4(){ //обработчик прерывания по сравнению 4 digitalWrite(PA4, (LEDOn4 = !LEDOn4)); //меняем состояние порта на противоположное TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания } void LED5(){ //обработчик прерывания по переполнению digitalWrite(PA5, (LEDOn5 = !LEDOn5)); //меняем состояние порта на противоположное TIMER2_BASE->SR &=~ (1<<0); // Сбрасываем флаг прерывания } void loop() { }простите, раз уж вы используете высокоуровневую функцию timer_attach_interrupt - то почему все остальное не сделать так же, собрал пример из документации:
#define TIM_RATE 200000 // in microseconds; should give 0.2s toggles // We'll use timer 2 HardwareTimer timer(2); void setup { // initialize Timer2 // Pause the timer while we're configuring it timer.pause(); // Set up period timer.setPeriod(TIM_RATE); // in microseconds // Set up an interrupt on channel 1 timer.setChannel1Mode(TIMER_OUTPUT_COMPARE); timer.setCompare(TIMER_CH1, 1); // Interrupt 1 count after each update timer.attachCompare1Interrupt(timer_handler_led); // Refresh the timer's count, prescale, and overflow timer.refresh(); // Start the timer counting timer.resume(); } void loop { }Это первое знакомство с таймерами stm32 поэтому решил начать снизу чтоб понять как они работают и до конфигурирования на более высоком уровне я еще просто не добрался, ну и так как информации и примеров по работе с stm в среде ардуино очень мало то слепил как сумел используя примеры конфигурации таймеров stm под keil)
А есть какой-то более низкоуровневый способ объявления прерывания чем timer_attach_interrupt?
Из какой документации ваш пример?
документации и примеров очень много на http://www.stm32duino.com/
да и вообще - просто в гугле набираешь stm32 arduino timer - и получаешь кучу ссылок
Увы с языками лажа поэтому в английские форумы и сайты лезу когда уж вообще ничего нет...
ну вы ж даташит и описание библиотеки уже читали - форумы не сложнее.
А с русским языком голяк - по СТМ32 почти ничего нет
Господа! Вопрос в скользь темы: подскажите возможно ли каждый канал таймера настроить на "свою частоту", 1 на 1МГц, 2 - 100КГц и тд. пооможет выставления нового значения Compare в прервывании по данному каналу для того чтобы вызвать срабатывание несколько раз в течении цикла (до переполнения счетчика таймера)?
поменять значение регистра сравнения в прерывании можно. можно ли таким образом вызывать несколько прерываний за один период счета, будет зависить от того, в каком состоянии находится бит OCnPE регистра TIMx_CCMRn. Если бит в нуле, то новое значение регистра сравнения становится актуальным немедленно и следующее прерывание возможно, когда значения счетчика и регистра сравнения совпадут вновь . Если в единице, то только после переполнения счетчика и тут никакой множественности не будет.
где найти описаниие функций библиотеки HardwareTimer