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

STM32G0-Platformio+libopencm3-定时器使用

[复制链接]
STMCU小助手 发布时间:2023-2-22 18:44
使用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
  1. 1upload_protocol = cmsis-dap
    + b9 \; Q* F& R( @- I
  2. 2debug_tool = cmsis-dap
复制代码

- J$ {! ?1 t! k' W* @3 y; e* @
, N% T7 y8 ~0 y4 L$ Z/ W
2 使用基本定时器
  • 定时器设置
    * Z+ p$ j; ~- k  p
以下为设置定时器3的过程:
  1. 1static void timer_setup(void)
    # L9 |3 }  _9 N) [
  2. 2{
    - D% ?- a; c( A2 I2 @7 R
  3. 3    /* Enable TIM3 clock. */
      W3 `5 s3 l( G$ Q' K, q( U0 Z' o
  4. 4    rcc_periph_clock_enable(RCC_TIM3);0 [! n( n& y: e& k* S
  5. 5
    $ G. x9 m1 p& J& }* E: X
  6. 6    /* Enable TIM3 interrupt. */+ ]5 X1 r* Q* N& O) x+ u: U
  7. 7    nvic_enable_irq(NVIC_TIM3_IRQ);0 [+ s& `, n9 T, y, A
  8. 8
    9 [1 `4 E# g2 Y7 C; I! N' |# e
  9. 9    /* Timer global mode:# i9 X; |! f' Z7 w
  10. 10     * - No divider
    5 l6 i' }5 m- F" c: {  B) _
  11. 11     * - Alignment edge
    ! _7 F1 H6 L. l! R8 V5 }& U
  12. 12     * - Direction up, x3 [0 S, m( E  t# Q5 C
  13. 13     */5 m7 b$ j7 N$ e& J! a* C
  14. 14    timer_set_mode(TIM3, TIM_CR1_CKD_CK_INT,
    . ?2 [( Q4 l* h0 F: h5 `
  15. 15        TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);
    ; v% `' ], q5 D' W+ N2 W! h# B
  16. 16) b1 t' |/ k" _7 _  [
  17. 17    /*
    7 [1 t& L; n: U8 t8 C  i
  18. 18     * APB1 PRE = 1, TIMPCLK = PCLK! f' r, b# |. n* j. E( m
  19. 19     * APB1 PRE != 1, TIMPCLK = PCLK * 2! v9 C3 `! q. B# K& x
  20. 20     */7 `6 D+ v* W" x+ U' _, Q- a; p
  21. 21    timer_set_prescaler(TIM3, (rcc_apb1_frequency/100000-1)); //100KHz, s$ S6 x; B, u
  22. 22( U+ [# {/ F" C2 t8 x/ w" S
  23. 23    /* Disable preload. *// P" N; C* V# y: v+ R
  24. 24    timer_disable_preload(TIM3);4 V# k- ?0 F* z& n' f
  25. 25    timer_continuous_mode(TIM3);9 R6 M" f4 ]. F5 a1 E
  26. 263 E/ N) \6 M& X8 d
  27. 27    /* Timer Period */
    1 ~' n/ o9 }, v  P3 J% q1 E
  28. 28    timer_set_period(TIM3, 20000-1);    /* 100kHz /20_000 = 5 Hz */  o! D$ z* s5 J$ R
  29. 29* T& ]3 J% g; J& @' ?1 `5 g3 u$ n2 i
  30. 30    /* Counter enable. */" a6 P: k% w" b% \3 b8 m' k
  31. 31    timer_enable_counter(TIM3);
    4 U& }) U* v4 b$ `( a/ v
  32. 321 w+ ~8 _3 q0 _  y" ?! O, R" ?+ L( q
  33. 33    timer_enable_irq(TIM3, TIM_DIER_UIE);9 j6 b6 e9 }' u
  34. 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 ~* [
  1. 1void tim3_isr(void)* A, }/ F0 D8 J2 t9 g
  2. 2{
    ' Z2 y/ q; i& K% {$ I7 d
  3. 3    if(timer_get_flag(TIM3, TIM_SR_UIF)) {
    & B$ j) B7 _: N2 M! O1 r3 M
  4. 4        /* Clear compare interrupt flag. */
      @3 q/ J- x- N9 W) E) u, l
  5. 5        timer_clear_flag(TIM3, TIM_SR_UIF);2 q3 l4 x9 Q/ U8 f' h* `# ~
  6. 6
    3 K( T' q# v3 G' C7 f
  7. 7        gpio_toggle(GPIOB,GPIO4);8 X1 k! |, t$ C1 ?
  8. 8    }
    ; B+ q1 j/ B2 S% i$ i7 K( F: S- \* F  E
  9. 9}
复制代码

; k/ \# v; ^* @! ?5 H& D
9 {. y4 l+ ~9 N7 Q5 ^
这里直接在中断中对GPIO进行翻转,即5Hz翻转一次GPIO,即200ms进行高低变化;

) Q& v, T5 D6 f4 H7 D; G
  • 烧写测试
    , W9 V- d! q6 t/ h
将程序烧写到开发板后,测量频率可以看到和预期一致:
, Q; @& q* J2 Z& x2 ^
微信图片_20230222184426.png
" D6 s# x# C  m+ j9 Y: Y0 G
3 使用systick定时器3.1 systick 定时器设置
0 O% s4 j! N1 j
  1. 1static void systick_setup(void)
    3 c' G; L6 G: g0 v
  2. 2{
    % k( ?4 t/ H& }% f
  3. 3    /* clock rate / 1000 to get 1mS interrupt rate */# `+ t+ s0 X2 W$ H9 Z
  4. 4    systick_set_reload(64000);
    : t" W8 J7 x7 U
  5. 5    systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
    5 Y) o9 f# t9 s) Z3 j1 ]2 J( h8 P
  6. 6    systick_counter_enable();
    ) G9 `* L# z" y: |3 E0 v; t+ @8 L7 ^
  7. 7    /* this done last */
    . t0 i& b1 G+ x1 h+ a3 }
  8. 8    systick_interrupt_enable();
    7 J; I9 e; f) S" M" I. {) @5 I, G! x
  9. 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* [
  1. 1volatile uint32_t tick_counter = 0;+ i7 }" }- O; ^' \; x5 g
  2. 2
    # |0 `# ?" u8 n3 T3 C( z# Q
  3. 3void sys_tick_handler(void)  @+ X4 E- g) s8 `
  4. 4{3 R; }. P3 ]4 K( @& X( \
  5. 5    tick_counter++;% [0 q, M# Z4 c# I, g. g" o0 Y
  6. 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方式编程:
  • 由于定时器中断为1ms定时,因此tick_counter就是1ms的计数值
    6 r* T, k! @9 |5 I
  1. 1uint32_t millis(void)
    - z3 s" p# N% L# Z5 G$ E
  2. 2{
    / O4 c6 G# \7 R+ w: n# @& M" s
  3. 3    return tick_counter;2 F, m& B/ `7 q
  4. 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
  1. 1uint32_t lastTime = millis();5 K1 i& a' }% q& a
  2. 2while(1){8 g- R5 J) l9 }( `
  3. 3    if( (millis() - lastTime) > 500) {
    ! i. O  p; N8 T( I" a$ s4 Z
  4. 4        lastTime = millis();: }7 Y7 G' @  A  p  l
  5. 5& T# `9 Q1 _7 s1 e
  6. 6        gpio_toggle(GPIOB,GPIO4);2 }$ y" Q4 z+ }2 R: i
  7. 7    }
    ! N6 T9 \4 F' i; {
  8. 8
    " z- m$ l7 z* K. f" I6 D2 y5 F: q" b
  9. 9    ...
    ) [/ x1 o; I% W$ S* C' a. [" q
  10. 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
赞 收藏 评论0 发布时间:2023-2-22 18:44

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版