1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include "stm32f10x_rcc.h"
#include "wiring.h"
#include "timers.h"
#include "util.h"
typedef struct {
volatile uint16_t CR1;
uint16_t RESERVED0;
volatile uint16_t CR2;
uint16_t RESERVED1;
volatile uint16_t SMCR;
uint16_t RESERVED2;
volatile uint16_t DIER;
uint16_t RESERVED3;
volatile uint16_t SR;
uint16_t RESERVED4;
volatile uint16_t EGR;
uint16_t RESERVED5;
volatile uint16_t CCMR1;
uint16_t RESERVED6;
volatile uint16_t CCMR2;
uint16_t RESERVED7;
volatile uint16_t CCER;
uint16_t RESERVED8;
volatile uint16_t CNT;
uint16_t RESERVED9;
volatile uint16_t PSC;
uint16_t RESERVED10;
volatile uint16_t ARR;
uint16_t RESERVED11;
volatile uint16_t RCR;
uint16_t RESERVED12;
volatile uint16_t CCR1;
uint16_t RESERVED13;
volatile uint16_t CCR2;
uint16_t RESERVED14;
volatile uint16_t CCR3;
uint16_t RESERVED15;
volatile uint16_t CCR4;
uint16_t RESERVED16;
volatile uint16_t BDTR; // Not used in general purpose timers
uint16_t RESERVED17; // Not used in general purpose timers
volatile uint16_t DCR;
uint16_t RESERVED18;
volatile uint16_t DMAR;
uint16_t RESERVED19;
} Timer;
void timer_init(uint8_t timer_num, uint16_t prescale) {
Timer *timer;
uint32_t is_advanced = 0;
ASSERT(timer_num > 0 && timer_num <= 4);
switch(timer_num) {
case 1:
timer = (Timer*)TIMER1_BASE;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
is_advanced = 1;
break;
case 2:
timer = (Timer*)TIMER2_BASE;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
break;
case 3:
timer = (Timer*)TIMER3_BASE;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
break;
case 4:
timer = (Timer*)TIMER4_BASE;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
break;
}
timer->CR1 = ARPE; // No clock division
// Do not buffer auto-reload preload
// Edge aligned
// Upcounter
// Do not stop counter at update event
// Update events enabled (etc, see bits [1:2])
// Counter disabled for now
timer->PSC = prescale; // Prescaling by prescale (duh)
timer->ARR = 0xFFFF; // Max reload cont
/* initialize all the channels to 50% duty cycle,
* TODO: none of them actually get output unless the gpio pin
* is set, this will probably consume a bit more power but
* we'll worry about that later. */
timer->CCR1 = 0x8FFF; // PWM start value
timer->CCMR1 |= 0x68; // PWM mode 1, enable preload register.
timer->CCER |= 0x001; // enable ch
timer->CCR2 = 0x8FFF; // PWM start value
timer->CCMR1 |= (0x68 << 8);// PWM mode 1, enable preload register.
timer->CCER |= 0x010; // enable ch
timer->CCR3 = 0x8FFF; // PWM start value
timer->CCMR2 |= 0x68; // PWM mode 1, enable preload register.
timer->CCER |= 0x100; // enable ch
timer->CCR4 = 0x8FFF; // PWM start value
timer->CCMR2 |= (0x68 << 8);// PWM mode 1, enable preload register.
timer->CCER |= 0x1000; // enable ch
/* Advanced timer? */
if (is_advanced) {
timer->BDTR = 0x8000; // moe enable
}
timer->DIER = 0; // disable update interrupt
timer->EGR = 1; // Initialize update event and shadow registers
timer->CR1 |= 1; // Enable timer
}
|