|
使用Platformio平台的libopencm3开发框架来开发STM32G0,以下为定时器timer的基本使用方法。
4 l) @! [# w+ X 1 新建项目在PIO主页新建项目timer,框架选择libopencm3,开发板选择 MonkeyPi_STM32_G070RB; 新建完成后在src目录新建主程序文件main.c; 然后更改项目文件platformio.ini的烧写和调试方式: 3 x, K% K8 p! X2 y
- 1upload_protocol = cmsis-dap
+ b9 \; Q* F& R( @- I - 2debug_tool = cmsis-dap
复制代码
- J$ {! ?1 t! k' W* @3 y; e* @
, N% T7 y8 ~0 y4 L$ Z/ W2 使用基本定时器以下为设置定时器3的过程: - 1static void timer_setup(void)
# L9 |3 } _9 N) [ - 2{
- D% ?- a; c( A2 I2 @7 R - 3 /* Enable TIM3 clock. */
W3 `5 s3 l( G$ Q' K, q( U0 Z' o - 4 rcc_periph_clock_enable(RCC_TIM3);0 [! n( n& y: e& k* S
- 5
$ G. x9 m1 p& J& }* E: X - 6 /* Enable TIM3 interrupt. */+ ]5 X1 r* Q* N& O) x+ u: U
- 7 nvic_enable_irq(NVIC_TIM3_IRQ);0 [+ s& `, n9 T, y, A
- 8
9 [1 `4 E# g2 Y7 C; I! N' |# e - 9 /* Timer global mode:# i9 X; |! f' Z7 w
- 10 * - No divider
5 l6 i' }5 m- F" c: { B) _ - 11 * - Alignment edge
! _7 F1 H6 L. l! R8 V5 }& U - 12 * - Direction up, x3 [0 S, m( E t# Q5 C
- 13 */5 m7 b$ j7 N$ e& J! a* C
- 14 timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT,
. ?2 [( Q4 l* h0 F: h5 ` - 15 TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
; v% `' ], q5 D' W+ N2 W! h# B - 16) b1 t' |/ k" _7 _ [
- 17 /*
7 [1 t& L; n: U8 t8 C i - 18 * APB1 PRE = 1, TIMPCLK = PCLK! f' r, b# |. n* j. E( m
- 19 * APB1 PRE != 1, TIMPCLK = PCLK * 2! v9 C3 `! q. B# K& x
- 20 */7 `6 D+ v* W" x+ U' _, Q- a; p
- 21 timer_set_prescaler(TIM3, (rcc_apb1_frequency/100000-1)); //100KHz, s$ S6 x; B, u
- 22( U+ [# {/ F" C2 t8 x/ w" S
- 23 /* Disable preload. *// P" N; C* V# y: v+ R
- 24 timer_disable_preload(TIM3);4 V# k- ?0 F* z& n' f
- 25 timer_continuous_mode(TIM3);9 R6 M" f4 ]. F5 a1 E
- 263 E/ N) \6 M& X8 d
- 27 /* Timer Period */
1 ~' n/ o9 }, v P3 J% q1 E - 28 timer_set_period(TIM3, 20000-1); /* 100kHz /20_000 = 5 Hz */ o! D$ z* s5 J$ R
- 29* T& ]3 J% g; J& @' ?1 `5 g3 u$ n2 i
- 30 /* Counter enable. */" a6 P: k% w" b% \3 b8 m' k
- 31 timer_enable_counter(TIM3);
4 U& }) U* v4 b$ `( a/ v - 321 w+ ~8 _3 q0 _ y" ?! O, R" ?+ L( q
- 33 timer_enable_irq(TIM3, TIM_DIER_UIE);9 j6 b6 e9 }' u
- 34}
复制代码
, P# p5 r8 l# k m包括设置定时器的模式,使能定时器中断,定时器的中断频率通过 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; 7 J0 y5 ^! {6 k; ^
定时器中断
8 o, r% M G; X6 ~* [
- 1void tim3_isr(void)* A, }/ F0 D8 J2 t9 g
- 2{
' Z2 y/ q; i& K% {$ I7 d - 3 if(timer_get_flag(TIM3, TIM_SR_UIF)) {
& B$ j) B7 _: N2 M! O1 r3 M - 4 /* Clear compare interrupt flag. */
@3 q/ J- x- N9 W) E) u, l - 5 timer_clear_flag(TIM3, TIM_SR_UIF);2 q3 l4 x9 Q/ U8 f' h* `# ~
- 6
3 K( T' q# v3 G' C7 f - 7 gpio_toggle(GPIOB,GPIO4);8 X1 k! |, t$ C1 ?
- 8 }
; B+ q1 j/ B2 S% i$ i7 K( F: S- \* F E - 9}
复制代码
; k/ \# v; ^* @! ?5 H& D
9 {. y4 l+ ~9 N7 Q5 ^这里直接在中断中对GPIO进行翻转,即5Hz翻转一次GPIO,即200ms进行高低变化;
) Q& v, T5 D6 f4 H7 D; G
将程序烧写到开发板后,测量频率可以看到和预期一致: , Q; @& q* J2 Z& x2 ^
" D6 s# x# C m+ j9 Y: Y0 G
3 使用systick定时器3.1 systick 定时器设置
0 O% s4 j! N1 j- 1static void systick_setup(void)
3 c' G; L6 G: g0 v - 2{
% k( ?4 t/ H& }% f - 3 /* clock rate / 1000 to get 1mS interrupt rate */# `+ t+ s0 X2 W$ H9 Z
- 4 systick_set_reload(64000);
: t" W8 J7 x7 U - 5 systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
5 Y) o9 f# t9 s) Z3 j1 ]2 J( h8 P - 6 systick_counter_enable();
) G9 `* L# z" y: |3 E0 v; t+ @8 L7 ^ - 7 /* this done last */
. t0 i& b1 G+ x1 h+ a3 } - 8 systick_interrupt_enable();
7 J; I9 e; f) S" M" I. {) @5 I, G! x - 9}
复制代码
! B: j; x1 r8 E1 z0 o k' o这里设置systick重载值为64000,因为系统设置时钟为64MHz,那么定时器的频率为1KHz,即1ms时间定时中断; ! z3 G5 v; t- T, O
3.2 systick 定时器中断0 ~; `0 m% X0 @8 h) o* Z* [
- 1volatile uint32_t tick_counter = 0;+ i7 }" }- O; ^' \; x5 g
- 2
# |0 `# ?" u8 n3 T3 C( z# Q - 3void sys_tick_handler(void) @+ X4 E- g) s8 `
- 4{3 R; }. P3 ]4 K( @& X( \
- 5 tick_counter++;% [0 q, M# Z4 c# I, g. g" o0 Y
- 6}
复制代码 0 X2 @6 q7 g. L4 q' W
( v% m/ H! a( s3 t' R# M
这里在中断函数里进行计数;
' S1 p+ \/ Y2 \- z5 Q/ Z 3.3 使用一般这个systick定时器在cortex-m芯片中都存在,因此比较通用,可以用作RTOS的时基或用作延时功能,比如根据上面的tick_counter计数可以实现类似Arduino中的millis方式编程: - 1uint32_t millis(void)
- z3 s" p# N% L# Z5 G$ E - 2{
/ O4 c6 G# \7 R+ w: n# @& M" s - 3 return tick_counter;2 F, m& B/ `7 q
- 4}
复制代码
1 d8 E) s* Y2 ]9 U
j2 u5 k& a8 e- r, o1 i3 t/ k使用millis进行延时 r6 R$ ~ x4 V" N6 y( D4 _9 b
- 1uint32_t lastTime = millis();5 K1 i& a' }% q& a
- 2while(1){8 g- R5 J) l9 }( `
- 3 if( (millis() - lastTime) > 500) {
! i. O p; N8 T( I" a$ s4 Z - 4 lastTime = millis();: }7 Y7 G' @ A p l
- 5& T# `9 Q1 _7 s1 e
- 6 gpio_toggle(GPIOB,GPIO4);2 }$ y" Q4 z+ }2 R: i
- 7 }
! N6 T9 \4 F' i; { - 8
" z- m$ l7 z* K. f" I6 D2 y5 F: q" b - 9 ...
) [/ x1 o; I% W$ S* C' a. [" q - 10}
复制代码 , O; a' y4 {' f
" p! l5 |" J! p" {" k这样就达到500ms的延时,而且不会对其他语句的执行造成影响; $ T) _: H$ E% D h, t# K0 O
转载自: MakerInChina.cn 8 m. w( b% V' [" O9 d' h! E
. k; y/ y7 K7 A3 \ Y
|