c语⾔程序实现⼀个延时功能,⽤C语⾔实现精确的延时
⽤C语⾔实现精确的延时
怎么⽤C语⾔做单⽚机的精确延时
时器甚⾄已经全部⽤于其他⽅⾯的定时处理,此时就只能使⽤软件定时了[1]。
1 C语⾔程序延时 在单⽚机应⽤中,经常会遇到需要短时间延时的情况,⼀般都是⼏⼗到⼏百μs,并且需要很⾼的精度(⽐如⽤单⽚机驱动DS18B20时,误差容许的范围在⼗⼏μs以内,不然很容易出错);⽽某些情况下延时时间较长,⽤计时器往往有点⼩题⼤做。另外在特殊情况下,计
Keil C51的编程语⾔常⽤的有2种: ⼀种是汇编语⾔;另⼀种是C 语⾔。⽤汇编语⾔写单⽚机程序时,精确时间延时是相对容易解决的。⽐如,⽤的是晶振频率为12 MHz的AT89C51,打算延时20 μs,51单⽚机的指令周期是晶振频率的1/12,即⼀个机器周期为1
μs;“MOV R0,#X”需要2个机器周期,DJNZ也需要2个机器周期,单循环延时时间t=2X+3(X为装⼊寄存器R0的时间常数)[2]。这样,存⼊R0⾥的数初始化为8即可,其精度可以达到1 μs。⽤这种⽅法,可以⾮常⽅便地实现512 μs以下时间的延时。如果需要更长时间,可以使⽤两层或更多层的嵌套,当然其精度误差会随着嵌套层的增加⽽成倍增加。
虽然汇编语⾔的机器代码⽣成效率很⾼,但可读性却并不强,复杂⼀点的程序就更难读懂;⽽C语⾔在⼤多数情况下,其机器代码⽣成效率和汇编语⾔相当,但可读性和可移植性却远远超过汇编语⾔,且C 语⾔还可以嵌⼊汇编程序来解决⾼时效性的代码编写问题。就开发周期⽽⾔,中⼤型软件的编写使⽤C 语⾔的开发周期通常要⽐汇编语⾔短很多,因此研究C语⾔程序的精确延时性能具有重要的意义。
C程序中可使⽤不同类型的变量来进⾏延时设计。经实验测试,使⽤unsigned char类型具有⽐unsigned int更优化的代码,在使⽤时应该使⽤unsigned char作为延时变量。 2 单层循环延时精度分析
下⾯是进⾏μs级延时的while程序代码。
延时函数:
void delay1(unsigned char i) {
while(i );}
主函数:
void main() {
一个完整的c语言程序while(1) {
delay1(i);
}
}
使⽤Keil C51的反汇编功能,延时函数的汇编代码如下:
C:0x00E6AE07MOVR6,0x07
C:0x00E81FDECR7
C:0x00E9EEMOVA,R6
C:0x00EA70FAJNZC:00E6
C:0x00EC22RET
图1 断点设置位置图
通过对i赋值为10,在主程序中图1所⽰的位置设置断点。经过测试,第1次执⾏到断点处的时间为457 μs,再次执⾏到该处的时间为531μs,第3次执⾏到断点处的时间为605 μs,10次while循环的时间为74 μs,整个测试结果如图2所⽰。
图2 使⽤i--⽅式测试仿真结果图
通过对汇编代码分析,时间延迟t=7X+4(其中X为i的取值)。测试表明,for循环⽅式虽然⽣成的代码与⽤while语句不⼤⼀样,但是这两种⽅法的效率⼏乎相同。C语⾔中的⾃减⽅式有两种,前⾯都使⽤的是i--的⽅式,能不能使⽤--i⽅式来获得不同的效果呢?将前⾯的主函数保持不变,delay1函数修改为下⾯的⽅式:
void delay1(unsigned char i) {
while(--i);}
同样进⾏反汇编,得到如下结果:
C:0x00E3DFFEDJNZR7,
C:00E3C:0x00E522RET
⽐较发现,--i的汇编代码效率明显⾼于i--⽅式。由于只有1条语句DJNZ,执⾏只需要2个时钟周期, 1个时钟周期按1 μs计算,其延时精度为2 μs;另外,RET需要2个时钟周期,能够达到汇编语⾔代码的效率。按前⾯的测试条件进⾏测试,第1次执⾏到断点处的时间为437μs,再次执⾏到该处的时间为465 μs,第3次执⾏到断点处的时间为493 μs,10次while

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。