使用Platformio平台的libopencm3开发框架来开发STM32G0,以下为定时器timer的基本使用方法。 + w9 r5 Y6 H$ d& d" ~; X* }
1 新建项目在PIO主页新建项目timer,框架选择libopencm3,开发板选择 MonkeyPi_STM32_G070RB; 新建完成后在src目录新建主程序文件main.c; 然后更改项目文件platformio.ini的烧写和调试方式:
! |& X: p* U- M: C4 C% S. F
- 1upload_protocol = cmsis-dap
, z) l+ `" E& S$ l+ e - 2debug_tool = cmsis-dap
复制代码
, b& d8 R/ ^; P2 \+ r8 V
" p! n8 }6 ]7 v! Y6 ]! I4 h2 使用基本定时器定时器设置 # [1 G7 \' N6 k; w$ }8 N
以下为设置定时器3的过程: - 1static void timer_setup(void)
: v6 G2 x; l" \! |% @. K& u - 2{# v" z/ J1 n" m$ K3 }0 @- ?: E X
- 3 /* Enable TIM3 clock. */; ]0 {7 X v2 ] O- _& N
- 4 rcc_periph_clock_enable(RCC_TIM3);# j+ _9 {- o! o# M1 W8 A2 W: ^
- 5
I: O. s# u. _, `( K$ G' ]1 J# j - 6 /* Enable TIM3 interrupt. */
7 B& Z/ } a, y7 }1 b& P' a e - 7 nvic_enable_irq(NVIC_TIM3_IRQ);
. S3 x3 G V! d - 8# D; P4 x2 Q* i
- 9 /* Timer global mode:
* W+ e( c; P0 e5 [ - 10 * - No divider6 T4 R9 h+ P6 W3 [8 o. R4 l7 v t
- 11 * - Alignment edge
2 G, G* c6 W# `4 u8 H - 12 * - Direction up* R. }% C) K5 E- t
- 13 */
4 ?6 d2 t7 u% g3 a( o* D - 14 timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT,
- z3 F7 Z8 ]) v- p6 b - 15 TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
1 K- R1 B1 P) p' g" q/ M d - 16
$ ?" m# ?. V* k - 17 /*
7 j: g& Y: ~( g4 p0 E - 18 * APB1 PRE = 1, TIMPCLK = PCLK' t: W" T7 J$ U9 r2 I5 y% W
- 19 * APB1 PRE != 1, TIMPCLK = PCLK * 21 G5 w! }( e. R0 ~8 p$ N
- 20 */, |, u/ E5 a2 ~
- 21 timer_set_prescaler(TIM3, (rcc_apb1_frequency/100000-1)); //100KHz! k4 o# c! ?. w& |1 B, P# [
- 22
P% L2 t! D: j7 }0 N u. ` - 23 /* Disable preload. */
8 m3 w+ f" {3 z; b" Z. e7 b4 w* X, g - 24 timer_disable_preload(TIM3);
7 x5 ~9 {- ], i% s5 c" L( ] - 25 timer_continuous_mode(TIM3);
4 R3 \) G' f1 p8 F" _ - 26* p! W. S/ m/ \. u- g4 q/ H" ~
- 27 /* Timer Period */
, s. ~: d7 ?. ` - 28 timer_set_period(TIM3, 20000-1); /* 100kHz /20_000 = 5 Hz */' {7 W5 ]( `( D- T/ u+ ^5 C
- 29( u4 @- Y: m) A/ A: e k
- 30 /* Counter enable. */) o8 }1 y4 n, H1 c: I
- 31 timer_enable_counter(TIM3);* s, M: z( q# E3 [8 s/ I
- 324 G9 S( F/ X. g. L! @0 S) }( B. b
- 33 timer_enable_irq(TIM3, TIM_DIER_UIE);5 I% x% i4 O% u& Y
- 34}
复制代码
! } L3 q) |( H% k9 \6 M$ E包括设置定时器的模式,使能定时器中断,定时器的中断频率通过 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;
* ?$ |- d' U6 b( a0 V5 c: S
- 1void tim3_isr(void)
6 y+ H o, s' h0 E% @ - 2{! B$ Y* j9 u* V7 B) }
- 3 if(timer_get_flag(TIM3, TIM_SR_UIF)) {
9 {& G+ {! i5 p; F1 D; @+ h - 4 /* Clear compare interrupt flag. */9 W- O4 L* Q) t5 }7 T" b$ n" }
- 5 timer_clear_flag(TIM3, TIM_SR_UIF);
' ]# T# m0 [& K - 6; {/ C) D3 w; Z1 G2 }; T
- 7 gpio_toggle(GPIOB,GPIO4);
# D: Z3 i/ D6 \6 W0 ?. U8 X+ u' L; z - 8 }% p# P! h- o( ]/ \
- 9}
复制代码
/ @" D7 L, ^ |9 M# W
. T0 T7 q" x8 ^# @' ~. E) z这里直接在中断中对GPIO进行翻转,即5Hz翻转一次GPIO,即200ms进行高低变化;
; L/ M8 d% e& C5 [
烧写测试
% z$ W0 ~. I5 Z4 _/ r& J) F
将程序烧写到开发板后,测量频率可以看到和预期一致:
/ _* Z# \' _7 e: W5 a0 U7 w2 d
3 t1 ?& Z: r' P3 使用systick定时器3.1 systick 定时器设置1 A+ \( O! `& Y# W) e; E
- 1static void systick_setup(void)
8 K. u1 n9 |6 y O% v4 V( C4 ~ F - 2{
+ J- c6 `" u- Y* t8 l, B- Q - 3 /* clock rate / 1000 to get 1mS interrupt rate */
. b; Q" @3 I3 O3 {: I - 4 systick_set_reload(64000);8 f! ?( `6 L8 c( `6 Y: |$ X: {
- 5 systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);6 r, |: a8 O9 Z: a( q& \
- 6 systick_counter_enable();: e i c4 ^" Y% p7 w
- 7 /* this done last */0 N# K8 q; _! `
- 8 systick_interrupt_enable();+ U! L: d4 q6 H! ^
- 9}
复制代码 9 _" z0 [( Y" T$ A3 a
这里设置systick重载值为64000,因为系统设置时钟为64MHz,那么定时器的频率为1KHz,即1ms时间定时中断; ; A! i$ b; f0 o' L9 `% ^' n
3.2 systick 定时器中断
3 p+ t( e) {7 B. n. A; H: K4 I: u# y- 1volatile uint32_t tick_counter = 0;
! s5 w8 P9 n/ e1 j. ~9 ^4 b& W, U - 2
2 T6 J6 ?6 e) V+ O' U- ] - 3void sys_tick_handler(void)0 b! T4 H1 g; V7 r) a, B
- 4{
% _+ }; k7 @! a! B) W3 P& p - 5 tick_counter++;
0 v: f0 p. X# S9 h& ]" A - 6}
复制代码
" f0 ~, F7 ^2 G! U4 }0 y$ `
6 f# n$ S5 i( l) J9 ~& l* l7 Z这里在中断函数里进行计数; # B) r; x$ p' F5 E0 S: y& s
3.3 使用一般这个systick定时器在cortex-m芯片中都存在,因此比较通用,可以用作RTOS的时基或用作延时功能,比如根据上面的tick_counter计数可以实现类似Arduino中的millis方式编程: - 1uint32_t millis(void)# ^! s) p# V$ I4 s6 w
- 2{
8 k0 a1 a- U+ G; \ - 3 return tick_counter;" Y/ Z t% V; c! m3 O7 P- }9 \, C
- 4}
复制代码
2 r: b5 G. }; }- A& B- g9 k" e; Y7 }0 g! F9 l9 e0 t2 C
使用millis进行延时
/ s+ ]6 O3 g; K7 G$ s1 {0 N
- 1uint32_t lastTime = millis();5 }0 b, m5 N% m. f$ o6 q" F5 |8 C
- 2while(1){1 L& J, G& A" i
- 3 if( (millis() - lastTime) > 500) {
( r% j3 A) Q8 ]- c$ Y' ` - 4 lastTime = millis();
8 W3 @6 `8 F3 y% V: Z9 |% W0 v - 5
& n8 Q6 [5 B- A - 6 gpio_toggle(GPIOB,GPIO4);: m' b- z3 n1 }& v! x4 R1 }) K
- 7 }4 _, Z: `% Z# p: J4 U
- 8
" k% D0 M9 i! _# A - 9 ...
1 W8 I) Q9 d9 V; z0 e. W# x o2 ? - 10}
复制代码 . v( H' q! I) P5 s c N* `( H
/ w4 y' A" r8 t% q7 [4 z1 @这样就达到500ms的延时,而且不会对其他语句的执行造成影响; 4 a! I5 T4 l9 B3 ^
转载自: MakerInChina.cn & b7 G# L7 _. E3 }; m& H
; Q2 f- n4 V8 ?$ X/ |
|