你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32G0-Platformio+libopencm3-定时器使用

[复制链接]
STMCU小助手 发布时间:2023-2-22 18:44
使用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 _
  1. 1upload_protocol = cmsis-dap
    9 m( P, L3 n5 e- p2 D0 n9 ^
  2. 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的过程:
  1. 1static void timer_setup(void)( n/ z* e4 K" h$ a% p* w
  2. 2{
    5 K( e2 ]. J3 l3 Z( A
  3. 3    /* Enable TIM3 clock. */
    6 x" H1 K  l; e. h8 [0 q
  4. 4    rcc_periph_clock_enable(RCC_TIM3);
      Q3 k$ c; R( y9 `) M; k5 b- d0 b
  5. 58 j) T" j9 }# H; F6 z7 Y
  6. 6    /* Enable TIM3 interrupt. */. Q- D2 e7 a3 ^
  7. 7    nvic_enable_irq(NVIC_TIM3_IRQ);
    ' j& E0 v. q4 b  [3 C
  8. 8
    4 U' G& W2 L0 T8 N% o$ g. G! ^0 G
  9. 9    /* Timer global mode:8 r0 M2 Z6 v4 F: H# ~3 O5 q  N
  10. 10     * - No divider# O. P. o" S) d3 y) B
  11. 11     * - Alignment edge$ U0 D1 o6 Y5 g/ q4 }3 ~
  12. 12     * - Direction up  X5 v- c: Y# k/ v3 @4 y3 R+ ?
  13. 13     */7 m0 V4 H1 T( k  t/ w+ F5 C
  14. 14    timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT,
    1 y. @' ?: ]- A3 K9 {
  15. 15        TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    & v4 s6 I4 _! i* s  Z$ ^6 ]# L* |
  16. 16
    * h4 s5 `# V: q) W7 C
  17. 17    /*
    ) I9 x0 _: [# B
  18. 18     * APB1 PRE = 1, TIMPCLK = PCLK& [0 e# t2 W7 M/ v1 {! R( N8 B- R6 M
  19. 19     * APB1 PRE != 1, TIMPCLK = PCLK * 2; J9 L+ t+ M1 K, D
  20. 20     */
    7 E9 i  N" f# g9 W
  21. 21    timer_set_prescaler(TIM3, (rcc_apb1_frequency/100000-1)); //100KHz
    & M2 P; z+ v1 ?. Z! o
  22. 22
    4 f8 H( i) H" N7 d
  23. 23    /* Disable preload. */
    % c" H- ~6 z. M
  24. 24    timer_disable_preload(TIM3);1 S+ p  Y$ D/ q, K2 B' d% R
  25. 25    timer_continuous_mode(TIM3);
    : }3 B/ a1 c$ [; b) k  d* A# m8 Z- B
  26. 26
    - {2 F! W' q) M, U' {! ~
  27. 27    /* Timer Period */
      ?+ u/ k+ _) D: q; S$ G
  28. 28    timer_set_period(TIM3, 20000-1);    /* 100kHz /20_000 = 5 Hz */
    ; W. ^0 H# E% G# \! |/ s0 g
  29. 290 p6 U0 ^0 W9 A
  30. 30    /* Counter enable. */1 j2 i- ?. t# [
  31. 31    timer_enable_counter(TIM3);! z; `* _# [" g0 w8 X5 t1 _
  32. 32' K  g. O3 B, k8 _! c/ S4 K, N- q& G
  33. 33    timer_enable_irq(TIM3, TIM_DIER_UIE);
    5 B# @8 U1 _; R& }% ]8 ~
  34. 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 @
  1. 1void tim3_isr(void)
    " a* v  J" H  U+ ]1 c
  2. 2{
    ) I. v- R$ b  t+ H4 f& T! |3 n
  3. 3    if(timer_get_flag(TIM3, TIM_SR_UIF)) {
    . I  _8 f! t$ w1 O% v* j+ v
  4. 4        /* Clear compare interrupt flag. */0 Y) A1 w6 z: j- H. @( o
  5. 5        timer_clear_flag(TIM3, TIM_SR_UIF);; {- h# T4 s: e/ S3 k
  6. 6: A  M  i! A! p+ _: C* M
  7. 7        gpio_toggle(GPIOB,GPIO4);
    ' U: }: W" F2 B) L& d" F! `* G
  8. 8    }' F; I! ?) K5 w
  9. 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
微信图片_20230222184426.png

, z* w4 e& C. A% t% J3 Q% u3 使用systick定时器3.1 systick 定时器设置- N5 U4 w  a; e- x9 E
  1. 1static void systick_setup(void)% L( K% `$ }/ i2 Y2 D4 ], K2 v
  2. 2{$ t! M+ d1 U* d  ~# M3 J1 N9 _
  3. 3    /* clock rate / 1000 to get 1mS interrupt rate */
    7 H# w+ ]5 ?7 x% T0 r4 Q0 _7 b
  4. 4    systick_set_reload(64000);6 F" ^! j, x0 x0 m; B0 a
  5. 5    systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
    2 R, x9 c) D5 g- m2 W/ \
  6. 6    systick_counter_enable();% [" S( {" Q( y1 E+ H3 P
  7. 7    /* this done last */
    - H4 s+ U! t' A2 p$ \
  8. 8    systick_interrupt_enable();
    9 x( \$ G" ~& {8 ]4 I5 L8 |  E
  9. 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
  1. 1volatile uint32_t tick_counter = 0;9 N2 d  N8 h$ }( S
  2. 2$ \3 t/ J) |( d# X  v8 E5 U
  3. 3void sys_tick_handler(void)
    5 |9 `* M; `. j" l2 K; j
  4. 4{% p( f$ g' O6 v# `
  5. 5    tick_counter++;! v. ]  I: G  W; D. g: ^
  6. 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方式编程:
  • 由于定时器中断为1ms定时,因此tick_counter就是1ms的计数值
    0 \$ K2 [9 H( _
  1. 1uint32_t millis(void)
    ! R+ y8 H! Z$ }" Y
  2. 2{7 `  d8 E) |' y' p1 I9 a6 w
  3. 3    return tick_counter;0 C  r, q  k5 X) K9 Z; b; M/ z
  4. 4}
复制代码

- W- a/ ^$ s' ?$ v, \9 [
+ d1 t! A. P( `& e& B. u7 D
  • 使用millis进行延时
    ; [2 R9 B7 I+ O. s4 \9 P: _
  1. 1uint32_t lastTime = millis();
    / N: i3 F: p1 [, e5 G+ Q' M7 u
  2. 2while(1){- P0 |+ i# r/ y2 S! W6 F
  3. 3    if( (millis() - lastTime) > 500) {
    0 e) Q# z" p2 W
  4. 4        lastTime = millis();3 x2 m" x3 P" Z$ z! }
  5. 5
    , z# M) y- O- n: q
  6. 6        gpio_toggle(GPIOB,GPIO4);' b; L2 C$ }' U4 Z" Z9 ~* e6 Y
  7. 7    }$ O0 l4 b) s, I
  8. 86 x8 a8 h# F: Y- Q4 j, D8 w9 w% R
  9. 9    ...
    5 i1 G8 u# F% ~% b8 s2 i% D+ V
  10. 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/ |
收藏 评论0 发布时间:2023-2-22 18:44

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版