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

用 STM32 通用定时器做微秒延时函数(STM32CubeMX版本)

[复制链接]
STMCU-管管 发布时间:2020-12-1 13:33
用 STM32 通用定时器做微秒延时函数(STM32CubeMX版本)

0 p" h& V2 w7 b概述) o1 _# x; g6 c. v
        在使用 DHT11 的时候,时序通信需要微秒来操作,STM32CubeMX 自带一个系统时钟,但是实现的是毫秒级别的。因此就自己用通用计时器实现一个。* a# s0 X+ r! s! ^9 c' V

& s$ ?6 X" t  N" v3 s
" I+ h: w1 Y2 e; ^* w# X0 M
: p8 G. ^' L/ F
( o& C. m0 \+ t2 A1 |& c1 j4 b. c! @
    环境:
4 c! M) w! `% [3 W4 Z$ M% Y& v$ a5 {9 x) J0 W
& ^. g: o+ ^( \& z# A* o
开发板:STM32F4探索者(正点原子)
( A% Q) K$ \) W# C, F5 O- l3 \3 J+ Y% ?) P8 k( T
- m) z3 J9 E6 i; E
文章目录3 r; M) b6 F# k  q4 O
1.配置定时器时钟
6 d% `& k9 P. x7 L- }2.计数器时钟频率及计数模式. k5 g  ?" ?4 p

1 V. ]) U5 {, v3 G* }0 Y# e8 \' @
* Q/ f4 s+ q3 I+ K9 C  l
预分频系数
; ~+ D$ a2 l1 L( t3 _# v计数器模式
+ o, Q. c) C% O' g& ?6 R自动重装载值( ^3 X8 L3 d6 P$ K. q3 H
3.打开定时器中断
8 O! t' i$ g, x/ q. W4.具体实现代码5 L* t  g5 |5 x$ q: E$ I* l: `
5.代码测试
9 h6 b; W& r5 C2 y$ Q2 G) d2 x% ~% n1 D* j2 a
- |* U* v* _8 J8 a5 Y8 W
1.配置定时器时钟" ?/ d/ X) x& I! H- ]5 Y! }
·选择时钟源; w8 J, [4 l9 Q; L& T1 O
11.png
这里选择的是内部时钟,来自 RCC 的TIMxCLK,在通用定时器框图中我们可以看到如下:
2 q/ l" u; C" p3 Q
12.png
而我们可以在 STM32F4xx中文参考手册中找到,TIM2 在外设总线1(APB1上),因此其时钟为 84MHz,如下图所示:
$ a; ]/ r* _  h5 }/ @! c7 A+ b+ g: s
13.png
2.计数器时钟频率及计数模式; ?# ^' e3 h( [8 O3 M3 l0 O( C
除了配置定时器的时钟,还需要配置计数器时钟频率,我们要实现微秒延时,因此计数器时钟频率应该是1MHz,
3 A* C, Q' s7 D& D" E9 q5 @" B; M) H- R# x/ y' ]

4 d  I  q' h6 y, g6 W而要实现还需要以下3个参数:
& B6 Z6 [: Q( t
14.png
预分频系数
* }# y# V/ |, k根据STM32F4xx中文参考手册中的时钟频率计算,如下图所示:
7 G9 W$ \2 h& A3 I% g0 f
15.png
其中fCK_PSC就是通用定时器框图中的CK_PSC, 即值为84MHz,而我们所要的计数器时钟频率1MHz9 P6 C9 l- D' |* J$ X) k  t. E

9 i. H6 }) q+ J1 P) s1 j" z

4 u8 C  C$ L  q8 Q# z! y因此:
/ O  s' d  T: c) r2 Z9 ]. g
  1. PSC[15:0] = (fCK_PSC/CK_CNT) - 1 3 e+ V+ d$ F& `' {
  2.           = (84/1) - 1
    ; u1 x" u: W2 ?/ Y3 T& |: y
  3.           = 83
复制代码
因此预分频系数为 83
* v& m: E. C# ^0 J9 p- K% y7 E3 ]7 C/ w

' q( g7 c& K. W5 `$ c计数器模式- @6 g' k* d# f% ]: r/ s
计数器这里采用向下计数模式,也就是 如设置计数值为 1000,那么每隔一个微秒,就减一,一直减到 0  E' E) J/ ]6 w
+ [, m  o' N" J- v" M
  Y5 f- a$ I- i% d" {5 v
自动重装载值- u. G/ Y. Z' ~" i0 C  w7 z, e
虽然我们并不使用自动重装载功能,但是,我们还是要对自动重装载寄存器进行赋值且不赋值为0即可,但是我测试时发送,如果为1,延时会出现偏差,因此这里赋值为 2,依据如下:
/ a9 _: o) R# X3 M! F# b! {8 E
5 G0 I/ U; Q  t2 H/ b3.打开定时器中断
" {: b! p2 M# q4 G7 V. L
16.png
4.具体实现代码
5 K# O: \0 f  z$ V  [$ C5 I
  1. volatile bool elapsed = false; //用于判断设置的计数值是否耗尽(向下计数模式),耗尽时,在中断中奖会设置为true
    ; D* O/ O$ `4 p  w$ O  V
  2. & c: _' _, A; z) Z
  3. void setState(bool state)* V$ `1 T; r. ^6 ^) h4 x
  4. {
    9 }; N) U! O; v9 B" _. `8 q8 f
  5.     elapsed = state;* o1 s  F3 ]: |+ ^& i) E
  6. }
    2 [6 i& ]' v! b
  7. ; ?# k! q! W8 t; p
  8. bool getState()
    / o# ]' ]# H. T4 z
  9. {
    7 [& Z9 B0 L; U- l
  10.     return elapsed;' R8 P. p! [5 ?; }4 d; Q- J
  11. }8 q. y4 U/ |3 s9 p
  12. ; g2 m& O2 F& J+ L1 h- o
  13. void usDelay(uint32_t time)% J# N0 Q+ [* U; B$ x- d
  14. {% v% B/ ^2 V+ i

  15. 7 N' s1 _" Z# g  a* [, _) ~
  16.     __HAL_TIM_SetCounter(&htim2,time); //设置计数值  [) u' b: ]5 a$ T' d# n
  17.      setState(false);                  # h3 q5 e* ]: ^4 C/ x8 c2 e
  18.      HAL_TIM_Base_Start_IT(&htim2);     //开启定时器% D3 H6 ^% z% @" c' U# F
  19.      while(!getState());                //判断计数值是否耗尽" G7 o4 A! l: i
  20.      HAL_TIM_Base_Stop_IT(&htim2);      //关闭定时器
    : _+ y4 }  \$ n5 X$ Y! w5 c. R) U

  21. : v7 Q) I: f+ [
  22. }
复制代码
计数值耗尽回调函数
$ z( C5 s! M8 m0 C' r0 V8 {6 H! Z
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)4 M- ^) _0 A/ ]4 ^  P  G6 ^# S3 O
  2. {& b, @) e2 M9 ~+ m( s
  3.     if (htim->Instance == TIM2) {- ^& f' o( r! C7 _2 @  x8 T
  4.         setState(true);
    , m1 W. ~: J7 F  R4 g1 \! J
  5.     }; Q+ a3 Q" y! G* u& Q; ~5 d
  6.     7 U0 f1 }, T2 T  B
  7. }
复制代码
5.代码测试
0 ?! I9 y' z5 o9 R! E主函数的主循环中:2 _( `! `* S; y5 p* P
  1. while (1)2 L2 E6 v# i; h! i1 b9 ~
  2.   {
    ' H7 _7 s, m: W; d/ {
  3.     /* USER CODE END WHILE */& ?( o; n- d7 n* f/ _
  4. . x& ]: S, j- E# f" D; `2 F
  5.     /* USER CODE BEGIN 3 */
    4 y! i  F7 C/ h8 D
  6.       printf("hello usDelay");
    9 c8 J) Q* l, a" W  r& [8 ~: y; i
  7.       for(int i = 0; i < 1000; i++)# C7 z  e( X7 [
  8.       {% [4 l! B6 z3 j! f
  9.             usDelay(1000);* o5 N& y/ q+ T# M. u9 {3 L; J
  10.       }$ Z) Z' x: P$ \+ A
  11.       
    4 Y8 s. O! [& C
  12.   }
复制代码
在串口调试助手中,可以看到如下,一秒打印一条语句8 V2 l: c4 y' O' k- S
17.png
在后台回复“微秒延时”,将获取项目代码!6 ~* g! B0 h2 I+ d
后续也将分享如何使用该函数读取 DHT11 温湿度传感器的值,欢迎关注我与我交流!
! s4 Z4 _! X/ b0 _; e' ^* A! B: L; ^* S! i- |" H  ?8 w
收藏 评论0 发布时间:2020-12-1 13:33

举报

0个回答

所属标签

相似技术帖

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