mirror of
https://github.com/eddyem/stm32samples.git
synced 2025-12-06 18:55:13 +03:00
118 lines
3.3 KiB
C
118 lines
3.3 KiB
C
/*
|
|
* timer.c
|
|
*
|
|
* Copyright 2016 Edward V. Emelianov <eddy@sao.ru, edward.emelianoff@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "timer.h"
|
|
#include "user_proto.h" // for print_int
|
|
|
|
// current speed
|
|
uint16_t current_RPM = 0;
|
|
void get_RPM();
|
|
uint16_t get_ARR(uint32_t RPM);
|
|
|
|
// pulses: 16 1/0, 4 1/1, 16 1/0, 4 0/0,
|
|
const uint8_t pulses[] = {
|
|
1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
|
|
1,1,1,1,1,1,1,1,
|
|
1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
|
|
0,0,0,0,0,0,0,0};
|
|
const int pulsesLen = sizeof(pulses) - 1;
|
|
|
|
void tim2_init(){
|
|
// init TIM2
|
|
rcc_periph_clock_enable(RCC_TIM2);
|
|
timer_reset(TIM2);
|
|
// timer have frequency of 1MHz
|
|
timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
|
|
// 72MHz div 36 = 2MHz
|
|
TIM2_PSC = 35; // we need double freq to serve both halfs of signal
|
|
TIM2_ARR = get_ARR(MIN_RPM);
|
|
TIM2_DIER = TIM_DIER_UDE | TIM_DIER_UIE;
|
|
nvic_enable_irq(NVIC_TIM2_IRQ);
|
|
TIM2_CR1 |= TIM_CR1_CEN;
|
|
get_RPM();
|
|
}
|
|
|
|
void tim2_isr(){
|
|
static uint16_t ctr = 0;
|
|
if(TIM2_SR & TIM_SR_UIF){ // update interrupt
|
|
if(ctr > pulsesLen) ctr = 0;
|
|
if(pulses[++ctr])
|
|
GPIO_BSRR(OUTP_PORT) = OUTP_PIN;
|
|
else
|
|
GPIO_BSRR(OUTP_PORT) = OUTP_PIN << 16;
|
|
}
|
|
TIM2_SR = 0;
|
|
}
|
|
|
|
/**
|
|
* Calculate motor speed in RPM
|
|
* RPM = 1/tim2_arr / 40 * 60
|
|
*/
|
|
void get_RPM(){
|
|
uint32_t R = 3000000 / (uint32_t)TIM2_ARR;
|
|
current_RPM = R/2;
|
|
//current_RPM = R;
|
|
//current_RPM >>= 1; // x/2 != x>>1, WTF?
|
|
}
|
|
|
|
// calculate TIM2_ARR by RPM
|
|
uint16_t get_ARR(uint32_t RPM){
|
|
uint32_t R = 3000000 / RPM;
|
|
R /= 2;
|
|
//R >>= 1;
|
|
return (uint16_t)R;
|
|
}
|
|
|
|
/**
|
|
* Change "rotation speed" by 100rpm
|
|
*/
|
|
void increase_speed(){
|
|
if(current_RPM == MAX_RPM) return;
|
|
current_RPM += 100;
|
|
if(current_RPM > MAX_RPM){ // set LED "MAX"
|
|
current_RPM = MAX_RPM;
|
|
TIM2_ARR = get_ARR(current_RPM);
|
|
gpio_clear(LEDS_PORT, LED_UPPER_PIN);
|
|
}else{
|
|
TIM2_ARR = get_ARR(current_RPM);
|
|
get_RPM(); // recalculate speed
|
|
gpio_set(LEDS_PORT, LED_UPPER_PIN);
|
|
}
|
|
gpio_set(LEDS_PORT, LED_LOW_PIN);
|
|
print_int(current_RPM);
|
|
}
|
|
|
|
void decrease_speed(){
|
|
if(current_RPM == MIN_RPM) return;
|
|
current_RPM -= 100;
|
|
if(current_RPM < MIN_RPM){ // set LED "MIN"
|
|
current_RPM = MIN_RPM;
|
|
TIM2_ARR = get_ARR(current_RPM);
|
|
gpio_clear(LEDS_PORT, LED_LOW_PIN);
|
|
}else{
|
|
TIM2_ARR = get_ARR(current_RPM);
|
|
get_RPM();
|
|
gpio_set(LEDS_PORT, LED_LOW_PIN);
|
|
}
|
|
gpio_set(LEDS_PORT, LED_UPPER_PIN);
|
|
print_int(current_RPM);
|
|
}
|