搜索
bottom↓
回复: 10

分享一个us计数器,可测试代码运行时长

[复制链接]

出140入115汤圆

发表于 2019-4-29 16:19:53 | 显示全部楼层 |阅读模式
本帖最后由 yanyanyan168 于 2019-4-29 20:08 编辑

        从 KEIL MDK 的 Event Recorder 摘出SysTick配置,改成微秒计数器与微秒延时,可以用在M0/M0+/M3/M4等内核MCU上。
应用场景,测试某段代码的运行时长,精确微秒延时。 代码如下,献丑了

  1. typedef struct
  2. {
  3. uint32_t (*init)(void);
  4.   void     (*set)(uint8_t id);        // 设置当前值
  5.   uint32_t (*get)(uint8_t id);        // 获取与上次的差值       
  6.   void            (*Delay)(uint32_t nus);
  7. }
  8. US_DIFF_TypeDef;


  9. /* SysTick period in cycles */
  10. #ifndef SYSTICK_PERIOD
  11. #define SYSTICK_PERIOD  0x01000000U
  12. #endif

  13. /* SysTick variables */
  14. static volatile uint32_t SysTickCount;
  15. static volatile uint8_t  SysTickUpdated;

  16. /* SysTick IRQ handler */
  17. void SysTick_Handler (void) {
  18.   SysTickCount  += SYSTICK_PERIOD;
  19.   SysTickUpdated = 1U;
  20. }

  21. /* Setup SysTick */
  22. uint32_t SysTickSetup (void) {
  23.   SysTickCount  = 0U;
  24.   SysTick->LOAD = SYSTICK_PERIOD - 1U;
  25.   SysTick->VAL  = 0U;
  26.   SysTick->CTRL = SysTick_CTRL_ENABLE_Msk     |
  27.                   SysTick_CTRL_TICKINT_Msk    |
  28.                   SysTick_CTRL_CLKSOURCE_Msk;
  29.   return 1U;
  30. }


  31. /* Get SysTick count */
  32. __STATIC_INLINE uint32_t SysTickGetCount (void) {
  33.   uint32_t val;

  34.   do {
  35.     SysTickUpdated = 0U;
  36.     val  = SysTickCount;
  37.     val += (SYSTICK_PERIOD - 1U) - SysTick->VAL;
  38.   } while (SysTickUpdated != 0U);

  39.   return (val);
  40. }

  41. #define TIMER_NUM_MAX  10             // 计数器最多可支持9个, 最后一个做延时用
  42. static uint32_t us_count[TIMER_NUM_MAX];  

  43. /// 设置计数值初值
  44. void set_current_count(uint8_t id)
  45. {
  46. //        my_assert_param(id < TIMER_NUM_MAX);
  47.     us_count[id]        = SysTickGetCount();
  48. }


  49. // 获取与上一次的差值 返回的是时钟周期数,,转换成微秒需要除以(SystemCoreClock/1000000)
  50. uint32_t get_us_difference(uint8_t id)
  51. {
  52.         volatile uint32_t now_tim ;
  53. //        my_assert_param(id < TIMER_NUM_MAX);
  54.         now_tim = SysTickGetCount();
  55.         now_tim -= us_count[id];

  56.         return now_tim;
  57. }

  58. // 微秒延时
  59. static void usDelay(uint32_t nus)
  60. {
  61.         nus *= (SystemCoreClock/1000000);
  62.         set_current_count(TIMER_NUM_MAX-1);
  63.         volatile uint32_t now_tim ;
  64.         do
  65.         {
  66.                 now_tim = get_us_difference(TIMER_NUM_MAX-1);
  67.         }while(now_tim < nus);
  68. }

  69. US_DIFF_TypeDef usDiff =
  70. {
  71.         SysTickSetup,
  72.         set_current_count,
  73.         get_us_difference,
  74.         usDelay
  75. };

复制代码



应该方法:

  1. uint32_t us_code_tim; // 代码运行时钟周期数,转换成微秒需要除以(SystemCoreClock/1000000)

  2. int32_t main(void)
  3. {
  4.         /* 其它外设初始化   */
  5.         usDiff.init();
  6.         for(;;)
  7.         {
  8.                 usDiff.set(0);
  9.                
  10.                 /* 要测试的代码 */
  11.                
  12.                 us_code_tim = usDiff.get(0);
  13.                
  14.                 usDiff.Delay(200); // 延时200us
  15.         }
  16. }

  17. uint32_t us_tim3; // TIM3中断间隔时钟周期数,,转换成微秒需要除以(SystemCoreClock/1000000)

  18. void TIM3_IRQHandler(void)
  19. {
  20.     /* 其它代码 */
  21.         us_tim3 = usDiff.get(1); // 第一次不准
  22.         usDiff.set(1);
  23. }
复制代码

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2019-4-30 13:36:03 来自手机 | 显示全部楼层
还是使用io引脚测量时间,简单可靠。我的信念:尽量避免一切导致复杂的东西,除了jscope  rtt。

出0入475汤圆

发表于 2019-4-30 13:42:33 来自手机 | 显示全部楼层
我也新欢直接示波器看专门拉出来的引脚,这样避免很多问题,比如系统时钟设置不对,软件编写错误,框架设计错误等等

出0入0汤圆

发表于 2019-4-30 14:01:38 | 显示全部楼层
谢谢分享。。。。。。。

出0入90汤圆

发表于 2019-4-30 14:21:20 | 显示全部楼层
这是弄了一个1us的定时器吗?还要进中断,这也太频繁了吧。不如搞个定时器1us计数。然后用查询模式,在一个需要测量的函数或者代码段,的前后都读一下。基本就知道时间了。测量10us级别的也够了。

出40入42汤圆

发表于 2019-4-30 14:59:40 | 显示全部楼层
来来来,同款功能的另一种实现
https://www.amobbs.com/thread-5665490-1-1.html

出0入0汤圆

发表于 2019-4-30 20:25:04 来自手机 | 显示全部楼层
直接开一个timer,32位最好。运行之前读一下,运行之后读一下。差值就是时间。

出0入76汤圆

发表于 2019-4-30 20:55:14 | 显示全部楼层
TO 楼上: 在没有示波器的时候 我也是这么干的, 测量某个算法执行的时间; 有示波器,输出到IO上,直接用示波器时间了。   

出140入115汤圆

 楼主| 发表于 2019-4-30 22:08:47 来自手机 | 显示全部楼层
honami520 发表于 2019-4-30 14:21
这是弄了一个1us的定时器吗?还要进中断,这也太频繁了吧。不如搞个定时器1us计数。然后用查询模式,在一个 ...

16,777,216个时钟周期进一次中断,不算频繁吧,72MHz也要200多ms。

出140入115汤圆

 楼主| 发表于 2019-4-30 22:11:47 来自手机 | 显示全部楼层
落叶知秋 发表于 2019-4-30 14:59
来来来,同款功能的另一种实现
https://www.amobbs.com/thread-5665490-1-1.html ...

对,在M3/M4用的就是这个,华大的M0+不知道如何配置。

出0入4汤圆

发表于 2019-4-30 23:00:49 | 显示全部楼层
我都是用逻辑分析仪,找个信号引脚测试,
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-26 17:42

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表