求一个C语言的微秒级延时函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了求一个C语言的微秒级延时函数相关的知识,希望对你有一定的参考价值。

需要一个微秒级的延时函数...求一个微秒级的延时函数...

c语言,微秒级延时


void Delay_us (unsigned char time_us)

   unsigned long int  TM_LODAE;

   TR2   = 0;                          // Stop timer

   TF2H  = 0;                          // Clear timer overflow flag

   

   TM_LODAE = 65535-(UINT)(SYSCLK/1000000) * (UINT)(time_us);

   

  // TMR2  = -( (UINT)(SYSCLK/1000000) * (UINT)(time_us) );

   

  TMR2H =  TM_LODAE>>8;

  TMR2L =  TM_LODAE&0x00FF;

   TR2   = 1;                          // Start timer

   while (!TF2H);                      // Wait till timer overflow occurs

   TR2   = 0;                          // Stop timer

 程序分析:

    前面一起住航分析一下该代码,

    unsigned long int  TM_LODAE;  声明一个长整型数据,

    TR2   = 0;    定时器2停止计时

    TF2H  = 0;      清除定时器2中断标志

    TM_LODAE = 65535-(UINT)(SYSCLK/1000000) * (UINT)(time_us);    计算定时器初值。 SYSCLK是系统的晶振频率,SYSCLK/1000000是系统 1uS 执行的指令。 (UINT)(SYSCLK/1000000) * (UINT)(time_us)就是系统 time_us执行的指令数。 65535-(UINT)(SYSCLK/1000000) * (UINT)(time_us)定时器需要 TM_LODAE指令周期才会溢出。

    该单片机的一个指令周期就是一个时钟周期.TMR2H =  TM_LODAE>>8;  TMR2L =  TM_LODAE&0x00FF;置定时器寄存器的初值、

    TR2   = 1;   启动单片机计时  while (!TF2H);  等待定时器2寄存器溢出。TR2   = 0;停止计时,在这段代码注释中已经说明了应该有50nS的误差,这个是函数调用产生的。

参考技术A   _nop_(); //延时1us,fosc = 12MHz 时。

  C语言是一种计算机程序设计语言,属高级语言范畴。它既具有高级语言的特点,又具有汇编语言的特点。它可以作为工作系统设计语言,编写系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序,代码清晰精简,十分灵活。
参考技术B 可以用_nop_( )函数来实现微秒级的延时。
_nop_(); // 直接当成一条语句使用,产生一条NOP指令

NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。

注:使用该函数时,需要将头文件#include<intrins.h>包含进源文件中。
参考技术C //*********** 微秒延时函数 ********************************************
void Delayus(unsigned int US)

unsigned i;
US=US*5/4; //5/4是在8MHz晶振下,通过软件仿真反复实验得到的数值
for( i=0;i<US;i++);

//*********************************************************************

以上函数式根据AVR单片机在8MHZ时钟频率下得出的结果。
如果系统频率不一样,就按比例改变。
参考技术D 一个微秒级的延时函数今天要用到一个微秒级的定时函数,到网上search下,找了几个都不能用,我晕,无奈,还是自己动手比较好,赶紧贴出来。

免得以后要用的时候又不知道那里去找,方便自己也方便大家^_^ 又避免重复发明轮子^_^

/********************************************************************
Created: 2006/09/02
FileName: t.c
Author: Liu Qi

Purpose: 测试微秒级延时
*********************************************************************/

#include <windows.h>
#include <time.h>
#include <stdio.h>

ULONG GetTimeDis(struct tm first, struct tm second) //计算两次时间差

return abs((first.tm_hour * 3600 + first.tm_min * 60 + first.tm_sec)
- (second.tm_hour * 3600 + second.tm_min * 60 + second.tm_sec));


void Delay(ULONG ulMicroSeconds)

LARGE_INTEGER timeStop;
LARGE_INTEGER timeStart;
LARGE_INTEGER Freq;
ULONG ulTimeToWait;

if (!QueryPerformanceFrequency( &Freq ))
return;

ulTimeToWait = Freq.QuadPart * ulMicroSeconds / 1000 / 1000;

QueryPerformanceCounter ( &timeStart );

timeStop = timeStart;

while( timeStop.QuadPart - timeStart.QuadPart < ulTimeToWait )

QueryPerformanceCounter( &timeStop );



int main(void)

struct tm timeStart, timeEnd;

_getsystime(&timeStart);

Delay(1000 * 1000 * 3); //3秒

_getsystime(&timeEnd);
printf("用时:%d秒\n", GetTimeDis(timeStart, timeEnd));

return 0;

windows下基于(QPC)实现的微秒级延时

1.为什么会写windows下微秒级延时

在上一篇 实现memcpy()函数及过程总结 中测试memcpy的效率中,测试时间的拷贝效率在微秒级别,需要使用微秒级时间间隔计数。

windows下提供QueryPerformanceCounter(查询高性能计数器),QPC是基于硬件计数器,获取高分辨率时间戳。

参考:Acquiring high-resolution time stamps

应用形式:

 1 LARGE_INTEGER start, end;
 2 LARGE_INTEGER Frequency;
 3 QueryPerformanceFrequency(&Frequency);
 4  
 5 QueryPerformanceCounter(&start);
 6  
 7 //运行时间体
 8   
 9 QueryPerformanceCounter(&end);
10   
11 //转换时间(us) double(end.QuadPart - start.QuadPart) * 1000000 / Frequency.QuadPart

上面通过API查询高性能计数器,开始tick,结束tick,转换对应时间间隔。

2.基于QPC实现us延时

 1 //timer.c
 2
 3 #include "timer.h"
 4 
 5 static LARGE_INTEGER start;
 6 static LARGE_INTEGER tick;
 7 static LONGLONG SecondTick;
 8 
 9 double GetMicrosecondTimeInterval(long long StartTick, long long EndTick, long long Frequency)
10 {
11     return (double)(EndTick - StartTick) * 1000000 / Frequency;
12 }
13 
14 /*
15 *    function:us延时初始化
16 *
17 *    parameter:无
18 *
19 *    return value:无
20 *                
21 */
22 void MicrosecondDelayInit(void)
23 {
24     LARGE_INTEGER frequence;
25     QueryPerformanceFrequency(&frequence);
26     SecondTick = frequence.QuadPart;    
27 }
28 
29 /*
30 *    function:MicrosecondDelay();
31 *             实现微秒级延时
32 *    
33 *    parameter:
34 *                n:延时的us数
35 *    
36 *    return value:
37 *                无
38 */
39 
40 void MicrosecondDelay(int n)
41 {
42     QueryPerformanceCounter(&start);
43     double endtick = SecondTick * n/1000000.0 + start.QuadPart;
44     for(;;)
45     {
46         QueryPerformanceCounter(&tick);
47         if (tick.QuadPart >= endtick)
48             break;
49     }
50 }
 1 //timer.h
 2 
 3 #pragma once        //编译器保证头文件只编译一次
 4 
 5 #include <windows.h>
 6 #include <stdio.h>
 7 
 8 #ifdef __cplusplus  
 9 extern "C" {
10 #endif 
11     double GetMicrosecondTimeInterval(long long StartTick, long long EndTick, long long Frequency);
12     void MicrosecondDelayInit(void);
13     void MicrosecondDelay(int n);
14 #ifdef __cplusplus  
15 }
16 #endif 

3.us延时测试

 1 #include <stdio.h>
 2 #include <Windows.h>
 3 #include"timer.h"
 4 
 5 int main(void)
 6 {
 7     LARGE_INTEGER Frequency;
 8     LARGE_INTEGER StartingTime, EndingTime;
 9 
10     QueryPerformanceFrequency(&Frequency);
11     MicrosecondDelayInit();
12 
13     QueryPerformanceCounter(&StartingTime);
14     MicrosecondDelay(10);
15     QueryPerformanceCounter(&EndingTime);
16 
17     printf("延时:%lf\\n", GetMicrosecondTimeInterval(StartingTime.QuadPart, EndingTime.QuadPart, Frequency.QuadPart));
18     system("pause");
19     return 0;
20 }

测试情况:

1.延时情况能达到us级,多次测试运行,个别情况延时会有出入(出现情况较少)。

  分析原因:代码级影响较小,主要运行是在windows下,windows并不是实时操作系统,毕竟windows操作系统时间分辨率只能达到ms级。

                        延时可以被打断。cpu的频率会在变化,代码执行效率也会有影响。

2.这种延时效果明显好于Sleep的ms级延时。

4.windows下us延时,控制误差

1.硬件上实现us延时(这种情况对于不涉及底层硬件操作的并不现实)

2.既然windows提供给我们QPC(查询高性能计数器 <1us),配合着使用我们自己实现的us级延时。

我们延时前获取StartTick,延时结束后再获取EndTick,转换对应对应时间间隔。QueryPerformanceCounter函数2次消耗时间几乎可以忽略。通过打印我们可以看到us延时数。

大多数运行情况,延时函数效果1us内误差。大于1us延时我们可以剔除,保证1us时间误差。(这种做法是我们需要us级延时做测试时采用,保证后面数据结果在特定延时效果下)

5.总结

us延时常用于测试一些性能时使用。windows并未通过us级的延时函数。QPC是基于查询硬件计数器获取时间间隔,能达到us级别。

 

        

以上是关于求一个C语言的微秒级延时函数的主要内容,如果未能解决你的问题,请参考以下文章

STM32 延时函数,复位函数,汇编实现,精准微秒延时

求C语言大师级别高手,本人外行,需要逐句弄懂其意思,求大师逐句翻译每行 翻译啊~~~~~~万分感谢 ~~~~

这两个延时函数该怎么理解,又怎么使用,请大神指教?

c语言休眠函数怎么写

STM32 CubeMX如何生成微秒(us)级延时

gcc延时绑定参数