芯片j9九游会网


首页 -- 单片机j9九游会-- ICj9九游会-- 芯片j9九游会-- 新闻技能 --关于j9九游会
 

51单片机延时步伐的设计办法

使用单片机的时分,常常会遇到必要短工夫延时的状况。必要的延时工夫很短,一样平常都是几十到几百奇妙(us)。偶然候还必要很高的精度,好比用单片机驱动 DS18B20的时分,偏差允许的范畴在十几us以内,否则很容易堕落。这种状况下,用计时器每每有点小题大做。而在极度的状况下,计时器乃至曾经所有派上了另外用处。这时就必要j9九游会另想另外措施了。
曩昔用汇编言语写单片机步伐的时分,这个题目照旧绝对容易办理的。好比用的是12MHz晶振的51,计划延时20us,只需用上面的代码,就可以满意一样平常的必要:
mov r0, #09h
loop: djnz r0, loop
51 单片机的指令周期是晶振频率的1/12,也便是1us一个周期。mov r0, #09h必要2个极端周期,djnz也必要2个极端周期。那么存在r0里的数便是(20-2)/2。用这种办法,可以十分利便的完成256us以下工夫的延时。假如必要更永劫间,可以利用两层嵌套。并且精度可以到达2us,一样平常来说,这曾经充足了。
如今,使用更普遍的毫无疑问是Keil的 C编译器。绝对汇编来说,C虽然有许多好处,好比步伐易维护,便于了解,合适大的项目。但缺陷(我以为这是C的独一一个缺陷了)便是及时性没有包管,无法展望代码实行的指令周期。因此在及时性要求高的场所,还必要汇编和C的团结使用。但是不是如许一个延时步伐,也必要用汇编来完成呢?为了找到这个回答,我做了一个实行。
用C言语完成延时步伐,起首想到的便是C常用的循环语句。上面这段代码是我常常在网上看到的:
void delay2(unsigned char i)
{
for(; i != 0; i--);
}
究竟这段代码能到达多高的精度呢?为了间接权衡这段代码的结果,我把 Keil C 依据这段代码发生的汇编代码找了出来:
; FUNCTION _delay2 (BEGIN)
; SOURCE LINE # 18
;---- Variable i assigned to Register R7 ----
; SOURCE LINE # 19
; SOURCE LINE # 20
0000 ?C0007:
0000 EF MOV A,R7
0001 6003 JZ ?C0010
0003 1F DEC R7
0004 80FA SJMP ?C0007
; SOURCE LINE # 21
0006 ?C0010:
0006 22 RET
; FUNCTION _delay2 (END)
真是不看不晓得~~~一看才晓得这个延时步伐是何等的禁绝点~~~光看次要的那四条语句,就必要6个呆板周期。也便是说,它的精度顶多也便是6us罢了,这还没算上一条 lcall 和一条 ret。假如j9九游会把挪用函数时赋的i值根延时长度列一个表的话,便是:
i delay time/us
0 6
1 12
2 18
...
由于函数的挪用必要2个时钟周期的lcall,以是delay time比从函数代码的实行工夫多2。特地提一下,有的冤家写的是如许的代码:
void delay2(unsigned char i)
{
unsigned char a;
for(a = i; a != 0; a--);
}
大概有人以为这会天生更长的汇编代码来,但现实证明:
; FUNCTION _delay2 (BEGIN)
; SOURCE LINE # 18
;---- Variable i assigned to Register R7 ----
; SOURCE LINE # 19
; SOURCE LINE # 21
;---- Variable a assigned to Register R7 ----
0000 ?C0007:
0000 EF MOV A,R7
0001 6003 JZ ?C0010
0003 1F DEC R7
0004 80FA SJMP ?C0007
; SOURCE LINE # 22
0006 ?C0010:
0006 22 RET
; FUNCTION _delay2 (END)
其天生的代码是一样的。不外这确实不是什么好的习气。由于这里真实没有须要再引入多余的变量。j9九游会持续讨论正题。有的冤家为了妥当更长的延时,乃至用了如许的代码:
void delay2(unsigned long i)
{
for(; i != 0; i--);
}
这段代码发生的汇编代码是什么样子的?实在不必想也晓得它是怎样可怕的$#^%&%$......让j9九游会看一看:
; FUNCTION _delay2 (BEGIN)
; SOURCE LINE # 18
0000 8F00 R MOV i+03H,R7
0002 8E00 R MOV i+02H,R6
0004 8D00 R MOV i+01H,R5
0006 8C00 R MOV i,R4
; SOURCE LINE # 19
; SOURCE LINE # 20
0008 ?C0007:
0008 E4 CLR A
0009 FF MOV R7,A
000A FE MOV R6,A
000B FD MOV R5,A
000C FC MOV R4,A
000D AB00 R MOV R3,i+03H
000F AA00 R MOV R2,i+02H
0011 A900 R MOV R1,i+01H
0013 A800 R MOV R0,i
0015 C3 CLR C
###E LCALL ?C?ULCMP
0019 601A JZ ?C0010
001B E500 R MOV A,i+03H
001D 24FF ADD A,#0FFH
001F F500 R MOV i+03H,A
0021 E500 R MOV A,i+02H
0023 34FF ADDC A,#0FFH
0025 F500 R MOV i+02H,A
0027 E500 R MOV A,i+01H
0029 34FF ADDC A,#0FFH
002B F500 R MOV i+01H,A
002D E500 R MOV A,i
002F 34FF ADDC A,#0FFH
0031 F500 R MOV i,A
0033 80D3 SJMP ?C0007
; SOURCE LINE # 21
0035 ?C0010:
0035 22 RET
; FUNCTION _delay2 (END)
呵呵,这却是确实可以耽误很永劫间~~~但毫无精度可言了。
那么,用C究竟能不克不及完成准确的延时呢?我把代码略微改了一下:
void delay1(unsigned char i)
{
while(i--);
}
由于依据履历,越简便的C代码每每也能得出越简便的呆板代码。那如许后果怎样呢?把它天生的汇编代码拿出来看一看就晓得了。满怀盼望的我按下了“Build target”键,后果吹是宏大的:
; FUNCTION _delay1 (BEGIN)
; SOURCE LINE # 13
;---- Variable i assigned to Register R7 ----
; SOURCE LINE # 14
0000 ?C0004:
; SOURCE LINE # 15
0000 AE07 MOV R6,AR7
0002 1F DEC R7
0003 EE MOV A,R6
0004 70FA JNZ ?C0004
; SOURCE LINE # 16
0006 ?C0006:
0006 22 RET
; FUNCTION _delay1 (END)
虽说天生的代码跟用for语句是不大一样,不外我可以毫无疑问的说,这两种办法的服从是一样的。好像到此为止了,由于我真实想不出泉源步伐另有什么简化的余地。看来我就要得出来这个结论了:“假如必要us级的延时精度,必要时用汇编言语。”但真的是如许吗?我照旧不甘愿。由于我不信赖著名[zhe míng]的 Keil C 编译器竟然连 djnz 都不会用???由于实践上步伐体里只必要一句 loop: djnz r7, loop。近乎绝望之际(每每人在这种状况下确可以发作出来,哦呵呵呵~~~),我顺手改了一下:
void delay1(unsigned char i)
{
while(--i);
}
心猿意马[xīn yuán yì mǎ]的编译,看源码:
; FUNCTION _delay1 (BEGIN)
; SOURCE LINE # 13
;---- Variable i assigned to Register R7 ----
; SOURCE LINE # 14
0000 ?C0004:
; SOURCE LINE # 15
0000 DFFE DJNZ R7,?C0004
; SOURCE LINE # 16
0002 ?C0006:
0002 22 RET
; FUNCTION _delay1 (END)
天~~~古迹呈现了......我想这个步伐应该曾经可以满意一样平常状况下的必要了。假如列个表格的话:
i delay time/us
1 5
2 7
3 9
...
盘算延时工夫时,曾经算上了挪用函数的lcall语句所花的2个时钟周期的工夫。

前往顶部


2013-2015 芯片j9九游会网 All Rights Reserved.
若有任何题目和发起请>###@qq.com

深圳市星光芯电子有限公司 版权一切

地点:深圳市龙岗区南湾街道平吉小道1号建昇大厦B栋1618(李朗软件园劈面)###
###QQ:498187676 联系:周工


站点舆图