完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
思路:采用TIM3,设置为向上计数模式,每次计数溢出(因为以72Mhz计数,stm32全为16位定时器,0.9ms就会溢出了),则变量加一,如此来测量。核心代码如下,测试过了,非常准确。但是此方法的误差在于,由于stm32没有32位定时器,所以0.9ms就会进入中断一次进行cntPeriod++,这个也会消耗时间的,实际上就是一种误差了,但是一般而言,误差效果可以忽略不计。
extern u32 cntPeriod; void TIM3_Int_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能 DBGMCU_Config(DBGMCU_TIM3_STOP,ENABLE); // 使得调试模式下,定时器也跟着暂停 //定时器TIM3初始化 TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值 TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值 TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM向上计数模式 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位 //这条语句之后,定时器3的CNT计数值就为0了,对的 TIM_ClearFlag(TIM3,TIM_FLAG_Update); //加入这么一句,就不会事先进入一次中断了 TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断 // 注意:第二次之后,此条语句执行完后,就马上进入了中断(因为第一次NVIC_Init已经配置完了), // 所以后面统计真正的中断次数得减去1 //中断优先级NVIC设置 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能 NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器 // 注意:第一次配置时候,此条语句执行完后,就马上进入了中断,原因是,上面TIM_ITConfig配置了 TIM_Cmd(TIM3, ENABLE); //使能TIMx } void TIM3_Int_Close() { NVIC_InitTypeDef NVIC_InitStructure; //中断优先级NVIC设置 TIM_Cmd(TIM3, DISABLE); //停止TIM3 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级0级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级3级 NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; //IRQ通道被关闭 NVIC_Init(&NVIC_InitStructure); //初始化NVIC寄存器 } //定时器3中断服务程序 void TIM3_IRQHandler(void) //TIM3中断 { if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查TIM3更新中断发生与否 { TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除TIMx更新中断标志 ++cntPeriod; } } void MeasureTimeStart() { cntPeriod = 0; TIM3_Int_Init(64799,0);//1分频,即72Mhz的计数频率,计数到64800为0.9ms ,64800/72=900us } float MeasureTimeEnd() //别用double类型返回,用float,因为对keil对double支持不友好,尽量别用,详情可以参见我这个文章https://blog.csdn.net/kangkanglhb88008/article/details/107746298 { float runTime; u32 cntTmp; u32 cntTim3 = TIM3->CNT;//为了尽可能的减小偏移误差,这里尽快拿到这个CNT值,实测函数跳转特别耗时 TIM3_Int_Close(); printf("rncntTim3:%d rn",cntTim3); cntTmp = cntPeriod*64800 + cntTim3; runTime = (float)cntTmp/72.0/1000.0; //返回多少ms return runTime; } int main(void) { float val; delay_init(); //延时函数初始化 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 uart_init(115200); //串口初始化为115200 LED_Init(); //LED端口初始化 MeasureTimeStart(); delay_1ms_my(1000); val = MeasureTimeEnd(); printf("%f",val); // test(); while(1); } 注:delay_1ms_my()是我自己写的延时函数,测量后发现非常准确。 void delay_1us_my(void) //64个nop指令,加上跳转等执行时间,差不多就是72个时钟周期了,stm32f1主频72Mhz,即1us { __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); __nop(); } void delay_1ms_my(u32 nms) { u32 nus=nms*1000; while(--nus) { delay_1us_my(); } } 效果如下所示: 此外,测了一下中间不加任何指令的运行时间,如下图所示: 即两条空语句之间会用掉49个时钟周期,约0.681us(固定的多余消耗,提高测量精度时候可以直接减去这个值),这是因为其实中间有函数跳转等操作,可以看出也还是挺快的了,而且可以看出这个时间测量方法精度非常的高,达到1/72us 其中发现一个很奇怪的现象, MeasureTimeStart(); // 假如是测空语句,这个放前面和放这里测出来的会有细微的差别,这个没关系的了,知道就好 delay_1ms_my(1000); // _VZ(Smix,numOfStrongTask+numOfHardTask); timeRunVzop = MeasureTimeEnd(); printf("%f",timeRunVzop); while(1) { // TaskDataClear(); //这句代码有效的话,上面测量出来的时间会偏小3ms,想了很久,没想明白为什么,按道理说这后面的代码不会影响到上面的时间测量,只有一种解释,那就是编译后代码所占空间变大?导致前面的函数地址跳转变多了?我也不知道具体原因,反之就当真粗略使用吧 } |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1771 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1619 浏览 1 评论
1070 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
724 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1673 浏览 2 评论
1936浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
729浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
569浏览 3评论
594浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
552浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 20:58 , Processed in 0.787124 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号