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

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

[复制链接]
STMCU-管管 发布时间:2020-12-1 13:33
用 STM32 通用定时器做微秒延时函数(STM32CubeMX版本)
) h* @# `1 H, U* h
概述9 N" A2 ^% M+ Z5 G% J
        在使用 DHT11 的时候,时序通信需要微秒来操作,STM32CubeMX 自带一个系统时钟,但是实现的是毫秒级别的。因此就自己用通用计时器实现一个。
/ p5 n' ~6 ~7 }# [1 n6 L9 K0 D# ?3 w3 I1 O5 }" L: \
7 _; K" j4 ?7 V! G8 w/ n& M% D
- |+ {0 O% t8 c# m% d

: F4 M( u( ?5 |6 ^* r+ a    环境:7 g0 g# o# s0 u" f* V7 L

5 }$ }  D) S1 y$ ^: z

; e  E6 J; M$ J4 W& Q! s9 o. B开发板:STM32F4探索者(正点原子)2 h- i: i2 Q$ r" r9 W' R* m

" @' y6 d! {( _8 ~8 ^  z- V7 w
0 q' [$ f1 b3 Z
文章目录  c% K+ X8 c3 G- o
1.配置定时器时钟
8 `& Q+ }4 D8 i8 D2.计数器时钟频率及计数模式! A, p, y, \' ?8 z: G. e

) j1 q+ d7 E7 B9 X+ o6 j# e% @
$ r* g8 r' n$ ]! l, U% |( {
预分频系数
$ ?5 E5 V9 \; y7 H$ z7 f计数器模式) F4 {  }8 z8 _' I& h
自动重装载值8 W8 Q5 |8 W2 V  _0 ^1 k$ o; K
3.打开定时器中断; c; H+ P* S( X; Y& W
4.具体实现代码
; |) K8 B1 G6 _6 l/ w/ t) z$ u5.代码测试: Q6 ^( [  p2 j9 r1 R( P

/ g8 T- \: ?4 N- T
! ~9 V- m& ]' z* s  C; Y& a: @) d
1.配置定时器时钟
9 c- ?0 l+ `8 m' V8 }9 s  [$ t·选择时钟源
6 U) y* _! g% T, g$ f+ R
11.png
这里选择的是内部时钟,来自 RCC 的TIMxCLK,在通用定时器框图中我们可以看到如下:
4 K4 f6 {% e& A, S5 j$ H. Q
12.png
而我们可以在 STM32F4xx中文参考手册中找到,TIM2 在外设总线1(APB1上),因此其时钟为 84MHz,如下图所示:
* h  D" r' o4 Q0 p2 w
13.png
2.计数器时钟频率及计数模式
9 s* k6 `. s& z除了配置定时器的时钟,还需要配置计数器时钟频率,我们要实现微秒延时,因此计数器时钟频率应该是1MHz,
! M& x" b# @$ a6 \  r0 e7 s
0 x+ S6 F4 H3 R

! u- q5 E/ ~% K5 K; [. r; Z3 ^3 h而要实现还需要以下3个参数:; P6 f5 m9 n; I: {" [. `) I
14.png
预分频系数
! ]  [3 ]. X- _; B% B5 T2 o根据STM32F4xx中文参考手册中的时钟频率计算,如下图所示:
0 K3 `7 p2 @2 B2 y+ v
15.png
其中fCK_PSC就是通用定时器框图中的CK_PSC, 即值为84MHz,而我们所要的计数器时钟频率1MHz
- |& {2 Q; F5 D7 I: \3 n/ H
( d1 K- I. h) B1 c; }
. J/ L. }3 h* m/ H
因此:
' H& \# }; I3 i; o+ w2 w* F
  1. PSC[15:0] = (fCK_PSC/CK_CNT) - 1 ) o; x2 a& D/ h% y' a& j
  2.           = (84/1) - 1; z  n* G9 J  P4 W" c+ o( _' T% j
  3.           = 83
复制代码
因此预分频系数为 83' Y9 c# `! @. I- {$ G, T
+ s& F7 l. z5 u0 K9 P
" D" D/ F% a+ ]( Z" G5 ?+ M/ S
计数器模式8 p: A( D2 k7 e6 J# R  T
计数器这里采用向下计数模式,也就是 如设置计数值为 1000,那么每隔一个微秒,就减一,一直减到 0
) ~8 b: [  i' X
  M# N: y2 d8 P
  f! r6 l, V7 }! K
自动重装载值
8 N) m, ]' f8 t5 L4 q, m虽然我们并不使用自动重装载功能,但是,我们还是要对自动重装载寄存器进行赋值且不赋值为0即可,但是我测试时发送,如果为1,延时会出现偏差,因此这里赋值为 2,依据如下:% V: k: D: [  G: r7 }
8 s6 B) C! K4 J
3.打开定时器中断
$ I8 w0 o* L& H9 M
16.png
4.具体实现代码+ }) v  u: f  m! G# I- B
  1. volatile bool elapsed = false; //用于判断设置的计数值是否耗尽(向下计数模式),耗尽时,在中断中奖会设置为true
    ! Y7 {1 e; z, R$ y; |
  2. " k, Q# W6 L" {. w
  3. void setState(bool state)
    + X, K5 v4 t# X0 h7 u9 Z8 p8 H
  4. {
    8 U$ R- w( M% b
  5.     elapsed = state;& T0 Q3 x/ `/ g
  6. }
    , }( H8 ^  C& z+ C" m
  7. ) ~; k' }9 o( q" p6 Q
  8. bool getState()
    8 o6 t3 e2 O' X3 O3 ?+ h
  9. {
    * |& i+ d2 _* c1 M3 ^
  10.     return elapsed;1 e' L6 f0 l7 R3 z
  11. }
    5 T8 L/ g# n! c; [9 v
  12. ; Q# f% @$ D8 |* x
  13. void usDelay(uint32_t time)
    ! Y' p5 ~% B. Q* z- Y! r1 o
  14. {0 @- G% ?5 p) G7 M& D! o  g

  15. 7 D3 ]- b: Z. T9 v
  16.     __HAL_TIM_SetCounter(&htim2,time); //设置计数值( I4 k0 k3 Q  [! j5 _
  17.      setState(false);                  5 S* ^/ t  W! [" F% A
  18.      HAL_TIM_Base_Start_IT(&htim2);     //开启定时器
    - k9 }0 S% o% s) ]2 h
  19.      while(!getState());                //判断计数值是否耗尽
    2 `& ]4 C0 ~- v, j1 }
  20.      HAL_TIM_Base_Stop_IT(&htim2);      //关闭定时器7 w( z3 a0 ?" r5 r

  21. : ?( {6 N8 X' M  s+ `7 e6 Y7 Y
  22. }
复制代码
计数值耗尽回调函数- b* k. S: ~9 H1 K/ D
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
    ! e: k# B6 R& \; ~+ |: r$ q3 u
  2. {
    ; o6 L9 w8 h  Y
  3.     if (htim->Instance == TIM2) {
    5 }6 u5 v; D2 o% p+ D( w/ [1 T
  4.         setState(true);
    : x. r& A! h8 E% u( K% ?! U
  5.     }
    ) e: t* ~1 |; s" l
  6.    
    6 n, r5 G/ l5 w! Z" j5 Z; h
  7. }
复制代码
5.代码测试
- v$ g2 V& m3 U' l! L6 n* W) k! j主函数的主循环中:' K0 G/ R, Z, a$ q9 q
  1. while (1)! i5 s$ b5 ]9 O3 ?$ w) I$ W; I0 }
  2.   {
    ; @$ W6 C+ {6 Q+ b: V0 M! a& `5 u+ K
  3.     /* USER CODE END WHILE */
    & F) t( I, m" _, w/ [

  4. ; W. i9 T9 h! o! l7 K. x% u8 P
  5.     /* USER CODE BEGIN 3 */0 O& p1 ^4 U# l- d. O" b. T
  6.       printf("hello usDelay");
    9 q+ P% a5 s9 ~1 g' [1 `
  7.       for(int i = 0; i < 1000; i++)
    9 G; ]3 }/ u0 p9 n1 O" ^5 r
  8.       {
    4 Z7 g$ t& q4 y- D
  9.             usDelay(1000);* M# E' Y0 N! L0 r
  10.       }
    1 \, l' v& G# _8 L
  11.       & ~1 Z3 O  P7 ^
  12.   }
复制代码
在串口调试助手中,可以看到如下,一秒打印一条语句" [# @1 G1 t1 u# h- C# Y& T+ \
17.png
在后台回复“微秒延时”,将获取项目代码!' M  d" J1 f$ y5 E! b
后续也将分享如何使用该函数读取 DHT11 温湿度传感器的值,欢迎关注我与我交流!
! f1 t9 b* A( H8 G$ i* z/ g. Y; j% q: K7 n5 J" M2 p  B7 }
收藏 评论0 发布时间:2020-12-1 13:33

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版