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

STM32G0-Platformio+libopencm3-定时器使用

[复制链接]
STMCU小助手 发布时间:2023-2-22 18:44
使用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
  1. 1upload_protocol = cmsis-dap
    , z) l+ `" E& S$ l+ e
  2. 2debug_tool = cmsis-dap
复制代码

, b& d8 R/ ^; P2 \+ r8 V
" p! n8 }6 ]7 v! Y6 ]! I4 h
2 使用基本定时器
  • 定时器设置
    # [1 G7 \' N6 k; w$ }8 N
以下为设置定时器3的过程:
  1. 1static void timer_setup(void)
    : v6 G2 x; l" \! |% @. K& u
  2. 2{# v" z/ J1 n" m$ K3 }0 @- ?: E  X
  3. 3    /* Enable TIM3 clock. */; ]0 {7 X  v2 ]  O- _& N
  4. 4    rcc_periph_clock_enable(RCC_TIM3);# j+ _9 {- o! o# M1 W8 A2 W: ^
  5. 5
      I: O. s# u. _, `( K$ G' ]1 J# j
  6. 6    /* Enable TIM3 interrupt. */
    7 B& Z/ }  a, y7 }1 b& P' a  e
  7. 7    nvic_enable_irq(NVIC_TIM3_IRQ);
    . S3 x3 G  V! d
  8. 8# D; P4 x2 Q* i
  9. 9    /* Timer global mode:
    * W+ e( c; P0 e5 [
  10. 10     * - No divider6 T4 R9 h+ P6 W3 [8 o. R4 l7 v  t
  11. 11     * - Alignment edge
    2 G, G* c6 W# `4 u8 H
  12. 12     * - Direction up* R. }% C) K5 E- t
  13. 13     */
    4 ?6 d2 t7 u% g3 a( o* D
  14. 14    timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT,
    - z3 F7 Z8 ]) v- p6 b
  15. 15        TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    1 K- R1 B1 P) p' g" q/ M  d
  16. 16
    $ ?" m# ?. V* k
  17. 17    /*
    7 j: g& Y: ~( g4 p0 E
  18. 18     * APB1 PRE = 1, TIMPCLK = PCLK' t: W" T7 J$ U9 r2 I5 y% W
  19. 19     * APB1 PRE != 1, TIMPCLK = PCLK * 21 G5 w! }( e. R0 ~8 p$ N
  20. 20     */, |, u/ E5 a2 ~
  21. 21    timer_set_prescaler(TIM3, (rcc_apb1_frequency/100000-1)); //100KHz! k4 o# c! ?. w& |1 B, P# [
  22. 22
      P% L2 t! D: j7 }0 N  u. `
  23. 23    /* Disable preload. */
    8 m3 w+ f" {3 z; b" Z. e7 b4 w* X, g
  24. 24    timer_disable_preload(TIM3);
    7 x5 ~9 {- ], i% s5 c" L( ]
  25. 25    timer_continuous_mode(TIM3);
    4 R3 \) G' f1 p8 F" _
  26. 26* p! W. S/ m/ \. u- g4 q/ H" ~
  27. 27    /* Timer Period */
    , s. ~: d7 ?. `
  28. 28    timer_set_period(TIM3, 20000-1);    /* 100kHz /20_000 = 5 Hz */' {7 W5 ]( `( D- T/ u+ ^5 C
  29. 29( u4 @- Y: m) A/ A: e  k
  30. 30    /* Counter enable. */) o8 }1 y4 n, H1 c: I
  31. 31    timer_enable_counter(TIM3);* s, M: z( q# E3 [8 s/ I
  32. 324 G9 S( F/ X. g. L! @0 S) }( B. b
  33. 33    timer_enable_irq(TIM3, TIM_DIER_UIE);5 I% x% i4 O% u& Y
  34. 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
  • 定时器中断
    & h- ~3 D& M* Y7 q
  1. 1void tim3_isr(void)
    6 y+ H  o, s' h0 E% @
  2. 2{! B$ Y* j9 u* V7 B) }
  3. 3    if(timer_get_flag(TIM3, TIM_SR_UIF)) {
    9 {& G+ {! i5 p; F1 D; @+ h
  4. 4        /* Clear compare interrupt flag. */9 W- O4 L* Q) t5 }7 T" b$ n" }
  5. 5        timer_clear_flag(TIM3, TIM_SR_UIF);
    ' ]# T# m0 [& K
  6. 6; {/ C) D3 w; Z1 G2 }; T
  7. 7        gpio_toggle(GPIOB,GPIO4);
    # D: Z3 i/ D6 \6 W0 ?. U8 X+ u' L; z
  8. 8    }% p# P! h- o( ]/ \
  9. 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
微信图片_20230222184426.png

3 t1 ?& Z: r' P3 使用systick定时器3.1 systick 定时器设置1 A+ \( O! `& Y# W) e; E
  1. 1static void systick_setup(void)
    8 K. u1 n9 |6 y  O% v4 V( C4 ~  F
  2. 2{
    + J- c6 `" u- Y* t8 l, B- Q
  3. 3    /* clock rate / 1000 to get 1mS interrupt rate */
    . b; Q" @3 I3 O3 {: I
  4. 4    systick_set_reload(64000);8 f! ?( `6 L8 c( `6 Y: |$ X: {
  5. 5    systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);6 r, |: a8 O9 Z: a( q& \
  6. 6    systick_counter_enable();: e  i  c4 ^" Y% p7 w
  7. 7    /* this done last */0 N# K8 q; _! `
  8. 8    systick_interrupt_enable();+ U! L: d4 q6 H! ^
  9. 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
  1. 1volatile uint32_t tick_counter = 0;
    ! s5 w8 P9 n/ e1 j. ~9 ^4 b& W, U
  2. 2
    2 T6 J6 ?6 e) V+ O' U- ]
  3. 3void sys_tick_handler(void)0 b! T4 H1 g; V7 r) a, B
  4. 4{
    % _+ }; k7 @! a! B) W3 P& p
  5. 5    tick_counter++;
    0 v: f0 p. X# S9 h& ]" A
  6. 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方式编程:
  • 由于定时器中断为1ms定时,因此tick_counter就是1ms的计数值
    ) J6 ]6 l4 L! o- P
  1. 1uint32_t millis(void)# ^! s) p# V$ I4 s6 w
  2. 2{
    8 k0 a1 a- U+ G; \
  3. 3    return tick_counter;" Y/ Z  t% V; c! m3 O7 P- }9 \, C
  4. 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
  1. 1uint32_t lastTime = millis();5 }0 b, m5 N% m. f$ o6 q" F5 |8 C
  2. 2while(1){1 L& J, G& A" i
  3. 3    if( (millis() - lastTime) > 500) {
    ( r% j3 A) Q8 ]- c$ Y' `
  4. 4        lastTime = millis();
    8 W3 @6 `8 F3 y% V: Z9 |% W0 v
  5. 5
    & n8 Q6 [5 B- A
  6. 6        gpio_toggle(GPIOB,GPIO4);: m' b- z3 n1 }& v! x4 R1 }) K
  7. 7    }4 _, Z: `% Z# p: J4 U
  8. 8
    " k% D0 M9 i! _# A
  9. 9    ...
    1 W8 I) Q9 d9 V; z0 e. W# x  o2 ?
  10. 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/ |
收藏 评论0 发布时间:2023-2-22 18:44

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版