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

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

[复制链接]
STMCU小助手 发布时间:2022-11-20 15:24
思路:1)利用通用定时器(选择定时器2)计算某段代码的运行时间;2)顾名思义,会基于定时器2创建两个函数(TIM2_Clock_Start和TIM2_Clock_End)分别控制定时器2开始计时和结束计时,被测代码放在这两个代码的中间;3)考虑计时的精度和最大计时长度,创建变量 u8 OverflowNum_cnt用来计算定时器2溢出中断的次数,创建变量u16 cnt_value用来计算最后一次定时器2的cnt值;4)利用USART1实时读取某段代码的运行时间,并上传至电脑,便于查看。这个工程较为简单,主要代码如下:1.定时器2的初始化配置代码,注意:初始化后,不使能TIM2!!
  1. /*****************************************************************
  2. 函数名称:TIM2_Init(u16 arr, u16 psc)
  3. 函数功能:定时器2 初始化函数
  4. 入口参数:u16 arr:自动重装载值, u16 psc:时钟预分频数
  5. 返回参数:无
  6. 开发作者:闲人Ne
  7. ******************************************************************/
  8. void TIM2_Init(u16 arr, u16 psc)
  9. {
  10.   TIM_TimeBaseInitTypeDef TIM_TimeBaseInitTypeStruct;
  11.   TIM_DeInit(TIM2);                                                                                       // 定时器 2 复位
  12.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);              // 使能TIM 2 时钟
  13.   // 定时器 2 参数初始化配置
  14.   TIM_TimeBaseInitTypeStruct.TIM_Period=arr;
  15.   TIM_TimeBaseInitTypeStruct.TIM_Prescaler=psc;
  16.   TIM_TimeBaseInitTypeStruct.TIM_CounterMode=TIM_CounterMode_Up;   // 向上计数模式
  17.   TIM_TimeBaseInitTypeStruct.TIM_ClockDivision=TIM_CKD_DIV1;
  18.   TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitTypeStruct);
  19.   // 定时器 3 中断优先级配置
  20.   NVIC_Configuration();
  21. }
复制代码
2.定时器2开始和结束相关代码,注意:引用了2个放在main.c文件里的变量!!
  1. /*****************************************************************
  2. 函数名称:TIM2_Clock_Start()
  3. 函数功能:使能定时器 2 函数,开始计时
  4. 入口参数:无
  5. 返回参数:无
  6. 开发作者:闲人Ne
  7. ******************************************************************/
  8. extern u8  OverflowNum_cnt;                                    // u8 计数器,用来计算溢出中断的次数,初始化值为0000 0000
  9. void TIM2_Clock_Start()
  10. {
  11.         OverflowNum_cnt = 0;
  12.         TIM2->CNT=0x00;                             // 将定时器 2 的计数器至零
  13.         TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);    // 针对TIM2_DIER寄存器,[0]位,UIE至1,允许更新中断
  14.         TIM_Cmd(TIM2,ENABLE);  
  15. }
  16. /*****************************************************************
  17. 函数名称:u16 TIM2_Clock_End()
  18. 函数功能:停止定时器 2 函数,读取CNT数值
  19. 入口参数:无
  20. 返回参数:u16 cnt_value,返回当前TIM2_CNT的值
  21. 开发作者:闲人Ne
  22. ******************************************************************/
  23. extern u16 cnt_value;
  24. u16 TIM2_Clock_End()
  25. {
  26.         cnt_value = TIM2->CNT;
  27.         TIM_Cmd(TIM2,DISABLE);
  28.         return cnt_value;
  29. }
复制代码
3.定时器2的中断服务函数,主要目的是每发生一次溢出中断,OverflowNum_cnt值+1,如果OverflowNum_cnt值溢出,就报错。
  1. /************************************************
  2. 函数名称:TIM2_IRQHandler()
  3. 函数功能:定时器2中断服务函数
  4. 入口参数:无
  5. 返回参数:无
  6. 开发作者:闲人Ne
  7. *************************************************/
  8. extern u8  OverflowNum_cnt;                                                                  // u8 计数器,用来计算溢出中断的次数,初始化值为0000 0000                                            
  9. void TIM2_IRQHandler(void)
  10. {
  11.         if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)              // 判断是否发生更新中断
  12.         {
  13.                 if(OverflowNum_cnt==0XFF)                                              // 判断OverflowNum_cnt是否溢出                        
  14.                 {         
  15.                         printf("错误:超出最大计算时间!");
  16.                         OverflowNum_cnt = 0;                          // OverflowNum_cnt置零
  17.                 }
  18.                 else
  19.                 {
  20.                         OverflowNum_cnt++;
  21.                 }
  22.             TIM_ClearITPendingBit(TIM2,TIM_IT_Update);       // 清除定时器2中断标志位
  23.         }
  24. }
复制代码
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,那么就不适用了。
  1. /************************************************
  2. 函数名称:int main()
  3. 函数功能:主函数入口
  4. 入口参数:无
  5. 返回参数:int
  6. 开发作者:闲人Ne
  7. *************************************************/
  8. u8  OverflowNum_cnt = 0;     // 溢出的次数
  9. u16 cnt_value       = 0;     // 最后一次cnt的数值
  10. u16 TIM2_arr = 7199;  
  11. u16 TIM2_psc = 0;
  12. float TIM2_looptime = 0.0001;                       // TIM2 中断时间间隔,TIM2_looptime=((TIM2_psc+1)/72000000)*(TIM2_arr+1)
  13. float TIM2_clock = 0.0000000138888888888;  // TIM2 cnt更新周期,TIM2_clock=1/72000000
  14. u16 delay_time_ms=10;                      // 模拟某段代码的运行时间
  15. int main(void)
  16. {
  17.   float CodeRunTime=0;              // 计算某段代码的运行时间
  18.   u8 t=0;                           // while循环计数用
  19.   delay_init();
  20.   LED_Init();
  21.   My_USART1_Init();  
  22.   TIM2_Init(TIM2_arr, TIM2_psc);        
  23.   NVIC_Configuration();
  24.   while(1)
  25.   {
  26.         TIM2_Clock_Start();
  27.     delay_ms(delay_time_ms);             // 某段代码的运行时间
  28.         cnt_value=TIM2_Clock_End();
  29.         CodeRunTime = (float)cnt_value*TIM2_clock+(float)OverflowNum_cnt*TIM2_looptime;               
  30.         t++;
  31.         if(t==100)
  32.         {
  33.                 printf("设定某段代码的运行时间为:%d毫秒\r\n",delay_time_ms);
  34.                 printf("实际某段代码的运行时间为:%f秒\r\n\r\n",CodeRunTime);
  35.                 D1=!D1;     //提示系统正在运行//        
  36.                 t=0;
  37.         }                 
  38.         delay_time_ms=delay_time_ms+1;
  39.         if(delay_time_ms>20)
  40.                 delay_time_ms=10;               
  41.   }
  42. }
复制代码
实验结果在串口调试助手上显示结果如下: 20210102144801409.png 经验分享为什么要测试代码的运算时间?因为有时候,程序没必要运算的非常快,适当的降低运算时间,可以降低功耗。此外,有些功能需要实时的、快速的给与反馈,比如自动驾驶、无人机、主动控制这类工作,如果算法很牛逼,但是运算一次周期长,那也没什么实际用处。————————————————版权声明:天亮继续睡
收藏 评论0 发布时间:2022-11-20 15:24

举报

0个回答

所属标签

相似分享

官网相关资源

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