Stm32 прерывание по сравнению в таймере

a_l_e_x_Z
Offline
Зарегистрирован: 09.11.2017

Хочу освоить таймеры в 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() {
}

 

a_l_e_x_Z
Offline
Зарегистрирован: 09.11.2017

Утро вечера мудренее) Все работает. Список задекларированных параметров нашел здесь-  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() {
}

 

b707
Offline
Зарегистрирован: 26.05.2017

простите, раз уж вы используете высокоуровневую функцию 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 {
}

 

a_l_e_x_Z
Offline
Зарегистрирован: 09.11.2017

Это первое знакомство с таймерами stm32 поэтому решил начать снизу чтоб понять как они работают и до конфигурирования на более высоком уровне я еще просто не добрался, ну и так как информации и примеров по работе с stm в среде ардуино очень мало то слепил как сумел используя примеры конфигурации таймеров stm под keil)
А есть какой-то более низкоуровневый способ объявления прерывания чем timer_attach_interrupt?
Из какой документации ваш пример?
 

b707
Offline
Зарегистрирован: 26.05.2017

документации и примеров очень много на http://www.stm32duino.com/

да и вообще - просто в гугле набираешь stm32 arduino timer - и получаешь кучу ссылок

a_l_e_x_Z
Offline
Зарегистрирован: 09.11.2017

Увы с языками лажа поэтому в английские форумы и сайты лезу когда уж вообще ничего нет...

b707
Offline
Зарегистрирован: 26.05.2017

ну вы ж даташит и описание библиотеки уже читали - форумы не сложнее.

А с русским языком голяк - по СТМ32 почти ничего нет

captgreen
Offline
Зарегистрирован: 18.08.2018

Господа! Вопрос в скользь темы: подскажите возможно ли каждый канал таймера настроить на "свою частоту", 1 на 1МГц, 2 - 100КГц и тд. пооможет выставления нового  значения Compare в прервывании по данному каналу для того чтобы вызвать срабатывание несколько раз в течении цикла (до переполнения счетчика таймера)?

a5021
Offline
Зарегистрирован: 07.07.2013

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

sidorenko61
Offline
Зарегистрирован: 28.09.2018

где найти описаниие функций библиотеки HardwareTimer