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

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

[复制链接]
STMCU-管管 发布时间:2020-12-1 13:33
用 STM32 通用定时器做微秒延时函数(STM32CubeMX版本)
4 `, |: [' \+ m# }$ z+ M
概述
  X& w9 p$ x0 Q3 ?: G% O        在使用 DHT11 的时候,时序通信需要微秒来操作,STM32CubeMX 自带一个系统时钟,但是实现的是毫秒级别的。因此就自己用通用计时器实现一个。
. _( j/ g) `: Z/ {# G- @; q5 `
, V" E2 T3 S; i0 O) x! p( o. ?
& ]4 Z' m2 }; A6 r9 \  o. h
0 K/ Q; `+ `* |
; Q+ d- F4 {4 R: s. N, T
    环境:
' f+ _4 v; e. z% i" A+ s  J) [- `, u9 k# P: @
8 \1 B  F4 U2 z8 K* V$ z
开发板:STM32F4探索者(正点原子)$ [5 ?  v" h/ J) z' d9 F9 E

& A, }" D' k/ `
- w) h. E2 g3 k1 ?, @/ G5 S/ L
文章目录  e4 Q" v- i9 _* g* o
1.配置定时器时钟
6 x2 @& Z4 p% }8 p2.计数器时钟频率及计数模式. d' \" d- l4 N5 m: A6 @/ t
5 E1 c8 t4 E* ?
) _9 N& ^) [# E" ]
预分频系数
( m2 g* }8 Q3 [6 b5 M& w计数器模式! }/ [1 A1 A# i6 e0 R& U. y
自动重装载值
! E0 A% V0 j* v) S3.打开定时器中断
# Z9 W$ D& U% d! j( _( j- \7 q  z# `4 x4.具体实现代码
4 j; s% O+ V7 P9 ~0 a, `, M+ m5.代码测试
9 f9 ?* A/ r0 T* m+ R+ X; s0 S  c8 \$ b, ~! e
. `2 d& c. S/ ?9 Y; W
1.配置定时器时钟; k2 {  C* M! z# p6 C
·选择时钟源
2 _8 J7 H$ u; M$ G
11.png
这里选择的是内部时钟,来自 RCC 的TIMxCLK,在通用定时器框图中我们可以看到如下:* J/ M- |* w9 F  G. N
12.png
而我们可以在 STM32F4xx中文参考手册中找到,TIM2 在外设总线1(APB1上),因此其时钟为 84MHz,如下图所示:( u& L1 N8 i6 N) w* m( C5 ?
13.png
2.计数器时钟频率及计数模式
! g0 A0 a1 W5 r+ |9 m1 V除了配置定时器的时钟,还需要配置计数器时钟频率,我们要实现微秒延时,因此计数器时钟频率应该是1MHz,0 d# v5 R# C1 F" ]+ x) \: b- V8 A

- r4 L0 Z+ n" @

) Y$ M5 Y/ `" M1 j( b  ^而要实现还需要以下3个参数:0 J7 q& V3 Q) |: v6 i  ?5 N
14.png
预分频系数
% G7 i' v' q# F( i% }; n3 J根据STM32F4xx中文参考手册中的时钟频率计算,如下图所示:1 g( l$ ]% f2 |1 i; o! A
15.png
其中fCK_PSC就是通用定时器框图中的CK_PSC, 即值为84MHz,而我们所要的计数器时钟频率1MHz6 [6 ~( K$ e+ B, \& M  O
  d- l6 g! L% g
! X7 X3 M4 u8 Z; h% Q: G5 j
因此:
* s& M4 E/ k+ r
  1. PSC[15:0] = (fCK_PSC/CK_CNT) - 1 ; Q; q* D8 w! M
  2.           = (84/1) - 14 k9 Y! `% @+ v- {" b
  3.           = 83
复制代码
因此预分频系数为 83( D" H* s  V' ^# E4 @! {1 z

+ T: K, @- |  u) }2 X# \* `

7 B$ a, p0 |6 I计数器模式
) W. {- o& j3 d! _% E7 e1 X计数器这里采用向下计数模式,也就是 如设置计数值为 1000,那么每隔一个微秒,就减一,一直减到 0
! \! _; t# c* _5 l9 E1 ~
$ t0 x. L1 u5 C7 o

' s5 Y, \( Q$ v1 B+ d) o1 S自动重装载值
( M* y/ Q9 g, I! ]虽然我们并不使用自动重装载功能,但是,我们还是要对自动重装载寄存器进行赋值且不赋值为0即可,但是我测试时发送,如果为1,延时会出现偏差,因此这里赋值为 2,依据如下:* [6 a/ I) U) J* U, f

% E7 t+ ^8 X2 ]3.打开定时器中断
) S. s- A& c& @5 V- x
16.png
4.具体实现代码3 N9 L4 S: _/ M1 y4 W6 M- y" B) g; f
  1. volatile bool elapsed = false; //用于判断设置的计数值是否耗尽(向下计数模式),耗尽时,在中断中奖会设置为true% T8 o' |4 `( D4 p5 h' \

  2. ) Z0 ?! q6 F& e& s2 w; F" w- J0 q$ x
  3. void setState(bool state)
    / _+ x8 S- o; m  ~5 @0 `5 q8 g
  4. {8 C- X3 `6 m1 {; Y0 L" Z
  5.     elapsed = state;
    / m; g1 B0 |. E5 J( Z# F* s' k0 p
  6. }
    & A+ A7 a, X: _. Z- P# V

  7. ) d, S/ B" e+ @% @% N
  8. bool getState()
    % T0 F' G: q7 K- c* U
  9. {. r  H. D) {$ Q+ G& K
  10.     return elapsed;
    2 F( ]6 L1 {1 A5 c" n, ?
  11. }) G( D9 j/ m# a: ?: n5 I

  12. 5 ^$ x& d7 y) x, Z
  13. void usDelay(uint32_t time)& a  t* R7 o/ Z* y
  14. {
    4 H* B% t1 A. p" d9 W; r* d/ r8 E6 Y

  15. $ ]+ d& F3 m* ]* Q
  16.     __HAL_TIM_SetCounter(&htim2,time); //设置计数值$ z! ?2 @& H* Z
  17.      setState(false);                  % M9 R0 X- b  k7 m" @
  18.      HAL_TIM_Base_Start_IT(&htim2);     //开启定时器
    4 L5 }+ \  z0 J+ j
  19.      while(!getState());                //判断计数值是否耗尽! j  e# a( ^0 k& Q; B
  20.      HAL_TIM_Base_Stop_IT(&htim2);      //关闭定时器
    + S1 j6 v* x# A' @/ L

  21. . ?8 t3 }; i8 m1 ~! L
  22. }
复制代码
计数值耗尽回调函数6 ?2 m6 {8 C: [
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    / C- \% ^. K7 [$ I
  2. {2 v6 d( [0 {6 \; k& M3 \
  3.     if (htim->Instance == TIM2) {
    2 z; f3 J; y/ t  u$ f
  4.         setState(true);7 i- B" X0 d" R# R4 w3 g
  5.     }( S9 U' M6 K+ O8 S- e
  6.    
    2 f- ?6 |, a& f3 Y; h
  7. }
复制代码
5.代码测试5 ~, q  z+ u. C4 p& o
主函数的主循环中:
8 |! H. b# I3 m) y  C# h
  1. while (1)
    # a3 }  j9 G; m2 E8 b
  2.   {) Y, S  Y1 |) _" t) u- `
  3.     /* USER CODE END WHILE */5 V' X7 W" F0 F! o4 o6 n
  4. - A4 w; l6 y& n4 W5 [
  5.     /* USER CODE BEGIN 3 */2 b5 B* n* e3 \3 ^6 b$ W
  6.       printf("hello usDelay");
    : ]- [( |. M# e& m1 J
  7.       for(int i = 0; i < 1000; i++)
    , `8 r& t  \8 o" L8 Z
  8.       {
    9 r" E0 d% x# W# ^0 {# S* o/ Y- c# }& A
  9.             usDelay(1000);+ E2 C* s* p' Q" Q  }" S
  10.       }$ @- f4 I4 W1 P% T2 `
  11.       8 w- T* A: J) F8 l/ ]' W+ }
  12.   }
复制代码
在串口调试助手中,可以看到如下,一秒打印一条语句$ U3 S+ X8 Y& H- i2 S
17.png
在后台回复“微秒延时”,将获取项目代码!
6 j# j" P0 ~9 U: g/ J* c后续也将分享如何使用该函数读取 DHT11 温湿度传感器的值,欢迎关注我与我交流!
- T# @2 t, i- x/ U. k& P6 Z2 l% S$ }/ @; a8 G3 h% o5 O
收藏 评论0 发布时间:2020-12-1 13:33

举报

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