找回密码
 注册
关于网站域名变更的通知
查看: 65|回复: 0
打印 上一主题 下一主题

单片机C语言延时需注意的问题

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2023-1-9 17:35 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
标准的C语言中没有空语句。但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果。这在汇编语言中很容易实现,写几个nop就行了。' P" e3 @, }: k/ K  ^5 l; X7 z
% d" d% f' W) B4 D  v6 H# x7 m4 }0 X) g0 d
. ~& t5 J; a# q0 j' Z4 \! a4 w- E0 Y
! R( t6 _- e$ ]3 h在keil C51中,直接调用库函数:2 @% N1 k: h' q8 Z
#include // 声明了void _nop_(void);
' P/ k' z6 A; |5 O/ `_nop_(); // 产生一条NOP指令; T3 W8 a& u6 B, a$ v+ M* a4 n+ t, Q0 S: D% c

& h7 }/ U8 Q8 D7 }' O. X. u+ m9 W0 z* p: ?1 x
7 f& T+ h+ R6 N) D作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。
/ B2 c; `# `$ ?: U0 |' E' B2 G( k. t7 D7 }0 L2 l  _3 Z, M( W( E

! Z4 B9 o4 V4 }0 }0 Q+ n在选择C51中循环语句时,要注意以下几个问题:4 ]) x2 Y9 X" t7 c! o4 Y
+ U: K0 v9 Y# \; `6 e8 ]' ?1 b! N7 m' Y

; Z1 @" e+ y' y3 E4 i  z第一、定义的C51中循环变量,尽量采用无符号字符型变量。0 n5 d+ `: c, ^2 i6 K7 Z& e9 l
/ t0 {4 Y; \) l( h9 t( _
" _; ]( |; v% t$ t- Q9 w8 y' ?3 X" }* p, Y7 \9 V0 |% Y$ Q; Z4 t& Q; Q% k: V$ `  f, i$ ?! a7 `# @; y
第二、在FOR循环语句中,尽量采用变量减减来做循环。8 k5 ]9 c1 L4 D
- F. ]2 j+ G$ V+ J

; h8 @2 o' \2 P) S) m第三、在do…while,while语句中,循环体内变量也采用减减方法。
( s+ F0 t3 z4 m: s7 Y' f6 Q% q- T( g
. `' @% o. m) q6 x7 e1 m" N
+ V7 Q! z6 s* n( j, w. \这因为在C51编译器中,对不同的循环方法,采用不同的指令来完成的。0 [( ]" ^3 p8 _1 A2 M
* j+ e9 J+ G9 V7 m5 o0 u* y+ K' `. A/ h% V( Z1 {' l; J" m3 d. ]: f; {
' }6 p0 a+ D% Y& n" D" _& V/ ]& M$ y4 X
下面举例说明:3 O- l5 k' a& _2 o# `
unsigned char i;4 A0 d: M* U0 B. F
for(i=0;i<255;i++);7 B! s4 F9 i7 a3 d- A
unsigned char i;) c1 c9 Z7 B+ w4 D5 f2 k2 H  z4 [4 u+ I* k/ s5 {% o- N" o  \. W2 {
for(i=255;i>0;i--);6 z/ q6 {* ^% y

3 N& z6 f9 w4 z* B, ]4 D) Z, l" e; C0 l/ g# K0 `. ]
7 I0 O  v8 _; @" ]3 i: x% Y, C其中,第二个循环语句C51编译后,就用DJNZ指令来完成,相当于如下指令:
2 _; J) Z  ?" H5 t( p9 d. \MOV 09H,#0FFH
) E4 b* h9 d8 r# y* }LOOP: DJNZ 09H,LOOP
0 ~, x3 E. {) P2 a) n. p! L+ m, z7 Y  d2 c5 }7 z' E$ x
7 s" I, T# s! E; O9 u) _6 p: f- V) n2 n, d5 ?
+ t5 m+ y! i, F指令相当简洁,也很好计算精确的延时时间。
6 d& f: y+ a5 D同样对do…while,while循环语句中,也是如此5 ~% |/ i2 N" Z
. w" D1 i1 [8 X* l% f0 x" \例:2 @* ]2 t0 {1 u* D
unsigned char n;8 Z6 f4 v! }$ }
  r( U* x* n* _* Cn=255;. j2 ?3 K. i; w. ^6 X) `' j& [
+ J" P& Z* a5 J5 Fdo{n--}
7 n; C2 L% a5 l' r; z& |$ _while(n);# q6 c* Y# N* N4 O# K
) {4 v1 f. m; W. H3 Y; g0 c9 ]
n=255;( O  t+ Q1 `# ]7 A
% l+ p6 D/ {2 ], |+ O: {( H, vwhile(n)
4 S3 E+ {5 ~% h0 J; |: @( \{n--};
# {' ^! P) x2 X: A2 O* }
9 ?+ @3 `9 Z. N2 M* T2 B% r, A9 g  `2 a2 R+ [/ _9 K$ Q2 d1 \
这两个循环语句经过C51编译之后,形成DJNZ来完成的方法,故其精确时间的计算也很方便。8 w6 {, V' N/ S& N) ?3 T
8 v* u4 g. V  W0 h! I6 c0 d8 k% \3 F
6 }1 A7 @3 U& G: U! _0 V  g& h' |& z" B/ y2 ?
8 Z6 M# N* }! G6 I6 T: P其三:对于要求精确延时时间更长,这时就要采用循环嵌套的方法来实现,因此,循环嵌套的方法常用于达到ms级的延时。对于循环语句同样可以采用for,do…while,while结构来完成,每个循环体内的变量仍然采用无符号字符变量。' }3 E/ o2 Z' u* J' P1 @$ v5 N4 q8 w% H* s6 D2 H9 C
& i4 z- i& s$ v, Z
4 b/ @2 L6 H' B( h1 U+ m$ |+ g1 m! a2 E9 F$ K/ q" @$ X- Q4 q+ j/ K
unsigned char i,j5 I5 i7 C" w+ B: Q3 O% p
+ {* Y- P- f* y% M0 o- h9 }0 g6 rfor(i=255;i>0;i--)$ D4 |6 W; A  O* X* z' A' G
. t% U0 g' L0 ?8 ]- r: pfor(j=255;j>0;j--);
/ O2 m1 s( V5 ?7 h( s2 Y, p1 A4 \$ V& _. ^" I$ _* D* h' f# L; V
unsigned char i,j9 v% t& ]7 u* C, ?3 a9 w! X& k4 }7 ?9 G: \7 H' W
i=255;
5 U6 o, \/ G0 ~* q! D/ ^9 sdo{j=255;* ^9 s) V: V1 @
do{j--}- i7 N+ e' u) r2 l6 D8 k+ K
while(j);: T3 ]- F) V' [& l4 W
i--;# l  i' \# l' D$ n. h  Z7 c
! O& m) [/ T1 N( T}( ]0 k$ o- S. R+ v( M
8 @0 |. \$ n" ?* l# e" I5 F& Xwhile(i);: J/ f- E( V( b4 ^* q+ H
( r0 V; O- t1 Y+ M- d, A7 b1 @
unsigned char i,j
8 T) h/ O! ^4 U4 T; z& h0 m+ p( hi=255;& q# D8 v5 M1 x# s2 k4 d
while(i)* |& [" Q* K% F+ f
1 f: w/ z5 N6 z) N{j=255;3 {, z2 G5 b" I/ X
while(j), u( L: Y3 O& w4 _& W" ~- p; x- `7 W! Y0 V0 j/ b) \
{j--};, u0 N* Z: [8 F4 T+ _7 W( e' B, m0 S
i--;8 U  S: t& j8 O. |/ Q1 Y" l5 D/ q7 @" X( h
}7 C5 T5 e0 [, q( x" N3 D& S: v$ J% ?% H  @
这三种方法都是用DJNZ指令嵌套实现循环的,由C51编译器用下面的指令组合来完成的( b& W3 m/ L$ E6 z. r9 [
- ~1 G7 ^. Y3 n/ ]. u7 d" G! H1 G. ~1 S$ S/ B0 s9 i# L+ t( ]4 _3 u* w% H0 O! A' n7 W

) Y, f3 L9 w' O; I
& n& L9 ~6 @* E6 X% Q" ^+ FMOV R7,#0FFH+ D5 b4 R9 `6 c6 _! e
# [9 v/ L6 ^' |( m8 e- x! TLOOP2: MOV R6,#0FFH
. c* l: `/ G/ D9 nLOOP1: DJNZ R6,LOOP1, Q3 R# E1 M/ j  C" T' f9 ^  t5 ?& J
; \; o, W' l  R4 B& d1 FDJNZ R7,LOOP2; z! N# F, `: t6 ?# h( H0 ]- u0 y% e4 U
这些指令的组合在汇编语言中采用DJNZ指令来做延时用,因此它的时间精确计算也是很简单,假上面变量i的初值为m,变量j的初值为n,则总延时时 间为:m×(n×T+T),其中T为DJNZ指令执行时间(DJNZ指令为双周期指令)。这里的+T为MOV这条指令所使用的时间。同样对于更长时间的延 时,可以采用多重循环来完成。' Z4 N  R4 L4 q) v3 E; V1 }2 o+ O
! F& U; M+ P$ ]1 ]) q7 V1 G6 E# i- W; ^* n; n! I+ ?# L
( ^& C" Q4 k  Y& Z" A, f9 E
8 Z5 z3 S* ~$ q9 b, @0 `4 A9 A) J1 y0 |$ n2 B3 K. j  `
只要在程序设计循环语句时注意以上几个问题。/ I8 j9 c: }$ x$ `" [9 x/ S, [: u! B# O; x# h8 {
( X0 ^$ P- y/ ^% L- S. C
1 e1 |( ?2 `1 R0 {0 d5 J  S4 y' N4 Z9 `1 s' O# C
下面给出有关在C51中延时子程序设计时要注意的问题# p) u' o! C' Z7 g* t
! m6 j# ]1 C/ k! j  \1、在C51中进行精确的延时子程序设计时,尽量不要或少在延时子程序中定义局部变量,所有的延时子程序中变量通过有参函数传递。
$ F# R% u  T  x1 P" F" E. I2 q% d" A: k5 l7 J$ f& O" `' m/ t
, P/ f% i2 u& n3 x: J  B7 Y* W/ L9 b; c: [3 V2 }( ~( v# ^$ p: @- ?3 B* \
2、在延时子程序设计时,采用do…while,结构做循环体要比for结构做循环体好。
! ?0 e6 I2 [* m( B1 J3 X% v
* L" l4 M( ^9 c  T9 w$ Q) x* s, [. U& [/ D0 A
0 r( b# }5 E4 ^+ I3 D+ A; i& @& C3、在延时子程序设计时,要进行循环体嵌套时,采用先内循环,再减减比先减减,再内循环要好。6 B" v0 K2 [; C! f$ y, D
: o# ]1 G$ y1 y7 ~$ K9 u0 w) J7 E$ r) i& v
- L& m3 ?8 h5 R  V6 D, q1 z
unsigned char delay(unsigned char i,unsigned char j,unsigned char k)8 S* e( z8 @  Q
8 E; G9 o! Y* [. W, L6 ~{unsigned char b,c;/ L9 {0 e- P3 k  l2 c
b="j";4 H! }; u1 z8 ?  e8 q/ o* _, {; u/ U9 \
c="k";3 D: V/ q6 t. Y! n$ z5 b. z$ }) y0 c! U7 n! }6 M2 D
do{+ K: o% r# y& f1 t3 v/ {0 F. i5 y& R
do{' }2 ?6 p% C; V) f/ R& Y
do{k--};' {9 |# w' C! K2 m1 r4 r
2 L' {( E- O5 I9 {/ Awhile(k);7 ?) z. F! s& Y# U" X/ c
0 ~* U, j" V# ~( @! Bk="c";
. y& S3 H" ]/ tj--;};  h) w$ y) g* ?- _$ H# K
, J& W4 [% }  ^0 d) |while(j);
; ?- L+ N# Y! D7 vj=b;, O1 r4 g% P% z$ J9 Q! R
2 h# j( U) r3 n" ui--;};& B! m: ^5 ?- Q$ c! I8 `5 G+ X
while(i);, v- p5 r. g5 O3 A. Y/ ^) @. E
, r+ @& U/ \3 V3 e% U}
3 ~9 c6 h2 n5 _- H) T这精确延时子程序就被C51编译为有下面的指令组合完成: z5 m* j* [0 }6 S% L" A( F4 q  R- j; X
- m1 _$ k6 i; e2 B
4 R# X5 {1 |* H8 M$ A4 A  n5 w. L, H, X8 @; X0 M! Y$ x1 t4 |
' u% _: _* J6 \  |$ F0 n! k
1 y1 v7 ^# }8 zdelay延时子程序如下:
! G, `* f4 C3 [MOV R6,05H
8 t$ T- J6 r' y: H) Q7 s, E% p2 DMOV R4,03H+ N4 W% c4 J$ V; e& h$ `  D; b. w, a* G6 L
C0012: DJNZ R3, C0012* G$ V" R$ {8 C: j9 h
4 E! h& |: J1 x% |MOV R3,04H5 d" w- s4 |/ s0 \  F
DJNZ R5, C0012. S5 Z( l  C# h
MOV R5,06H$ N+ ]# ?! L* q& B. j: r
' L2 y  b2 {% ]5 o( M# eDJNZ R7, C0012( u6 z  c4 k. l7 h* w6 [: b# t. c# a% s8 D, M7 Q4 I( X# r0 A) x
RET
& _+ y) m" U0 Q# H$ s假设参数变量i的初值为m,参数变量j的初值为n,参数变量k的初值为l,则总延时时间为:l×(n×(m×T+2T)+2T)+3T,其中T为 DJNZ和MOV指令执行的时间。当m=n=l时,精确延时为9T,最短;当m=n=l=256时,精确延时到16908803T,最长: g$ n$ C+ ?6 T4 d
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-24 06:06 , Processed in 0.125000 second(s), 24 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表