使用Platformio平台的libopencm3开发框架来开发STM32G0,以下为定时器timer的基本使用方法。 - m9 p' @# _/ a& m* [ l
1 新建项目在PIO主页新建项目timer,框架选择libopencm3,开发板选择 MonkeyPi_STM32_G070RB; 新建完成后在src目录新建主程序文件main.c; 然后更改项目文件platformio.ini的烧写和调试方式: 6 J8 p- T! G) w+ l, C, J9 _
- 1upload_protocol = cmsis-dap
9 m( P, L3 n5 e- p2 D0 n9 ^ - 2debug_tool = cmsis-dap
复制代码
1 e8 g- u7 ~6 i2 X) A; a1 O6 ], C' a k6 ^9 i" V8 i
2 使用基本定时器定时器设置
) _' L. D% y1 U% j$ c, B6 z- W/ s+ v
以下为设置定时器3的过程: - 1static void timer_setup(void)( n/ z* e4 K" h$ a% p* w
- 2{
5 K( e2 ]. J3 l3 Z( A - 3 /* Enable TIM3 clock. */
6 x" H1 K l; e. h8 [0 q - 4 rcc_periph_clock_enable(RCC_TIM3);
Q3 k$ c; R( y9 `) M; k5 b- d0 b - 58 j) T" j9 }# H; F6 z7 Y
- 6 /* Enable TIM3 interrupt. */. Q- D2 e7 a3 ^
- 7 nvic_enable_irq(NVIC_TIM3_IRQ);
' j& E0 v. q4 b [3 C - 8
4 U' G& W2 L0 T8 N% o$ g. G! ^0 G - 9 /* Timer global mode:8 r0 M2 Z6 v4 F: H# ~3 O5 q N
- 10 * - No divider# O. P. o" S) d3 y) B
- 11 * - Alignment edge$ U0 D1 o6 Y5 g/ q4 }3 ~
- 12 * - Direction up X5 v- c: Y# k/ v3 @4 y3 R+ ?
- 13 */7 m0 V4 H1 T( k t/ w+ F5 C
- 14 timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT,
1 y. @' ?: ]- A3 K9 { - 15 TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
& v4 s6 I4 _! i* s Z$ ^6 ]# L* | - 16
* h4 s5 `# V: q) W7 C - 17 /*
) I9 x0 _: [# B - 18 * APB1 PRE = 1, TIMPCLK = PCLK& [0 e# t2 W7 M/ v1 {! R( N8 B- R6 M
- 19 * APB1 PRE != 1, TIMPCLK = PCLK * 2; J9 L+ t+ M1 K, D
- 20 */
7 E9 i N" f# g9 W - 21 timer_set_prescaler(TIM3, (rcc_apb1_frequency/100000-1)); //100KHz
& M2 P; z+ v1 ?. Z! o - 22
4 f8 H( i) H" N7 d - 23 /* Disable preload. */
% c" H- ~6 z. M - 24 timer_disable_preload(TIM3);1 S+ p Y$ D/ q, K2 B' d% R
- 25 timer_continuous_mode(TIM3);
: }3 B/ a1 c$ [; b) k d* A# m8 Z- B - 26
- {2 F! W' q) M, U' {! ~ - 27 /* Timer Period */
?+ u/ k+ _) D: q; S$ G - 28 timer_set_period(TIM3, 20000-1); /* 100kHz /20_000 = 5 Hz */
; W. ^0 H# E% G# \! |/ s0 g - 290 p6 U0 ^0 W9 A
- 30 /* Counter enable. */1 j2 i- ?. t# [
- 31 timer_enable_counter(TIM3);! z; `* _# [" g0 w8 X5 t1 _
- 32' K g. O3 B, k8 _! c/ S4 K, N- q& G
- 33 timer_enable_irq(TIM3, TIM_DIER_UIE);
5 B# @8 U1 _; R& }% ]8 ~ - 34}
复制代码 2 y! c! B1 H# D7 `$ M! v" \+ a# T
包括设置定时器的模式,使能定时器中断,定时器的中断频率通过 timer_set_prescaler 设置分频值和 timer_set_period 设置周期值,上面需要注意的是 timer_set_prescaler 设置分频值需要根据系统设置的时钟,如果APB1的分频为1,则TIM外设时钟和APB1相同,否则为其2倍,这里由于系统设置的时钟为64MHz,即APB1预分频为1,因此这里设置TIM分频为 rcc_apb1_frequency/100000-1,即100KHz;然后timer_set_period设置定时器周期为 20000-1,那么定时器中断频率为5Hz; ) F" F3 |8 W% c/ m& i$ }8 F0 Z
定时器中断 1 k9 N- H0 y, p* `0 y4 @
- 1void tim3_isr(void)
" a* v J" H U+ ]1 c - 2{
) I. v- R$ b t+ H4 f& T! |3 n - 3 if(timer_get_flag(TIM3, TIM_SR_UIF)) {
. I _8 f! t$ w1 O% v* j+ v - 4 /* Clear compare interrupt flag. */0 Y) A1 w6 z: j- H. @( o
- 5 timer_clear_flag(TIM3, TIM_SR_UIF);; {- h# T4 s: e/ S3 k
- 6: A M i! A! p+ _: C* M
- 7 gpio_toggle(GPIOB,GPIO4);
' U: }: W" F2 B) L& d" F! `* G - 8 }' F; I! ?) K5 w
- 9}
复制代码
$ C, z5 z% E4 C- L: I V; C( t8 E5 y9 G/ r) t: K
这里直接在中断中对GPIO进行翻转,即5Hz翻转一次GPIO,即200ms进行高低变化;
8 L2 y5 k. I; ~# V
烧写测试
$ a2 ]- o* D+ U- y" G2 t! ?
将程序烧写到开发板后,测量频率可以看到和预期一致: ) ~$ |, i( S8 S% f# H2 m9 R) V
, z* w4 e& C. A% t% J3 Q% u3 使用systick定时器3.1 systick 定时器设置- N5 U4 w a; e- x9 E
- 1static void systick_setup(void)% L( K% `$ }/ i2 Y2 D4 ], K2 v
- 2{$ t! M+ d1 U* d ~# M3 J1 N9 _
- 3 /* clock rate / 1000 to get 1mS interrupt rate */
7 H# w+ ]5 ?7 x% T0 r4 Q0 _7 b - 4 systick_set_reload(64000);6 F" ^! j, x0 x0 m; B0 a
- 5 systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
2 R, x9 c) D5 g- m2 W/ \ - 6 systick_counter_enable();% [" S( {" Q( y1 E+ H3 P
- 7 /* this done last */
- H4 s+ U! t' A2 p$ \ - 8 systick_interrupt_enable();
9 x( \$ G" ~& {8 ]4 I5 L8 | E - 9}
复制代码
# |5 K1 U/ @0 e& k3 [. B这里设置systick重载值为64000,因为系统设置时钟为64MHz,那么定时器的频率为1KHz,即1ms时间定时中断;
, m, ?, H* v l) }* x" ~ \ 3.2 systick 定时器中断0 n6 n7 d2 A( y
- 1volatile uint32_t tick_counter = 0;9 N2 d N8 h$ }( S
- 2$ \3 t/ J) |( d# X v8 E5 U
- 3void sys_tick_handler(void)
5 |9 `* M; `. j" l2 K; j - 4{% p( f$ g' O6 v# `
- 5 tick_counter++;! v. ] I: G W; D. g: ^
- 6}
复制代码
! @) l$ V1 d( C+ D' a
' _- c8 a% z$ w' Z- ~2 \1 w这里在中断函数里进行计数; ' e5 c" J ^ X( j& Y
3.3 使用一般这个systick定时器在cortex-m芯片中都存在,因此比较通用,可以用作RTOS的时基或用作延时功能,比如根据上面的tick_counter计数可以实现类似Arduino中的millis方式编程: - 1uint32_t millis(void)
! R+ y8 H! Z$ }" Y - 2{7 ` d8 E) |' y' p1 I9 a6 w
- 3 return tick_counter;0 C r, q k5 X) K9 Z; b; M/ z
- 4}
复制代码
- W- a/ ^$ s' ?$ v, \9 [
+ d1 t! A. P( `& e& B. u7 D使用millis进行延时 ; [2 R9 B7 I+ O. s4 \9 P: _
- 1uint32_t lastTime = millis();
/ N: i3 F: p1 [, e5 G+ Q' M7 u - 2while(1){- P0 |+ i# r/ y2 S! W6 F
- 3 if( (millis() - lastTime) > 500) {
0 e) Q# z" p2 W - 4 lastTime = millis();3 x2 m" x3 P" Z$ z! }
- 5
, z# M) y- O- n: q - 6 gpio_toggle(GPIOB,GPIO4);' b; L2 C$ }' U4 Z" Z9 ~* e6 Y
- 7 }$ O0 l4 b) s, I
- 86 x8 a8 h# F: Y- Q4 j, D8 w9 w% R
- 9 ...
5 i1 G8 u# F% ~% b8 s2 i% D+ V - 10}
复制代码 - i2 ]. D/ O: x) Z0 m, m
* E0 ~0 n3 x! M6 p+ V7 S2 i
这样就达到500ms的延时,而且不会对其他语句的执行造成影响;
' m `" {" G, B4 y& a% ^
转载自: MakerInChina.cn
" k7 `: r" G: b0 M! a
4 H8 n( K: I' S8 U1 a* S/ | |