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

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

[复制链接]
STMCU小助手 发布时间:2022-11-20 15:24
思路:+ ]# l3 {' \5 R3 O, l
1)利用通用定时器(选择定时器2)计算某段代码的运行时间;4 c+ ^+ Y5 |' o( |# n
2)顾名思义,会基于定时器2创建两个函数(TIM2_Clock_Start和TIM2_Clock_End)分别控制定时器2开始计时和结束计时,被测代码放在这两个代码的中间;8 v; o% M  U( \1 I' Y
3)考虑计时的精度和最大计时长度,创建变量 u8 OverflowNum_cnt用来计算定时器2溢出中断的次数,创建变量u16 cnt_value用来计算最后一次定时器2的cnt值;) ?  ]" F1 K. k0 H( F3 s6 P9 T
4)利用USART1实时读取某段代码的运行时间,并上传至电脑,便于查看。
& J8 @; E& j0 J6 F  m. F: \) V2 _1 Z- V* ?, \+ Q. `! W
这个工程较为简单,主要代码如下:" s: |- R$ b* P; A7 `0 m2 u
8 N* O  l+ y8 K# E
1.定时器2的初始化配置代码,注意:初始化后,不使能TIM2!!3 J. b7 a% ]( f7 N1 E
  1. /****************************************************************** E: W6 f; G$ Y4 C) T
  2. 函数名称:TIM2_Init(u16 arr, u16 psc)
    * [3 u/ _7 p  D) ]
  3. 函数功能:定时器2 初始化函数
    2 @4 L* E) i: G: S7 [" a$ L# M7 C
  4. 入口参数:u16 arr:自动重装载值, u16 psc:时钟预分频数
    ' B5 q' u9 y& s! D
  5. 返回参数:无. K- F" B6 u) F7 A/ @
  6. 开发作者:闲人Ne
    2 K% j! B6 C) H, M+ e$ t' J# A8 R
  7. ******************************************************************/
    % `! X4 d0 K5 Z& Y; x5 K/ X. ]
  8. void TIM2_Init(u16 arr, u16 psc)  w' T1 b$ ?6 d7 V- l* B+ J
  9. {; z( u% ?! I3 `* L4 ~% m! Z
  10.   TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeStruct;
    " A& v: h2 T- ?4 T( |2 `
  11.   TIM_DeInit(TIM2);                                                                                       // 定时器 2 复位! e( O1 @, |' e3 c# @! e
  12.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);              // 使能TIM 2 时钟
    : x0 Z7 f, F, M3 b1 J2 t" b
  13.   // 定时器 2 参数初始化配置
    9 a, E) B- N, J/ v2 |( ~% t, N
  14.   TIM_TimeBaseInitTypeStruct.TIM_Period=arr;$ {- O7 j. L0 ?: b; K
  15.   TIM_TimeBaseInitTypeStruct.TIM_Prescaler=psc;
    5 q) n$ ^. g1 @2 D
  16.   TIM_TimeBaseInitTypeStruct.TIM_CounterMode=TIM_CounterMode_Up;   // 向上计数模式4 @# K% N# e6 ^1 z+ f- Z# n
  17.   TIM_TimeBaseInitTypeStruct.TIM_ClockDivision=TIM_CKD_DIV1;
    ! D: t% m) ?+ v$ h0 L7 w
  18.   TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitTypeStruct);, V# Y& g6 U, \
  19.   // 定时器 3 中断优先级配置
    ' p  z) ~1 g  s
  20.   NVIC_Configuration();
      L- n0 K( `. J  f4 C' S/ ~
  21. }
复制代码

3 W! o$ J0 r4 s2.定时器2开始和结束相关代码,注意:引用了2个放在main.c文件里的变量!!
: P/ S( d6 k5 t3 S
  1. /*****************************************************************6 \9 `; v- q+ B1 n% ~% e
  2. 函数名称:TIM2_Clock_Start()
    * U4 I+ E& Y: s& D9 x
  3. 函数功能:使能定时器 2 函数,开始计时
      Y4 _) n# W1 N4 m- C% V# ~
  4. 入口参数:无& ^& o5 q9 z' i2 t& ^
  5. 返回参数:无
    7 k' r  z" Y/ h& ]+ x/ H5 x" X3 A! d
  6. 开发作者:闲人Ne
    3 n5 U6 R5 N4 d3 [8 ^8 Z
  7. ******************************************************************/# L& p8 s* [& s" G* D. P
  8. extern u8  OverflowNum_cnt;                                    // u8 计数器,用来计算溢出中断的次数,初始化值为0000 00009 R6 _1 D0 b; h. ~4 `3 ^$ M
  9. void TIM2_Clock_Start()" a) m6 f4 n) v6 l" L
  10. {/ v, c- k( D( b. |+ i
  11.         OverflowNum_cnt = 0;
    7 j* y$ o$ O( [9 m/ k. E1 B
  12.         TIM2->CNT=0x00;                             // 将定时器 2 的计数器至零
    6 m, x7 p% F( W5 G4 u7 C
  13.         TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);    // 针对TIM2_DIER寄存器,[0]位,UIE至1,允许更新中断; ]+ C% M: G( W3 d; n6 n
  14.         TIM_Cmd(TIM2,ENABLE);  , p7 `9 H* Z: n* F/ D  j
  15. }
    - G4 h( Y' `2 C+ `
  16. /*****************************************************************
    3 |2 H  _; q" s5 F+ `- `. O
  17. 函数名称:u16 TIM2_Clock_End()
    $ g" \8 l0 \) x& W# I
  18. 函数功能:停止定时器 2 函数,读取CNT数值0 J! U* W) Q) w. i; J+ e) |
  19. 入口参数:无
    $ a9 p1 {+ F) ?, A) Q$ C
  20. 返回参数:u16 cnt_value,返回当前TIM2_CNT的值( V: W5 V6 C5 e+ b8 n  w
  21. 开发作者:闲人Ne) P1 `  A+ L8 t# @, p
  22. ******************************************************************/) V: `- O8 \- @& ]7 u4 ]
  23. extern u16 cnt_value;( g. r* ?: `3 m! }
  24. u16 TIM2_Clock_End()+ N8 p- \$ O1 i) D
  25. {0 b, w+ }1 Y) Y% [
  26.         cnt_value = TIM2->CNT;/ |8 `& s$ |' _# X" K/ ^8 E
  27.         TIM_Cmd(TIM2,DISABLE);* |1 P. C& r* E/ ^/ f
  28.         return cnt_value;! z% l1 I: ^( ~: Q6 K1 Q) _+ ~9 v
  29. }( ?- H& w# l8 y/ X
复制代码
" P/ L. ]6 L* r% Z
3.定时器2的中断服务函数,主要目的是每发生一次溢出中断,OverflowNum_cnt值+1,如果OverflowNum_cnt值溢出,就报错。: r3 j3 l7 ]/ G2 I8 y0 j3 x* M
  1. /************************************************0 K9 P# @7 v$ q2 a
  2. 函数名称:TIM2_IRQHandler()
    6 A2 z6 N7 m2 q6 U$ J3 K
  3. 函数功能:定时器2中断服务函数+ ]% N- `  J/ _/ F- O0 S% k6 N
  4. 入口参数:无, m& Y' H2 F/ p# O
  5. 返回参数:无* K4 `5 u# k" @; i* h/ w
  6. 开发作者:闲人Ne
    ; z3 N0 t+ b9 z$ R( |$ t
  7. *************************************************/
    * Q# z) d& X% s9 Y
  8. extern u8  OverflowNum_cnt;                                                                  // u8 计数器,用来计算溢出中断的次数,初始化值为0000 0000                                            
    & X" c) _/ E  I. o( i
  9. void TIM2_IRQHandler(void)
    ( h& e; m( S2 n. }$ }6 ^( w
  10. {
    - `& D6 W- X: C4 y& l5 s
  11.         if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)              // 判断是否发生更新中断
    5 E! f; \( h  L) {% ^- i
  12.         {% _5 e0 R/ s; Q( O
  13.                 if(OverflowNum_cnt==0XFF)                                              // 判断OverflowNum_cnt是否溢出                         0 z6 e5 p8 R* ~( F
  14.                 {          - a$ K$ _" J, \/ X1 l4 y
  15.                         printf("错误:超出最大计算时间!");
    2 a0 @& c- i# N
  16.                         OverflowNum_cnt = 0;                          // OverflowNum_cnt置零
    6 p, Q% @; H0 V0 n0 w: m4 Y) `
  17.                 }# n8 P- w9 w% c9 B/ }  L
  18.                 else+ S6 R6 O0 S: s* d
  19.                 {  ^( C. V/ C  j7 ^0 i
  20.                         OverflowNum_cnt++;5 _9 H( b8 ^8 b; A+ v) L2 p
  21.                 }
    1 `9 Q8 m3 L3 J; q
  22.             TIM_ClearITPendingBit(TIM2,TIM_IT_Update);       // 清除定时器2中断标志位! L7 g$ G1 _9 Z5 `3 Z
  23.         }
    9 `6 U% a# ^2 C2 }6 w
  24. }
复制代码
# z: O) _; {1 T. ~4 j
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,那么就不适用了。
0 N8 @9 d9 D; b- J
  1. /************************************************( \. G" D4 c: v5 p( P6 O0 }0 S
  2. 函数名称:int main()5 U2 _! Z  ~6 X
  3. 函数功能:主函数入口
    # T1 E% z' W$ V0 z
  4. 入口参数:无
    . x. |9 \( q: W5 M6 j
  5. 返回参数:int
    ; E3 H+ Z0 J$ x: w# T2 r  {
  6. 开发作者:闲人Ne0 P/ ?' E3 Y) o, g& D: o
  7. *************************************************/; |0 M: a5 q* n+ t
  8. u8  OverflowNum_cnt = 0;     // 溢出的次数: T7 k4 Y4 h1 i& U" ~# q; G7 ~; Y
  9. u16 cnt_value       = 0;     // 最后一次cnt的数值
    + D1 Y& }: R7 H3 l4 |- v
  10. u16 TIM2_arr = 7199;  / `- Z7 P: H/ i; ]5 G
  11. u16 TIM2_psc = 0;
    * _+ ]' }5 `2 K! d: p
  12. float TIM2_looptime = 0.0001;                       // TIM2 中断时间间隔,TIM2_looptime=((TIM2_psc+1)/72000000)*(TIM2_arr+1)
    6 }! o' D( X$ D/ Y$ e& T5 n5 E5 \% x
  13. float TIM2_clock = 0.0000000138888888888;  // TIM2 cnt更新周期,TIM2_clock=1/720000005 z% _1 \9 ]) d) f& Y
  14. u16 delay_time_ms=10;                      // 模拟某段代码的运行时间0 c! v* T# p) q) C1 l% m9 {
  15. int main(void)- j, W3 n8 L0 S7 q& Z. J9 f) a8 F
  16. {& y7 H* T/ G, `% w
  17.   float CodeRunTime=0;              // 计算某段代码的运行时间2 N- F9 d2 ^0 K1 D$ G
  18.   u8 t=0;                           // while循环计数用& Y6 I" N: R: U) v
  19.   delay_init();
    4 ?8 L. f$ Q4 ]# r
  20.   LED_Init();, @/ m2 f" _) B$ b; X
  21.   My_USART1_Init();  
    , F( }! o& X( v
  22.   TIM2_Init(TIM2_arr, TIM2_psc);        1 d4 f5 z/ K/ x7 Y! T' [
  23.   NVIC_Configuration();7 Y8 T+ j# Y! y7 t* S
  24.   while(1)- V$ y0 K& f. z& I
  25.   {
    ' |6 d6 E% F( b4 \
  26.         TIM2_Clock_Start();9 {6 h$ h! ?! l. d
  27.     delay_ms(delay_time_ms);             // 某段代码的运行时间
    . y/ e- i. \9 a
  28.         cnt_value=TIM2_Clock_End();
    * Q- B1 Y# z6 `- P9 Y
  29.         CodeRunTime = (float)cnt_value*TIM2_clock+(float)OverflowNum_cnt*TIM2_looptime;                , A& f0 O$ G1 K9 R. N) M4 M
  30.         t++;
    & o/ V! d* ?# K9 S& `1 B7 R
  31.         if(t==100)
    9 Q2 Q$ C/ \9 f
  32.         {+ B+ c4 H( Y) \$ V7 t. D
  33.                 printf("设定某段代码的运行时间为:%d毫秒\r\n",delay_time_ms);! ~# V. F6 `/ E1 Z" C9 @' v
  34.                 printf("实际某段代码的运行时间为:%f秒\r\n\r\n",CodeRunTime);
    0 }1 x" t/ F( X2 L5 r- Q, |2 `
  35.                 D1=!D1;     //提示系统正在运行//        / Q3 S! e" T- K8 b6 V! q" g
  36.                 t=0;
    2 g6 E7 A1 \" m# M' j" b
  37.         }                 
    1 J6 [& p1 T/ A& N6 x* i4 _
  38.         delay_time_ms=delay_time_ms+1;
    6 z4 `0 ?+ @/ B5 i! _
  39.         if(delay_time_ms>20), w) z2 D  f" w: Y. {# k0 T6 x' d
  40.                 delay_time_ms=10;                4 i, _# n/ _* T& ^( P/ R, {6 n# E
  41.   }
    ' H1 ?6 U. }" s/ y) O
  42. }
复制代码
2 M  n  A/ J3 ?. X/ x& u' y9 U
实验结果
: p5 }2 q! ~8 T$ p在串口调试助手上显示结果如下:5 z" q  u- \% \7 \- N/ l9 |
20210102144801409.png + K6 l, T; C  C

9 r' d+ k/ y) r, c& Y经验分享% g) q, I/ x0 A7 ]' K5 J
为什么要测试代码的运算时间?因为有时候,程序没必要运算的非常快,适当的降低运算时间,可以降低功耗。此外,有些功能需要实时的、快速的给与反馈,比如自动驾驶、无人机、主动控制这类工作,如果算法很牛逼,但是运算一次周期长,那也没什么实际用处。
; |& u/ h' R& l: a3 S& u, }; i————————————————; `' F9 S7 m: ]: o4 V
版权声明:天亮继续睡2 U% R1 B% Z, a0 c, l6 b6 |
9 J. D6 i' X1 C; l3 K/ X

3 P% U* O( u( s2 _% C
赞 收藏 评论0 发布时间:2022-11-20 15:24

举报

0个回答

所属标签

相似技术帖

官网相关资源

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