自己做彩票网站,江阴公司网站建设,wordpress 七牛云图床,福州百度关键词排名文章整理自网络序对于某些对时间精度要求较高的程序#xff0c;用 c 写延时显得有些力不从心#xff0c;故需用到汇编程序。本人通过测试#xff0c;总结了 51 的精确延时函数(在 c 语言中嵌入汇编)分享给大家。至于如何在 c 中嵌入汇编大家可以去网上查查#xff0c;这方面… 文章整理自网络序对于某些对时间精度要求较高的程序用 c 写延时显得有些力不从心故需用到汇编程序。本人通过测试总结了 51 的精确延时函数(在 c 语言中嵌入汇编)分享给大家。至于如何在 c 中嵌入汇编大家可以去网上查查这方面的资料很多且很简单。以 12MHz 晶振为例12MHz晶振的机器周期为 1us所以执行一条单周期指令所用时间就是 1us如 NOP 指令。下面具体阐述一下。若要延时 1us则可以调用_nop_();函数此函数是一个 c 函数其相当于一个 NOP 指令使用时必须包含头文件 intrins.h例如
#include intrins.h
#include reg52.h
void main(void)
{P1 0x0;_nop_(); //延时 1usP1 0xff;
}
延时 5us,则可以写一个delay_5us()函数delay_5us()
{#pragma asmnop#pragma endasm
}
这就是一个延时 5us 的函数只需要在需要延时 5us 时调用此函数即可。或许有人会问只有一个 NOP 指令怎么是延时 5us 呢答案是在调用此函数时需要一个调用指令此指令消耗 2个周期(即 2us)函数执行完 毕时要返回主调函数需要一个返回指令此指令消耗 2 个周期(2us)。调用和返回消耗了2us 2us 4us。然后再加上一个NOP指令消耗 1us不就是5us吗?延时 10us。我们编写一个 delay_10us()函数delay_10us(){
#pragma asm
nop
nop
nop
nop
nop
nop
#pragma endasm
}
这就是延时 10us 的函数。同延时 5us 函数一样调用和返回消耗 4us加上函数中的6 个 NOP 指令6us正好是10us。此时有人不禁要问那么任意微秒时函数应该怎么写呢?看我慢慢道来首先延时任意微秒我暂时没有想到但是我可以延时任意偶数微秒或延时任意奇数微秒, 也就是说需要两个函数一个函数专门实现任意偶数的微秒级延时另一个函数专门实现 任意奇数的微秒级延时。只要有了这两个函数在不就可以延时任意的微秒了吗首先我们来实现任意偶数的微秒级延时void delay_even_us(unsigned char even){ //任意偶数的微秒级延时
#pragma asm
1 mov a, r7 //为什么要用到 r7 呢因为 r7 里面装的是函数的参数
// ^_^ 这句消耗 1 个周期
2 subb a, #10H //这句看完程序我再解释 这句消耗 1 个周期
3 mov b, #02H //这句看完程序我再解释 这句消耗 2 个周期
4 div ab // 这句意思是 a/b 商放在 a 里余数放在 b 里 稍
//后解释 这句消耗 4 个周期
5 mov r0, a //这句消耗 1 个周期
6 nop //这句消耗 1 个周期
7 loop:
8 djnz r0, loop //不等于 0 跳转指令也就是说 r0 中的值若不为 0 的话
//就跳转到 loop 处 这句消耗 2 个周期
#pragma endasm
}
下面我们来分析一下为何这样写为了方便分析我给句子编上了序号。我们以延时 100us为例(delay_even_us(100))。首先减去调用和返回的 4 个周期(4us)。再减去参数传递所消耗的2 个周期。因为 c 函数参数传递到汇编是需要消耗周期的。一共消耗了 6 个周期。也就是消 耗了 6us还剩下 100us-6us94us。然后再看我再程序上面注释的各语句消耗时间从 1 句到 5 句一共消耗了 10 个周期(不信你数数^_^)。还剩下 94us-10us84us。现在就看第 8 句了这句应该消耗 84 个周期才能达到我们延时 100us。而这句每执行一次消耗 2 个周期也就是说 r0 的值应该为 84/242。那么怎样达到 r042 的呢我们从第 1 句开始分析第 1 句中r7 为 c 传递过来的参数此例子中为 100.执行完此句后 a 的值为 100第 2 句中将 aa-16 100-1684。此句结束后 a 的值为 84第 3 句中给 b 赋值为 2第 4 句中用 a 来除以 b。结果商存入 a 中余数存入 b 中此句结束后 a 的值为 aa/b 84/2 42第 5 句将 a 值赋给 r0此句结束后 r0 的值为 42。于是乎 r0 的值为 42 这个目的达到了。结合前面的分析此程序是不是延时了 100us 呢答案当然是 “是”了这个函数可以实现任意偶数微秒(18)的延时的不信的话可以带一个值进去算的。至于为什么值必须18us用不着我解释了吧。任意奇数的微秒级延时void delay_odd_us(unsigned char odd){
#pragma asm
1 mov a, r7
2 subb a, #0fH
3 mov b, #02H
4 div ab
5 mov r0, a
6 loop1:
7 djnz r0, loop1
#pragma endasm
}
此即为任意奇数微秒的延时和偶数延时一样的道理不解释了。^_^此函数的参数必须大于等于 17请思考为什么^_^#推荐阅读 专辑|Linux文章汇总 专辑|程序人生 专辑|C语言嵌入式Linux微信扫描二维码关注我的公众号