ASCII Serial Com
Serial communication library between computers, microcontrollers, FPGAs, etc. Uses only ASCII. Not the most efficient protocol, but meant to be easy to read
Loading...
Searching...
No Matches
stm_timers.h
Go to the documentation of this file.
1#ifndef STM_TIMERS_H
2#define STM_TIMERS_H
3
4/** \file
5 *
6 * \brief To be used with the timer peripherals on STM32 microcontrollers
7 *
8 * */
9
10#include <libopencm3/stm32/gpio.h>
11#include <libopencm3/stm32/timer.h>
12#include <stdint.h>
13
14/** \brief Initialize a timer to output a periodic pulse on an output pin
15 *
16 * This really just sets up a timer in edge-aligned PWM mode.
17 *
18 * ## Notes
19 *
20 * **The user must setup the peripheral clocks for both this timer and the
21 * output port.**
22 *
23 * **The user must enable the counter when ready with:**
24 * `timer_enable_counter(<timer>);`
25 *
26 * **This macro takes care of setting up the GPIO pin.**
27 *
28 * Uses output compare unit 1 on the timer. Make sure this is available on the
29 * timer.
30 *
31 * Sets timer in: upcount, edge-aligned, not one-pulse mode, using the
32 * un-divided peripheral clock as input to the prescaler. This should be
33 * available on all general-purpose timers.
34 *
35 * ## Registers Relevant to Ascii-Serial-Com
36 *
37 * `TIM_ARR(<timer>)`: which should be set to period in timer ticks
38 *
39 * `TIM_CCR1(<timer>)`: which should be set to pulse_length in timer ticks
40 *
41 * `TIM_PSC(<timer>)`: which should be set to the prescaler value in peripheral
42 * clock ticks
43 *
44 * ## Parameters
45 *
46 * timer: the timer you want to use like TIM2
47 *
48 * prescale: the number of peripher clock ticks between timer ticks, uint32_t
49 * (but only ever 16 bit)
50 *
51 * period: The number of timer ticks between pulse rising edges, uint32_t
52 *
53 * pulse_length: length of pulse in timer ticks, uint32_t
54 *
55 * output: the output compare output to use: TIM_OC1, TIM_OC2, TIM_OC3, TIM_OC4
56 * (availability depends on timer)
57 *
58 * gpio_port: GPIOA, GPIOB, ... (must match output)
59 *
60 * gpio_pin: GPIO0, GPIO1, ... (must match output)
61 *
62 * gpio_af: alternate function for the given pin/port and output, e.g.
63 * GPIO_AF0, GPIO_AF1, ...
64 *
65 */
66#define setup_timer_periodic_output_pulse(timer, prescale, period, \
67 pulse_length, output, gpio_port, \
68 gpio_pin, gpio_af) \
69 gpio_mode_setup(gpio_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_pin); \
70 gpio_set_output_options(gpio_port, GPIO_OTYPE_PP, GPIO_OSPEED_HIGH, \
71 gpio_pin); \
72 gpio_set_af(gpio_port, gpio_af, gpio_pin); \
73 timer_set_mode(timer, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); \
74 timer_set_oc_mode(timer, output, TIM_OCM_PWM1); \
75 timer_enable_oc_output(timer, output); \
76 TIM_PSC(timer) = prescale; \
77 TIM_ARR(timer) = period; \
78 TIM_CCR1(timer) = pulse_length
79
80/** \brief Initialize a timer to capture periodic pulses on an input pin
81 *
82 * This really just sets up a timer for PWM input capture
83 *
84 * ## Usage
85 *
86 * The pulse period should be available in TIM_CCR1(<timer>) in timer ticks
87 *
88 * The pulse length should be available in TIM_CCR2(<timer>) in timer ticks
89 *
90 * So duty cycle is TIM_CCR2(<timer>) / TIM_CCR1(<timer>)
91 *
92 * Polling: `bool flag = timer_get_flag(<timer>,TIM_SR_CC1IF);`, if true read
93 * out `TIM_CCR2(<timer>)` and `TIM_CCR1(<timer>)`, then check the overcapture
94 * bits: `timer_get_flag(<timer>,TIM_SR_CC1OF) &&
95 * timer_get_flag(<timer>,TIM_SR_CC2OF)`.
96 *
97 * Interrupt: Setup the interrupt on CC1:
98 * `timer_enable_irq(<timer>,TIM_DIER_CC1IE)`, then in the handler read out
99 * both CCRs and then check the overcapture bits:
100 * `timer_get_flag(<timer>,TIM_SR_CC1OF) &&
101 * timer_get_flag(<timer>,TIM_SR_CC2OF)`
102 *
103 * DMA: ?
104 *
105 * If overcapture happens, you have to clear the flag with
106 * `timer_clear_flag(<timer>,TIM_SR_CC1OF)` or
107 * `timer_clear_flag(<timer>,TIM_SR_CC2OF)`.
108 *
109 * ## Notes
110 *
111 * **The user must setup the peripheral clocks for both this timer and the
112 * input port.**
113 *
114 * **The user must enable the counter when ready with:**
115 * `timer_enable_counter(<timer>);`
116 *
117 * **Uses input compare channels 1 and 2, so timer must have 2 IC units!**
118 *
119 * **This macro takes care of setting up the GPIO pin.**
120 *
121 * Sets timer in: upcount, edge-aligned, not one-pulse mode, using the
122 * un-divided peripheral clock as input to the prescaler. This should be
123 * available on all general-purpose timers.
124 *
125 * ## Registers Relevant to Ascii-Serial-Com
126 *
127 * `TIM_PSC(<timer>)`: which should be set to the prescaler value in peripheral
128 * clock ticks
129 *
130 * `TIM_CCR1(<timer>)`: read the pulse period in timer ticks
131 *
132 * `TIM_CCR2(<timer>)`: read the pulse length in timer ticks
133 *
134 * ## Parameters
135 *
136 * timer: the timer you want to use like TIM2
137 *
138 * prescale: the number of peripher clock ticks between timer ticks, uint32_t
139 * (but only ever 16 bit)
140 *
141 * max_timer_counts: you probably want 0xFFFF for 16 bit counters and
142 * 0xFFFFFFFF for 32 bit ones.
143 *
144 * input: which input compare input: TIM_IC_IN_TI1, TIM_IC_IN_TI2,
145 * TIM_IC_IN_TI3 or TIM_IC_IN_TI4 (don't quote; some not avaiable on all
146 * timers)
147 *
148 * gpio_port: GPIOA, GPIOB, ... (must match input)
149 *
150 * gpio_pin: GPIO0, GPIO1, ... (must match input)
151 *
152 * gpio_af: alternate function for the given pin/port and input, e.g.
153 * GPIO_AF0, GPIO_AF1, ...
154 *
155 */
156#define setup_timer_capture_pwm_input(timer, prescale, max_timer_counts, \
157 input, gpio_port, gpio_pin, gpio_af) \
158 gpio_mode_setup(gpio_port, GPIO_MODE_AF, GPIO_PUPD_NONE, gpio_pin); \
159 gpio_set_af(gpio_port, gpio_af, gpio_pin); \
160 timer_set_mode(timer, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); \
161 timer_ic_set_input(timer, TIM_IC1, input); \
162 timer_ic_set_polarity(timer, TIM_IC1, TIM_IC_RISING); \
163 timer_ic_set_input(timer, TIM_IC2, input); \
164 timer_ic_set_polarity(timer, TIM_IC2, TIM_IC_FALLING); \
165 timer_slave_set_trigger(timer, TIM_SMCR_TS_TI1FP1); \
166 timer_slave_set_mode(timer, TIM_SMCR_SMS_RM); \
167 timer_ic_enable(timer, TIM_IC1); \
168 timer_ic_enable(timer, TIM_IC2); \
169 TIM_PSC(timer) = prescale; \
170 TIM_ARR(timer) = max_timer_counts
171
172#endif