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

基于STM32F103C8T6工控板利用定时器计算某段代码的运行时间

[复制链接]
STMCU小助手 发布时间:2022-11-20 15:24
思路:6 \& Z7 R" i8 |, w. Y
1)利用通用定时器(选择定时器2)计算某段代码的运行时间;
! I$ B+ g* u' w/ R% r7 s2)顾名思义,会基于定时器2创建两个函数(TIM2_Clock_Start和TIM2_Clock_End)分别控制定时器2开始计时和结束计时,被测代码放在这两个代码的中间;
( F9 M  \: K) @& w, j9 K3)考虑计时的精度和最大计时长度,创建变量 u8 OverflowNum_cnt用来计算定时器2溢出中断的次数,创建变量u16 cnt_value用来计算最后一次定时器2的cnt值;9 s3 ]9 T7 m7 z
4)利用USART1实时读取某段代码的运行时间,并上传至电脑,便于查看。5 R2 E) ], u5 w& h+ F6 V

; I) n' G1 h: N# X! o1 {1 z: ^( I这个工程较为简单,主要代码如下:. h. ]) W' @: _2 @- Q
2 K4 L; K0 q$ r' }$ ]* a/ f
1.定时器2的初始化配置代码,注意:初始化后,不使能TIM2!!
& i7 c( i! @+ L
  1. /*****************************************************************4 X; h* S1 M- c0 i7 E6 P
  2. 函数名称:TIM2_Init(u16 arr, u16 psc)$ X& m* o& g5 z9 t* ~
  3. 函数功能:定时器2 初始化函数
    % V. o  E: X1 O7 j' l$ Z2 U% ?; a
  4. 入口参数:u16 arr:自动重装载值, u16 psc:时钟预分频数
    7 S; W& f* b/ c8 ?& }
  5. 返回参数:无6 Z0 t' B( x1 f- Q8 x6 G
  6. 开发作者:闲人Ne$ E2 U# a0 q8 z' g; n
  7. ******************************************************************/
    ' s  e/ n# w$ ^1 ]/ P
  8. void TIM2_Init(u16 arr, u16 psc)0 R& \% @$ }; j* u; O. S: r6 X
  9. {0 |0 q* f9 M/ Y
  10.   TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeStruct;
    # t1 r( K7 U- _) p
  11.   TIM_DeInit(TIM2);                                                                                       // 定时器 2 复位! y  G( T1 @9 G0 e7 L
  12.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);              // 使能TIM 2 时钟; I8 O' Q5 Q  U
  13.   // 定时器 2 参数初始化配置
    " ^9 w4 Z8 s& _. g' s
  14.   TIM_TimeBaseInitTypeStruct.TIM_Period=arr;
    / G. a" b$ N5 u: ^2 c
  15.   TIM_TimeBaseInitTypeStruct.TIM_Prescaler=psc;
    " B4 {/ n5 w& n, F0 Y% o
  16.   TIM_TimeBaseInitTypeStruct.TIM_CounterMode=TIM_CounterMode_Up;   // 向上计数模式
    ) X& n1 t' B$ ~6 w" z1 b8 b9 S
  17.   TIM_TimeBaseInitTypeStruct.TIM_ClockDivision=TIM_CKD_DIV1;
    ! Z: {0 p& p# O9 `  P
  18.   TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitTypeStruct);  a: |- V: ]  i
  19.   // 定时器 3 中断优先级配置
    + `+ P/ L$ Q# _- l! d3 d6 K6 S9 Q
  20.   NVIC_Configuration();2 `- [8 C% s5 V: o: _6 ^
  21. }
复制代码
! B& z: l$ m6 J3 t
2.定时器2开始和结束相关代码,注意:引用了2个放在main.c文件里的变量!!, T, M4 I2 X# ^7 K( ~! e
  1. /*****************************************************************9 C8 y2 b  n+ H( x
  2. 函数名称:TIM2_Clock_Start()8 ~6 }5 a9 v5 O3 b
  3. 函数功能:使能定时器 2 函数,开始计时
    9 P: v2 ^, K' _/ `0 U  x- G1 F) W
  4. 入口参数:无8 j/ z0 z+ U5 i0 l. ^
  5. 返回参数:无% ~9 C: r& J1 M
  6. 开发作者:闲人Ne
    % H1 i3 Z6 l! D! I+ a
  7. ******************************************************************/, `5 F3 `, Y" x8 \
  8. extern u8  OverflowNum_cnt;                                    // u8 计数器,用来计算溢出中断的次数,初始化值为0000 00008 l9 S0 g) R- [0 l) q$ g3 n# H  X
  9. void TIM2_Clock_Start()
    , C. B8 A- L% B. P6 L/ }! e
  10. {
    : s1 C/ r- {4 [; e' f
  11.         OverflowNum_cnt = 0;
    4 M4 q: L" A8 Z5 A  {
  12.         TIM2->CNT=0x00;                             // 将定时器 2 的计数器至零
    ! U# v$ D- `9 p/ O) y: q/ `
  13.         TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);    // 针对TIM2_DIER寄存器,[0]位,UIE至1,允许更新中断
    : c% `: T/ N: H6 C( |3 A- a3 H
  14.         TIM_Cmd(TIM2,ENABLE);  - R5 J8 h1 s) s3 g* b5 y* r7 N
  15. }
    1 }9 Z  P$ K6 c4 S. S
  16. /*****************************************************************7 K9 r3 |, I4 c7 O3 m' c
  17. 函数名称:u16 TIM2_Clock_End()
    % X0 W* }' T2 H: \4 K
  18. 函数功能:停止定时器 2 函数,读取CNT数值
    + x7 R2 [! l0 {& m
  19. 入口参数:无/ g) H' G' c% _6 o' Z3 E
  20. 返回参数:u16 cnt_value,返回当前TIM2_CNT的值
    ; S0 e, I6 w) ?$ Z2 |
  21. 开发作者:闲人Ne
    - P1 L, v/ @; n* S1 q
  22. ******************************************************************/" i1 @( m+ a% ~. T$ B3 Q* Z
  23. extern u16 cnt_value;
    ! j6 u2 Q! v7 p. N2 Q) v# l, p
  24. u16 TIM2_Clock_End(); t: P7 G1 v/ g1 o
  25. {
    . j$ a3 Y+ I( ^3 Y1 Y' O8 _1 B
  26.         cnt_value = TIM2->CNT;8 ]' e1 o& R; T! O3 L
  27.         TIM_Cmd(TIM2,DISABLE);5 h$ w& l3 m% _" e
  28.         return cnt_value;7 R; s, c# P/ |) P9 g$ G
  29. }
    % d! G) r1 i! V6 T; B
复制代码

3 P& n2 M$ C% F% [, o( ?3.定时器2的中断服务函数,主要目的是每发生一次溢出中断,OverflowNum_cnt值+1,如果OverflowNum_cnt值溢出,就报错。
' G+ j$ j: d6 L& T: b) f& s5 y$ f
  1. /************************************************" w* _, J! r7 f" E
  2. 函数名称:TIM2_IRQHandler()
    ( W& `: i  j4 ^$ V+ o
  3. 函数功能:定时器2中断服务函数% K. `* X  B8 d6 b" I
  4. 入口参数:无) y1 `/ t% g& g
  5. 返回参数:无% U3 [8 [' U. q
  6. 开发作者:闲人Ne
    " N+ q! v& V) ?& n( R+ U
  7. *************************************************/
    0 s) D' O  h' P% q' c$ r
  8. extern u8  OverflowNum_cnt;                                                                  // u8 计数器,用来计算溢出中断的次数,初始化值为0000 0000                                            4 `. a8 [/ c1 ?# A
  9. void TIM2_IRQHandler(void)4 G  a) S( g) i
  10. {
    " s9 j) K. F1 X8 `( C0 S! d  c( J
  11.         if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)              // 判断是否发生更新中断, G4 y+ r: k* @3 ~1 U
  12.         {
    - m2 f) \( }8 E
  13.                 if(OverflowNum_cnt==0XFF)                                              // 判断OverflowNum_cnt是否溢出                         7 c8 g& ]& h- j) o5 ~" D  ?
  14.                 {          $ u$ T, G( l) f5 Z% p' e
  15.                         printf("错误:超出最大计算时间!");' J$ g: G5 b& R! d) k1 S
  16.                         OverflowNum_cnt = 0;                          // OverflowNum_cnt置零- ^) V) u  V: W
  17.                 }5 W1 H# _6 L. P( d5 K
  18.                 else! c! U) U$ n/ t3 {. p) z
  19.                 {
    - O- b& [. C& J7 R' w/ y- U
  20.                         OverflowNum_cnt++;& r  A1 S  {0 Y* r1 }- F- I
  21.                 }
    $ D, A' q- @; l6 ~
  22.             TIM_ClearITPendingBit(TIM2,TIM_IT_Update);       // 清除定时器2中断标志位* U. w* T+ d) H! ^- v2 t7 s: Z
  23.         }( q3 F- Y- ~9 i$ c" {
  24. }
复制代码
4 y/ u3 z* o$ k
4.主函数,这里注意,当TIM2_arr = 7199,TIM2_psc = 0,那么TIM2 中断时间间隔为0.0001s,又因为u8 OverflowNum_cnt最大值为255,所以所创建的定时器2计算某段代码的运行时间上限是0.0001 X 255 = 0.0255s,即25.5ms。如果被测代码的实际运行时间大于25.5ms,那么就不适用了。
: H' ?! F) v* M( T. W" C
  1. /************************************************* K0 F1 n. C+ r
  2. 函数名称:int main()
    ( h" A5 B" M  |) I
  3. 函数功能:主函数入口- t( n1 T6 B/ A1 y- {5 d0 f
  4. 入口参数:无
    : |8 H0 |" g+ L* |4 t4 ~% U
  5. 返回参数:int
    - Y0 ~3 i# O! ^1 q- z6 J- d
  6. 开发作者:闲人Ne/ p8 j5 U/ i  }( @! U4 \# x
  7. *************************************************/- u; o$ o. [6 u- G- U' l  G
  8. u8  OverflowNum_cnt = 0;     // 溢出的次数- R+ N. P# N( W" O* Z$ J
  9. u16 cnt_value       = 0;     // 最后一次cnt的数值: D' R. X" H& f) c4 q8 c
  10. u16 TIM2_arr = 7199;  9 g+ `- V* Y+ J: l
  11. u16 TIM2_psc = 0;0 G6 _+ p7 E4 n0 S8 N
  12. float TIM2_looptime = 0.0001;                       // TIM2 中断时间间隔,TIM2_looptime=((TIM2_psc+1)/72000000)*(TIM2_arr+1)
    , I: I7 ~( T7 e6 q
  13. float TIM2_clock = 0.0000000138888888888;  // TIM2 cnt更新周期,TIM2_clock=1/72000000
    ' K: ]! `. ?, |) `; T# ?7 d
  14. u16 delay_time_ms=10;                      // 模拟某段代码的运行时间2 Z8 v9 r2 Y3 Q" r, J: a4 f" R8 L
  15. int main(void). D  Z3 [; L6 j
  16. {
    * d& y( A% {$ u& M0 [) d
  17.   float CodeRunTime=0;              // 计算某段代码的运行时间) T7 C9 W! k% E) L
  18.   u8 t=0;                           // while循环计数用% T+ C: q3 H7 ]
  19.   delay_init();: o/ X7 l0 K8 s) Y- g
  20.   LED_Init();
    ; z/ ^7 K% D! k$ f2 |3 y& H
  21.   My_USART1_Init();  
    + z# o' J2 y& [, \* [
  22.   TIM2_Init(TIM2_arr, TIM2_psc);        8 l$ d3 j' \: @# }0 v# l" i
  23.   NVIC_Configuration();, c+ F' n& j8 }5 ^. @( x: v
  24.   while(1)* g- \5 r- g; D6 O& `4 m
  25.   {
    - ]% a6 K' [8 Z* `# S! O/ C
  26.         TIM2_Clock_Start();
    5 I- i: ~9 @# V! N2 K) C# u5 d
  27.     delay_ms(delay_time_ms);             // 某段代码的运行时间
    , p0 J% M' u8 S) @
  28.         cnt_value=TIM2_Clock_End();: O; d" @+ D" o) I) g3 l
  29.         CodeRunTime = (float)cnt_value*TIM2_clock+(float)OverflowNum_cnt*TIM2_looptime;                6 P# m2 r3 [3 n( v* |: m. @
  30.         t++;
    + G/ j& G4 K) D( q$ w; V" ]! J
  31.         if(t==100)5 K$ w% r% z9 [) ~4 f& [$ I
  32.         {
      {% r3 C1 z2 B, d
  33.                 printf("设定某段代码的运行时间为:%d毫秒\r\n",delay_time_ms);
    ' ~. W0 K, j9 o; Y" ^
  34.                 printf("实际某段代码的运行时间为:%f秒\r\n\r\n",CodeRunTime);
    0 ~( ~1 {3 r: ]0 V0 a0 r! D
  35.                 D1=!D1;     //提示系统正在运行//        2 H) O2 z5 b" y& E: I
  36.                 t=0;
    ) |4 w( q6 D. {0 \. ]9 ^( B* x$ ^
  37.         }                 . }9 N4 a" Q. m$ q4 l" M7 v: M2 _' F
  38.         delay_time_ms=delay_time_ms+1;: A" T$ G' D4 i( c. ]- Z3 P1 S
  39.         if(delay_time_ms>20)4 y# f6 }# z9 F) N
  40.                 delay_time_ms=10;               
    + O7 Z9 u$ J$ [: M+ U
  41.   }
    , Q! X) y/ \7 a2 ^' V
  42. }
复制代码
+ p: Z% F% A# |. T" j
实验结果
6 A8 R! A4 q; W' P" [在串口调试助手上显示结果如下:' d% P- j; t3 C: j3 l
20210102144801409.png & e% J0 F' Q: f- r. ^6 p2 k6 b

1 F1 x( S; u% c; i5 a/ u: `3 n经验分享# x/ d9 b3 O0 [# Q# q! m
为什么要测试代码的运算时间?因为有时候,程序没必要运算的非常快,适当的降低运算时间,可以降低功耗。此外,有些功能需要实时的、快速的给与反馈,比如自动驾驶、无人机、主动控制这类工作,如果算法很牛逼,但是运算一次周期长,那也没什么实际用处。" \/ M1 {# B( d' O7 t  P+ B- v; _$ c
————————————————% Q  D* F& [1 e$ V/ [5 ]
版权声明:天亮继续睡2 ^" B) {( _' m

& _5 k( T( a4 G' {
5 `1 }0 ]& O) L) N
收藏 评论0 发布时间:2022-11-20 15:24

举报

0个回答

所属标签

相似分享

官网相关资源

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