C语言精确延时

C语言精确延时,第1张

void delay500ms(void)
{ unsigned char i,j,k;
for(i=15;i>0;i--) for(j=202;j>0;
j--) for(k=81;k>0;k--);
}
产生的汇编:
C:0x0800 7F0F MOV R7,#0x0F 7ECA MOV R6,#0xCA
7D51 MOV R5,#0x51
DDFE DJNZ R5,C:0806
DEFA DJNZ R6,C:0804
DFF6 DJNZ R7,C:0802 C:0x080C 22 RET
程序共有三层循环 一层循环n:R52 = 812 = 162us DJNZ 2us 二层循环m:R6(n+3) = 202165 = 33330us DJNZ 2us + R5赋值 1us = 3us 三层循环: R7(m+3) = 1533333 = 499995us DJNZ 2us + R6赋值 1us = 3us 循环外: 5us 子程序调用 2us + 子程序返回 2us + R7赋值 1us = 5us 延时总时间 = 三层循环 + 循环外 = 499995+5 = 500000us =500ms 计算公式:延时时间= [(2R5+3)R6+3]R7+5
二 200ms延时子程序 程序:
void delay200ms(void)
{ unsigned char i,j,k;
for(i=5;i>0;i--) for(j=132;j>0;j--)
for(k=150;k>0;k--);
}
产生的汇编
C:0x0800 7F05 MOV R7,#0x05
C:0x0802 7E84 MOV R6,#0x84
C:0x0804 7D96 MOV R5,#0x96 DDFE DJNZ R5,C:0806
DEFA DJNZ R6,C:0804
DFF6 DJNZ R7,C:0802
22 RET
三 10ms延时子程序 程序:
void delay10ms(void)
{ unsigned char i,j,k;
for(i=5;i>0;i--)
for(j=4;j>0;j--)
for(k=248;k>0;k--); }
产生的汇编 C:0x0800 7F05 MOV R7,#0x05 7E04 MOV R6,#0x04
7DF8 MOV R5,#0xF8
C:0x0806 DDFE DJNZ R5,C:0806 DEFA DJNZ R6,C:0804
DFF6 DJNZ R7,C:0802
C:0x080C 22 RET
四 1s延时子程序 程序:
void delay1s(void)
{ unsigned char h,i,j,k;
for(h=5;h>0;h--)
for(i=4;i>0;i--)
for(j=116;j>0;j--)
for(k=214;k>0;k--); }
产生的汇编
C:0x0800 7F05 MOV R7,#0x05 7E04 MOV R6,#0x04
7D74 MOV R5,#0x74
7CD6 MOV R4,#0xD6
DCFE DJNZ R4,C:0808
DDFA DJNZ R5,C:0806
DEF6 DJNZ R6,C:0804
DFF2 DJNZ R7,C:0802
22 RET 在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响

要自己构造,
步骤1,检查单片机的说明书,知道执行一条指令要多少时钟周期,
2, 12M的时钟频率就是一个始终周期833ns,
3,你要1毫秒,就是要延迟12000个时钟周期,
做一个For循环,在里面做4000次加法运算就可以了(假设你的单片机一个指令用一个时钟)

那样子你的调用系统的API来获得调用此函数之前的系统时间,还有调用此函数返回之后的系统时间进行比较。
#include <windowsh>
#include <stdioh>
voidmain()
{
SYSTEMTIME sys;
GetLocalTime( &sys );
int start=syswMilliseconds;//获取开始时的毫秒数
//下面调用你的函数
delay(uint型变量);//这里面的参数你必须自己看着办
GetLocalTime( &sys );
int end=syswMilliseconds;//获取调用delay函数之后的秒数
printf("调用delay函数消耗了%d毫秒!\n",end-start);
printf("注意:此程序只能处理1秒以内的延迟毫秒数!");
}
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=125;y>0;y--);
}

假设一个延时函数如下:
void delay()
{
uint i;
for(i=0;i<20000;i++);
}
我们怎么来算呢,先将20000转成16进制,得到4E20,然后将高字节4E乘以6得到468D,再将468+2=470,然后将470D20HEX(即32D)=15040;所心这个延时函数总共要执行15040个周期,假设所用的晶振为12MHZ,则该段函数总延时:1504ms。
有了这个公式我们如果想要设定指定的延时长度就可以用它的己知公式确定。即:总时间=[(6i值的高8位)+2]i的低8位。
例如:设要延时125ms。
我们将低字节先赋值200D(即:C8),然后再算高低节的定值,由式中可知125ms=200((i值的高字节6)+2),又可推算出(高低节6)+2的总延迟时间应等于625us,将625/6=1041666,取整数得到104,将104转成16进制得到68H,再将高字节和低字节组合起来即得到了定值,即:68C8HEX,代入函数即如下:
void delay()
{
uint i;
for(i=0;i<0x68C8;i++);
}
如果写直进行就要将68C8转成10进制,即:26824,代入后得到:
void delay()
{
uint i;
for(i=0;i<0x26824;i++);
在c语言中嵌入一段汇编的延时程序呀,你自己看看书,很简单的
用在单片机里的可以C和汇编混合使用,因为用汇编编写延时要准确些,所以你不妨写一个汇编程序,然后再调用它好了,要用C来编精确的延时确实是比较难的哦呵呵
谁说C语言不能精确延时,用51单片机的定时/计数器一或者用定时/计数器2的工作方式2,自动再装入8位计数器,就可以精确延时,别说1MS了就是100um也能精确做到。
其实很简单,采用定时器,将需要定时时间算好后写入单片机中断程序中即可,这种方法可以实现精确定时,最终的误差仅由晶振来确定了。
不错,用定时器最准确。但是定时器数量有限,有时候不见得能够用。比如温度检测(尤其是变化比较大、快的),一个定时器就得一直不停检测。这个时候如果另外一个定时器有正好分配的其他任务,就只有用其他方法延时了。
空循环就行了
如while(i--);根据i的不同决定了延时长短
不过C的延时不是非常准确,你得根据反汇编,看汇编语句的数量和指令周期来计算时间
也可以是
void mDelay(unsigned int Delay) //Delay = 1000 时间为1S
{
unsigned int i;
for(;Delay>0;Delay--)
{
for(i=0;i<124;i++)
{;}
}
}


欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/yw/13210228.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-06-21
下一篇 2023-06-21

发表评论

登录后才能评论

评论列表(0条)

保存