12下一页
返回列表 发新帖我要提问本帖赏金: 50.00元(功能说明)

[AT32F403/403A] 测量代码片段运行时间

[复制链接]
 楼主| zexin 发表于 2024-10-21 10:41 | 显示全部楼层 |阅读模式
<
本帖最后由 zexin 于 2024-10-21 15:20 编辑

#申请原创#
代码运行时间的三种测量方法
一、基本介绍
在软件调试过程中,测量代码片段的运行时间对理解程序执行过程和优化程序执行效率有重要意义。本文以测量ADC转换时间为例,介绍以下三种方法。
①GPIO翻转法:在ADC转换前后,将引脚电平的高低状态作为时间测量的起止点,利用逻辑分析仪或示波器等设备读取GPIO状态变化的时间差
②调试器跟踪法:以AT-link为例,在ADC转换开始和结束设置断点,读取断点间代码运行的时间差
③DWT(DataWatchpoint and Trace)测量法:在ADC转换开始前后,利用DWT的计数器记录起止点之间执行的指令数,根据指令数和系统时钟计算时间差
二、案例搭建
1.简介
使用PA0PA1两个通道采集外部信号,用不同方法测试ADC的转换时间。
2.步骤
①开启ADC1的通道0和通道1;
d18a7680428db44f86a584c110d7c2b9
②开启普通通道的序列模式,设置通道数目以及采样时间
a8b77134d69af5113cdf440a25a018b7
③添加DMA请求;
4b82a5cbd6cda5d7a215a3ca1a94ff54
④开启DMA中断;
23c95e74798926aba964332d1e82af17
⑤如果使用“GPIO电平翻转法”来测试,还需要配置一个GPIO作为输出(以PA4为例);
889e714989ba3d26ec4fd234beb1d8e6
⑥生成代码。
三、主要代码
main.c
  1. #include "at32f403a_407_wk_config.h"
  2. #include "wk_system.h"
  3. //#include "timecalculate.h" /*(DWT测量法)*/

  4. uint16_t adc_value[2] = {0}; //用于存放外部信号的adc数组
  5. uint16_t dma_trans_complete_flag = 0; //dma转换完成标志
  6. //uint16_t start = 0, stop = 0; /*(DWT测量法)*/
  7. /*(调试器跟踪法)——基本配置*/
  8. /*
  9. void disable_swo_debug_config(void)
  10. {
  11.   crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
  12.   gpio_pin_remap_config(SWJTAG_GMUX_010, TRUE);

  13. //  DEBUGMCU->ctrl_bit.trace_ioen = FALSE;
  14.   DEBUGMCU->ctrl_bit.trace_ioen = TRUE;
  15. }
  16. */

  17. int main(void)
  18. {
  19.   wk_system_clock_config();
  20.   wk_periph_clock_config();
  21. //disable_swo_debug_config();/*(调试器跟踪法)——使能swo功能*/
  22.   wk_nvic_config();
  23.   wk_timebase_init();
  24.   wk_dma1_channel1_init();
  25.   wk_dma_channel_config(DMA1_CHANNEL1,
  26.                         (uint32_t)&ADC1->odt,
  27.                         DMA1_CHANNEL1_MEMORY_BASE_ADDR,
  28.                         DMA1_CHANNEL1_BUFFER_SIZE);
  29.   dma_channel_enable(DMA1_CHANNEL1, TRUE);
  30.   wk_adc1_init();
  31.   wk_gpio_config(); /*GPIO翻转法*/
  32.   adc_ordinary_software_trigger_enable(ADC1, TRUE);
  33.   //start = ARM_CM_DWT_CYCCNT; /*(DWT测量法)*/
  34.   //gpio_bits_set(GPIOA, GPIO_PINS_4); /*(GPIO翻转法)*/
  35.   while(dma_trans_complete_flag == 0); //等待DMA传输完成

  36.   while(1)
  37.   {
  38.    
  39.   }
  40. }
at32f403a_407_wk_config.c
  1. #include "at32f403a_407_wk_config.h"
  2. void wk_system_clock_config(void)
  3. {
  4. crm_reset();
  5. crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);
  6. while(crm_flag_get(CRM_LICK_STABLE_FLAG) != SET)
  7. {
  8. }
  9. crm_clock_source_enable(CRM_CLOCK_SOURCE_HICK, TRUE);
  10. while(crm_flag_get(CRM_HICK_STABLE_FLAG) != SET)
  11. {
  12. }
  13. crm_pll_config(CRM_PLL_SOURCE_HICK, CRM_PLL_MULT_60, CRM_PLL_OUTPUT_RANGE_GT72MHZ);
  14. crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);
  15. while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
  16. {
  17. }
  18. crm_ahb_div_set(CRM_AHB_DIV_1);
  19. crm_apb2_div_set(CRM_APB2_DIV_2);
  20. crm_apb1_div_set(CRM_APB1_DIV_2);
  21. crm_auto_step_mode_enable(TRUE);
  22. crm_sysclk_switch(CRM_SCLK_PLL);
  23. while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
  24. {
  25. }
  26. crm_auto_step_mode_enable(FALSE);
  27. system_core_clock_update();
  28. }
  29. void wk_periph_clock_config(void)
  30. {
  31. crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
  32. crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
  33. crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  34. crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
  35. crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
  36. }
  37. void wk_nvic_config(void)
  38. {
  39. nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  40. NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
  41. nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
  42. }
  43. void wk_gpio_config(void)
  44. {
  45. gpio_init_type gpio_init_struct;
  46. gpio_default_para_init(&gpio_init_struct);
  47. gpio_bits_reset(GPIOA, GPIO_PINS_4);
  48. gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  49. gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  50. gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  51. gpio_init_struct.gpio_pins = GPIO_PINS_4;
  52. gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  53. gpio_init(GPIOA, &gpio_init_struct);
  54. }
  55. void wk_adc1_init(void)
  56. {
  57. gpio_init_type gpio_init_struct;
  58. adc_base_config_type adc_base_struct;
  59. gpio_default_para_init(&gpio_init_struct);
  60. gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
  61. gpio_init_struct.gpio_pins = GPIO_PINS_0;
  62. gpio_init(GPIOA, &gpio_init_struct);
  63. gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
  64. gpio_init_struct.gpio_pins = GPIO_PINS_1;
  65. gpio_init(GPIOA, &gpio_init_struct);
  66. crm_adc_clock_div_set(CRM_ADC_DIV_6);
  67. adc_combine_mode_select(ADC_INDEPENDENT_MODE);
  68. adc_base_default_para_init(&adc_base_struct);
  69. adc_base_struct.sequence_mode = TRUE;
  70. adc_base_struct.repeat_mode = FALSE;
  71. adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
  72. adc_base_struct.ordinary_channel_length = 2;
  73. adc_base_config(ADC1, &adc_base_struct);
  74. adc_ordinary_channel_set(ADC1, ADC_CHANNEL_0, 1, ADC_SAMPLETIME_239_5);
  75. adc_ordinary_channel_set(ADC1, ADC_CHANNEL_1, 2, ADC_SAMPLETIME_239_5);
  76. adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
  77. adc_ordinary_part_mode_enable(ADC1, FALSE);
  78. adc_dma_mode_enable(ADC1, TRUE);
  79. adc_enable(ADC1, TRUE);
  80. adc_calibration_init(ADC1);
  81. while(adc_calibration_init_status_get(ADC1));
  82. adc_calibration_start(ADC1);
  83. while(adc_calibration_status_get(ADC1));
  84. }
  85. void wk_dma1_channel1_init(void)
  86. {
  87. dma_init_type dma_init_struct;
  88. dma_reset(DMA1_CHANNEL1);
  89. dma_default_para_init(&dma_init_struct);
  90. dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  91. dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
  92. dma_init_struct.memory_inc_enable = TRUE;
  93. dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
  94. dma_init_struct.peripheral_inc_enable = FALSE;
  95. dma_init_struct.priority = DMA_PRIORITY_LOW;
  96. dma_init_struct.loop_mode_enable = FALSE;
  97. dma_init(DMA1_CHANNEL1, &dma_init_struct);
  98. dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_ADC1);
  99. dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
  100. }
  101. void wk_dma_channel_config(dma_channel_type* dmax_channely, uint32_t peripheral_base_addr, uint32_t memory_base_addr, uint16_t buffer_size)
  102. {
  103. dmax_channely->dtcnt = buffer_size;
  104. dmax_channely->paddr = peripheral_base_addr;
  105. dmax_channely->maddr = memory_base_addr;
  106. }
at32f403a_407_wk_config.h
  1. #ifndef __AT32F403A_407_WK_CONFIG_H
  2. #define __AT32F403A_407_WK_CONFIG_H
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. #include "at32f403a_407.h"
  7. #define DMA1_CHANNEL1_BUFFER_SIZE 2 //DMA传输数据个数
  8. #define DMA1_CHANNEL1_MEMORY_BASE_ADDR (uint32_t)adc_value //DMA传输目标地址
  9. void wk_system_clock_config(void);
  10. void wk_periph_clock_config(void);
  11. void wk_nvic_config(void);
  12. void wk_gpio_config(void);
  13. void wk_adc1_init(void);
  14. void wk_dma1_channel1_init(void);
  15. void wk_dma_channel_config(dma_channel_type* dmax_channely, uint32_t peripheral_base_addr, uint32_t memory_base_addr, uint16_t buffer_size);
  16. #ifdef __cplusplus
  17. }
  18. #endif
  19. #endif
  20.   
at32f403a_407_int.c
  1. #include "at32f403a_407_int.h"
  2. #include "wk_system.h"
  3. //#include "timecalculate.h" /*(DWT测量法)*/
  4. extern uint16_t dma_trans_complete_flag;
  5. //extern uint16_t stop; /*(DWT测量法)*/
  6. void SysTick_Handler(void)
  7. {
  8. wk_timebase_handler();
  9. }
  10. void DMA1_Channel1_IRQHandler(void)
  11. {
  12. //stop = ARM_CM_DWT_CYCCNT; /*(DWT测量法)*/
  13. //gpio_bits_reset(GPIOA, GPIO_PINS_4); /*(GPIO翻转法)*/
  14. if(dma_interrupt_flag_get(DMA1_FDT1_FLAG) != RESET)
  15. {
  16. dma_flag_clear(DMA1_FDT1_FLAG);
  17. dma_trans_complete_flag = 1;
  18. }
  19. }
  20.   
四、测试方法
不同测试方法的main.c和at32f403a_407_int.c略有不同,其他基本一致。
1.GPIO翻转法
介绍
GPIO在ADC转换前为低电平,转换开始时为高电平,转换结束后为低电平
代码
main.c
  1. #include "at32f403a_407_wk_config.h"
  2. #include "wk_system.h"
  3. uint16_t adc_value[2] = {0}; //用于存放外部信号的adc数组
  4. uint16_t dma_trans_complete_flag = 0; //dma转换完成标志
  5. int main(void)
  6. {
  7. wk_system_clock_config();
  8. wk_periph_clock_config();
  9. wk_nvic_config();
  10. wk_timebase_init();
  11. wk_dma1_channel1_init();
  12. wk_dma_channel_config(DMA1_CHANNEL1,
  13. (uint32_t)&ADC1->odt,
  14. DMA1_CHANNEL1_MEMORY_BASE_ADDR,
  15. DMA1_CHANNEL1_BUFFER_SIZE);
  16. dma_channel_enable(DMA1_CHANNEL1, TRUE);
  17. wk_adc1_init();
  18. wk_gpio_config(); /*GPIO翻转法——默认PA4为低电平*/
  19. adc_ordinary_software_trigger_enable(ADC1, TRUE);
  20. gpio_bits_set(GPIOA, GPIO_PINS_4); /*(GPIO翻转法)——ADC开始转换后PA4设为高电平*/
  21. while(dma_trans_complete_flag == 0); //等待DMA传输完成
  22. while(1)
  23. {
  24. }
  25. }
at32f403a_407_int.c
  1. #include "at32f403a_407_int.h"
  2. #include "wk_system.h"
  3. extern uint16_t dma_trans_complete_flag;
  4. void SysTick_Handler(void)
  5. {
  6. wk_timebase_handler();
  7. }
  8. void DMA1_Channel1_IRQHandler(void)
  9. {
  10. gpio_bits_reset(GPIOA, GPIO_PINS_4); /*(GPIO翻转法)——ADC转换结束后PA4设为低电平*/
  11. if(dma_interrupt_flag_get(DMA1_FDT1_FLAG) != RESET)
  12. {
  13. dma_flag_clear(DMA1_FDT1_FLAG);
  14. dma_trans_complete_flag = 1;
  15. }
  16. }
  17.   
结果
①理论时间
单个通道:(采样+转换)时间= (采样时间+12.5)个ADCCLK周期;
两个通道:T_calculate = (239.5+12.5) ÷ 20M × 2 = 25.2us
②实测时间
d5fe5c8a64c1b4806ba384cc52a2ce25
逻辑分析仪测量得ADC转换(两个通道)时间T_test = 25.75us
2.调试器跟踪法(AT-Link)
介绍
使用AT-link进入调试,测量两个断点之间的时间差代码
main.c
  1. #include "at32f403a_407_wk_config.h"
  2. #include "wk_system.h"
  3. uint16_t adc_value[2] = {0}; //用于存放外部信号的adc数组
  4. uint16_t dma_trans_complete_flag = 0; //dma转换完成标志
  5. /*(调试器跟踪法)——基本配置*/
  6. void disable_swo_debug_config(void)
  7. {
  8.   crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
  9.   gpio_pin_remap_config(SWJTAG_GMUX_010, TRUE);

  10. //DEBUGMCU->ctrl_bit.trace_ioen = FALSE;
  11.   DEBUGMCU->ctrl_bit.trace_ioen = TRUE;
  12. }

  13. int main(void)
  14. {
  15.   wk_system_clock_config();
  16.   wk_periph_clock_config();
  17.   disable_swo_debug_config();/*(调试器跟踪法)——使能swo功能*/
  18.   wk_nvic_config();
  19.   wk_timebase_init();
  20.   wk_dma1_channel1_init();
  21.   wk_dma_channel_config(DMA1_CHANNEL1,
  22.                         (uint32_t)&ADC1->odt,
  23.                         DMA1_CHANNEL1_MEMORY_BASE_ADDR,
  24.                         DMA1_CHANNEL1_BUFFER_SIZE);
  25.   dma_channel_enable(DMA1_CHANNEL1, TRUE);
  26.   wk_adc1_init();
  27.   adc_ordinary_software_trigger_enable(ADC1, TRUE);
  28.   while(dma_trans_complete_flag == 0); //等待DMA传输完成

  29.   while(1)
  30.   {
  31.    
  32.   }
  33. }
at32f403a_407_int.c
  1. #include "at32f403a_407_int.h"
  2. #include "wk_system.h"

  3. extern uint16_t dma_trans_complete_flag;

  4. void SysTick_Handler(void)
  5. {
  6. wk_timebase_handler();
  7. }
  8. void DMA1_Channel1_IRQHandler(void)
  9. {
  10. if(dma_interrupt_flag_get(DMA1_FDT1_FLAG) != RESET)
  11. {
  12. dma_flag_clear(DMA1_FDT1_FLAG);
  13. dma_trans_complete_flag = 1;
  14. }
  15. }
步骤
①设置调试器
c386049ae769dec58813d72407f9d184
②启用变量跟踪
714e761752b6ed0df2e968322037e2f6
③进入DUBUG模式,先设置断点(如下图),再全速运行代码;
40ae750493ec5014fc41201662baaef0
右击右下角的运行时间t1,将其复位为0
3b97de24689b823edb6e1d007e1e8363
⑤在中断设置下一个断点,再全速运行
838edb84a925f9d8269abfc548ac55eb
结果
①理论时间
单个通道:(采样+转换)时间= (采样时间+12.5)个ADCCLK周期;
两个通道:T_calculate = (239.5+12.5) ÷ 20M × 2 = 25.2us
②实测时间
5de27478d608d869e89e35e7c413f267
观察右下角t1得ADC转换(两个通道)时间T_test = 25.7us
3.DWT测量法
介绍
添加DWT测量的C文件和H文件,在DEBUG下观察计数差值,利用差值计算得ADC转换时间。
步骤
①将“cpu_sysclk_time_calculate”文件夹(详见附件)移植至工程文件下;
bc91daa59621570f3a70ff4b833fc489
②新建Group(Calculate)并添加现有文件进来;
2dbe91a15fc8109c84393a84cb389ab7
63369953a8c102d8840a09b890a3b0bd
③选择步骤①路径下“cpu_sysclk_time_calculate”的c文件;
bd6a13ce8296a9b5af31d973b7505f55
④添加文件路径;
bc6ec10d9e3a5108d28effd817762776
⑤添加步骤①路径下的“cpu_sysclk_time_calculate”文件夹;
b06d34de6bc5092ea7826a01ebb0072a
代码
main.c
  1. #include "at32f403a_407_wk_config.h"
  2. #include "wk_system.h"
  3. #include "timecalculate.h" /*(DWT测量法)——包含相关头文件*/
  4. uint16_t adc_value[2] = {0}; //用于存放外部信号的adc数组
  5. uint16_t dma_trans_complete_flag = 0; //dma转换完成标志
  6. uint16_t start = 0, stop = 0; /*(DWT测量法)——计数的起始点和终止点*/
  7. int main(void)
  8. {
  9. wk_system_clock_config();
  10. wk_periph_clock_config();
  11. wk_nvic_config();
  12. wk_timebase_init();
  13. wk_dma1_channel1_init();
  14. wk_dma_channel_config(DMA1_CHANNEL1,
  15. (uint32_t)&ADC1->odt,
  16. DMA1_CHANNEL1_MEMORY_BASE_ADDR,
  17. DMA1_CHANNEL1_BUFFER_SIZE);
  18. dma_channel_enable(DMA1_CHANNEL1, TRUE);
  19. wk_adc1_init();
  20. adc_ordinary_software_trigger_enable(ADC1, TRUE);
  21. start = ARM_CM_DWT_CYCCNT; /*(DWT测量法)——记录起始计数值*/
  22. while(dma_trans_complete_flag == 0); //等待DMA传输完成
  23. while(1)
  24. {
  25. }
  26. }
timecalculate.c
  1. #include "timecalculate.h"
  2. #include "at32f403a_407_wk_config.h"

  3. void start_Math(void)
  4. {
  5.   if (ARM_CM_DWT_CTRL != 0) {        // See if DWT is available
  6.    ARM_CM_DEMCR      |= 1 << 24;  // Set bit 24
  7.    ARM_CM_DWT_CYCCNT  = 0;
  8.    ARM_CM_DWT_CTRL   |= 1 << 0;   // Set bit 0
  9.    }
  10. }
timecalculate.h
  1. #ifndef __TIMECALCULATE_H
  2. #define __TIMECALCULATE_H

  3. #define  ARM_CM_DEMCR      (*(uint32_t *)0xE000EDFC)
  4. #define  ARM_CM_DWT_CTRL   (*(uint32_t *)0xE0001000)
  5. #define  ARM_CM_DWT_CYCCNT (*(uint32_t *)0xE0001004)

  6. void start_Math(void);

  7. #endif
at32f403a_407_int.c
  1. #include "at32f403a_407_int.h"
  2. #include "wk_system.h"
  3. #include "timecalculate.h" /*(DWT测量法)——包含相关头文件*/
  4. extern uint16_t dma_trans_complete_flag;
  5. extern uint16_t stop; /*(DWT测量法)——声明外部变量*/
  6. void SysTick_Handler(void)
  7. {
  8. wk_timebase_handler();
  9. }
  10. void DMA1_Channel1_IRQHandler(void)
  11. {
  12. stop = ARM_CM_DWT_CYCCNT; /*(DWT测量法)——记录终止点的计数值*/
  13. if(dma_interrupt_flag_get(DMA1_FDT1_FLAG) != RESET)
  14. {
  15. dma_flag_clear(DMA1_FDT1_FLAG);
  16. dma_trans_complete_flag = 1;
  17. }
  18. }
  19.   
结果
①理论时间
单个通道:(采样+转换)时间= (采样时间+12.5)个ADCCLK周期;
两个通道:T_calculate = (239.5+12.5) ÷ 20M × 2 = 25.2us
②实测时间
0c01148c96eed0dac0ab24f8462eebea
DEBUG模式下,观察起始计数值终止计数值,根据二者的差值(指令数)计算得ADC转换(两个通道)时间T_test = (stop - start) ×指令周期= (18578 - 12436) ÷240M = 25.59us
五、总结


优点
缺点
GPIO翻转法
操作简单,通用性强
精度受限于GPIO切换速度
调试器跟踪法
无其他代码的干预
需特定的硬件支持
DWT测量法
无需外部测量工具
配置过程相对复杂
三种方法都可测量代码片段的运行时间(比如ADC转换时间、定时器的中断频率等),可根据不同场景灵活使用。

由于作者水平有限,文中如有错误之处,恳请读者批评指正。
参考资料:
《RM_AT32F403A_407_CH_V2.06》的19模拟数字转换(ADC)https://www.arterytek.com/file/download/1995
雅特力AT32F423开启FPU跟不开启FPU性能差异(使用DWT测量)https://blog.csdn.net/l18817813618/article/details/140275305





cpu_sysclk_time_calculate.rar

617 Bytes, 下载次数: 10

DWT测量法的相关文件

打赏榜单

21小跑堂 打赏了 50.00 元 2024-10-25
理由:恭喜通过原创审核!期待您更多的原创作品~

评论

使用三种常用方法测量代码运行时间,三种方式均描述的较为详细,也是常用的可靠方法,调试细节介绍清晰,文章完整。  发表于 2024-10-25 17:44
 楼主| zexin 发表于 2024-10-21 10:45 | 显示全部楼层
呐咯密密 发表于 2024-10-22 10:13 | 显示全部楼层
我基本都是用示波器测量GPIO翻转
Chad1989 发表于 2024-10-22 11:52 | 显示全部楼层
为什么不用系统时钟去计算呢
 楼主| zexin 发表于 2024-10-22 13:58 | 显示全部楼层
Chad1989 发表于 2024-10-22 11:52
为什么不用系统时钟去计算呢

其实DWT测量法也是利用系统时钟计算的,当然您有其他更方便的方法也欢迎分享,这边只是在学习过程中做了一些整理
xionghaoyun 发表于 2024-10-23 08:51 | 显示全部楼层
开串口打印
febgxu 发表于 2024-11-7 22:28 | 显示全部楼层
测量单片机代码片段的运行时间通常需要使用一个高精度的计时器或定时器。
elsaflower 发表于 2024-11-8 09:16 | 显示全部楼层
通过设置一个快速循环,并在循环内部进行计数操作,利用循环执行的时间来近似估算代码片段的运行时间。这种方法相对简单,但精度较低,适用于对时间精度要求不高的情况。
xiaoyaodz 发表于 2024-11-8 10:07 | 显示全部楼层
配置定时器:首先,配置一个定时器,使其以一定的频率计数。
记录开始时间:在代码片段执行前,记录定时器的当前计数值。
记录结束时间:在代码片段执行后,再次记录定时器的当前计数值。
计算时间差:通过两次记录的计数值之差,计算出代码片段的运行时间。
alvpeg 发表于 2024-11-8 11:21 | 显示全部楼层
在待测代码段开始前启动单片机内部的定时器,并在代码段结束时停止定时器。通过读取定时器的计数值来计算代码段的运行时间。
backlugin 发表于 2024-11-8 12:43 | 显示全部楼层
可以使用外部工具如逻辑分析仪或示波器来测量代码片段的运行时间。
usysm 发表于 2024-11-8 14:31 | 显示全部楼层
首先计算出循环执行一次的平均时间,然后根据所记录的开始时间、结束时间以及代码片段执行期间循环执行的次数,计算出代码片段的运行时间。例如,如果循环执行一次的平均时间为 t 秒,代码片段执行期间循环执行了 n 次,那么运行时间 =(结束时间 - 开始时间)- n × t 秒。
earlmax 发表于 2024-11-8 16:15 | 显示全部楼层
使用定时器              
caigang13 发表于 2024-11-8 19:00 来自手机 | 显示全部楼层
最简单的方式就是使用定时器
nomomy 发表于 2024-11-8 20:01 | 显示全部楼层
单片机通常内置有定时器,可以用来测量时间间隔。
sdlls 发表于 2024-11-8 20:48 | 显示全部楼层
定时器的精度取决于单片机的时钟频率。
albertaabbot 发表于 2024-11-8 21:22 | 显示全部楼层
SysTick定时器是ARM Cortex-M系列微控制器的一个特性,可以用来生成周期性的中断,也可以用来测量时间间隔
macpherson 发表于 2024-11-8 21:45 | 显示全部楼层
单片机内部通常都包含这样的硬件资源,可以用来精确地测量时间间隔。
beacherblack 发表于 2024-11-8 22:18 | 显示全部楼层
使用结束时间和开始时间计算代码片段的运行时间。
timfordlare 发表于 2024-11-8 23:00 | 显示全部楼层
利用单片机内部的定时器来计时。定时器是一种能够按照设定的时间间隔产生中断或进行计数操作的硬件模块。通过在代码片段开始和结束时分别对定时器进行相关操作,就可以计算出代码片段运行所占用的时间。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

17

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部